Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 20 Oct 2020 16:18:31 +0000 (09:18 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 20 Oct 2020 16:18:31 +0000 (09:18 -0700)
Pull ARM updates from Russell King:

 - handle inexact watchpoint addresses (Douglas Anderson)

 - decompressor serial debug cleanups (Linus Walleij)

 - update L2 cache prefetch bits (Guillaume Tucker)

 - add text offset and malloc size to the decompressor kexec data

* tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm:
  ARM: add malloc size to decompressor kexec size structure
  ARM: add TEXT_OFFSET to decompressor kexec image structure
  ARM: 9007/1: l2c: fix prefetch bits init in L2X0_AUX_CTRL using DT values
  ARM: 9010/1: uncompress: Print the location of appended DTB
  ARM: 9009/1: uncompress: Enable debug in head.S
  ARM: 9008/1: uncompress: Drop excess whitespace print
  ARM: 9006/1: uncompress: Wait for ready and busy in debug prints
  ARM: 9005/1: debug: Select flow control for all debug UARTs
  ARM: 9004/1: debug: Split waituart to CTS and TXRDY
  ARM: 9003/1: uncompress: Delete unused debug macros
  ARM: 8997/2: hw_breakpoint: Handle inexact watchpoint addresses

34 files changed:
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/debug.S
arch/arm/boot/compressed/head.S
arch/arm/boot/compressed/vmlinux.lds.S
arch/arm/include/debug/8250.S
arch/arm/include/debug/asm9260.S
arch/arm/include/debug/at91.S
arch/arm/include/debug/bcm63xx.S
arch/arm/include/debug/brcmstb.S
arch/arm/include/debug/clps711x.S
arch/arm/include/debug/dc21285.S
arch/arm/include/debug/digicolor.S
arch/arm/include/debug/efm32.S
arch/arm/include/debug/icedcc.S
arch/arm/include/debug/imx.S
arch/arm/include/debug/meson.S
arch/arm/include/debug/msm.S
arch/arm/include/debug/omap2plus.S
arch/arm/include/debug/pl01x.S
arch/arm/include/debug/renesas-scif.S
arch/arm/include/debug/sa1100.S
arch/arm/include/debug/samsung.S
arch/arm/include/debug/sirf.S
arch/arm/include/debug/sti.S
arch/arm/include/debug/stm32.S
arch/arm/include/debug/tegra.S
arch/arm/include/debug/vf.S
arch/arm/include/debug/vt8500.S
arch/arm/include/debug/zynq.S
arch/arm/kernel/debug.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/mm/cache-l2x0.c

index 80000a6..87912e5 100644 (file)
@@ -1546,6 +1546,17 @@ config DEBUG_SIRFSOC_UART
        bool
        depends on ARCH_SIRF
 
+config DEBUG_UART_FLOW_CONTROL
+       bool "Enable flow control (CTS) for the debug UART"
+       depends on DEBUG_LL
+       default y if ARCH_EBSA110 || DEBUG_FOOTBRIDGE_COM1 || DEBUG_GEMINI || ARCH_RPC
+       help
+         Some UART ports are connected to terminals that will use modem
+         control signals to indicate whether they are ready to receive text.
+         In practice this means that the terminal is asserting the special
+         control signal CTS (Clear To Send). If your debug UART supports
+         this and your debug terminal will require it, enable this option.
+
 config DEBUG_LL_INCLUDE
        string
        default "debug/sa1100.S" if DEBUG_SA1100
@@ -1893,11 +1904,6 @@ config DEBUG_UART_8250_PALMCHIP
          except for having a different register layout.  Say Y here if
          the debug UART is of this type.
 
-config DEBUG_UART_8250_FLOW_CONTROL
-       bool "Enable flow control for 8250 UART"
-       depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
-       default y if ARCH_EBSA110 || DEBUG_FOOTBRIDGE_COM1 || DEBUG_GEMINI || ARCH_RPC
-
 config DEBUG_UNCOMPRESS
        bool "Enable decompressor debugging via DEBUG_LL output"
        depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M
index e589da3..c430143 100644 (file)
@@ -143,6 +143,9 @@ head-y              := arch/arm/kernel/head$(MMUEXT).o
 
 # Text offset. This list is sorted numerically by address in order to
 # provide a means to avoid/resolve conflicts in multi-arch kernels.
+# Note: the 32kB below this value is reserved for use by the kernel
+# during boot, and this offset is critical to the functioning of
+# kexec-tools.
 textofs-y      := 0x00008000
 # We don't want the htc bootloader to corrupt kernel during resume
 textofs-$(CONFIG_PM_H1940)      := 0x00108000
index 58028ab..47f001c 100644 (file)
@@ -7,11 +7,11 @@
 
 OBJS           =
 
-AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
 HEAD   = head.o
 OBJS   += misc.o decompress.o
 ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y)
 OBJS   += debug.o
+AFLAGS_head.o += -DDEBUG
 endif
 FONTC  = $(srctree)/lib/fonts/font_acorn_8x8.c
 
@@ -68,7 +68,12 @@ ZTEXTADDR    := 0
 ZBSSADDR       := ALIGN(8)
 endif
 
+MALLOC_SIZE    := 65536
+
+AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) -DMALLOC_SIZE=$(MALLOC_SIZE)
 CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
+CPPFLAGS_vmlinux.lds += -DTEXT_OFFSET="$(TEXT_OFFSET)"
+CPPFLAGS_vmlinux.lds += -DMALLOC_SIZE="$(MALLOC_SIZE)"
 
 compress-$(CONFIG_KERNEL_GZIP) = gzip
 compress-$(CONFIG_KERNEL_LZO)  = lzo
index 6bf2917..fac40a7 100644 (file)
@@ -8,7 +8,10 @@
 
 ENTRY(putc)
        addruart r1, r2, r3
-       waituart r3, r1
+#ifdef CONFIG_DEBUG_UART_FLOW_CONTROL
+       waituartcts r3, r1
+#endif
+       waituarttxrdy r3, r1
        senduart r0, r1
        busyuart r3, r1
        mov      pc, lr
index 434a169..2e04ec5 100644 (file)
 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
                .macro  loadsp, rb, tmp1, tmp2
                .endm
-               .macro  writeb, ch, rb
+               .macro  writeb, ch, rb, tmp
                mcr     p14, 0, \ch, c0, c5, 0
                .endm
 #elif defined(CONFIG_CPU_XSCALE)
                .macro  loadsp, rb, tmp1, tmp2
                .endm
-               .macro  writeb, ch, rb
+               .macro  writeb, ch, rb, tmp
                mcr     p14, 0, \ch, c8, c0, 0
                .endm
 #else
                .macro  loadsp, rb, tmp1, tmp2
                .endm
-               .macro  writeb, ch, rb
+               .macro  writeb, ch, rb, tmp
                mcr     p14, 0, \ch, c1, c0, 0
                .endm
 #endif
 
 #include CONFIG_DEBUG_LL_INCLUDE
 
-               .macro  writeb, ch, rb
+               .macro  writeb, ch, rb, tmp
+#ifdef CONFIG_DEBUG_UART_FLOW_CONTROL
+               waituartcts \tmp, \rb
+#endif
+               waituarttxrdy \tmp, \rb
                senduart \ch, \rb
+               busyuart \tmp, \rb
                .endm
 
 #if defined(CONFIG_ARCH_SA1100)
                bl      phex
                .endm
 
-               .macro  debug_reloc_start
-#ifdef DEBUG
-               kputc   #'\n'
-               kphex   r6, 8           /* processor id */
-               kputc   #':'
-               kphex   r7, 8           /* architecture id */
-#ifdef CONFIG_CPU_CP15
-               kputc   #':'
-               mrc     p15, 0, r0, c1, c0
-               kphex   r0, 8           /* control reg */
-#endif
-               kputc   #'\n'
-               kphex   r5, 8           /* decompressed kernel start */
-               kputc   #'-'
-               kphex   r9, 8           /* decompressed kernel end  */
-               kputc   #'>'
-               kphex   r4, 8           /* kernel execution address */
-               kputc   #'\n'
-#endif
-               .endm
-
-               .macro  debug_reloc_end
-#ifdef DEBUG
-               kphex   r5, 8           /* end of kernel */
-               kputc   #'\n'
-               mov     r0, r4
-               bl      memdump         /* dump 256 bytes at start of kernel */
-#endif
-               .endm
-
                /*
                 * Debug kernel copy by printing the memory addresses involved
                 */
                .macro dbgkc, begin, end, cbegin, cend
 #ifdef DEBUG
-               kputc   #'\n'
                kputc   #'C'
                kputc   #':'
                kputc   #'0'
                kputc   #'x'
                kphex   \cend, 8        /* End of kernel copy */
                kputc   #'\n'
-               kputc   #'\r'
+#endif
+               .endm
+
+               /*
+                * Debug print of the final appended DTB location
+                */
+               .macro dbgadtb, begin, end
+#ifdef DEBUG
+               kputc   #'D'
+               kputc   #'T'
+               kputc   #'B'
+               kputc   #':'
+               kputc   #'0'
+               kputc   #'x'
+               kphex   \begin, 8       /* Start of appended DTB */
+               kputc   #' '
+               kputc   #'('
+               kputc   #'0'
+               kputc   #'x'
+               kphex   \end, 8         /* End of appended DTB */
+               kputc   #')'
+               kputc   #'\n'
 #endif
                .endm
 
@@ -303,7 +298,7 @@ restart:    adr     r0, LC1
 
 #ifndef CONFIG_ZBOOT_ROM
                /* malloc space is above the relocated stack (64k max) */
-               add     r10, sp, #0x10000
+               add     r10, sp, #MALLOC_SIZE
 #else
                /*
                 * With ZBOOT_ROM the bss/stack is non relocatable,
@@ -357,6 +352,7 @@ restart:    adr     r0, LC1
                mov     r5, r5, ror #8
                eor     r5, r5, r1, lsr #8
 #endif
+               dbgadtb r6, r5
                /* 50% DTB growth should be good enough */
                add     r5, r5, r5, lsr #1
                /* preserve 64-bit alignment */
@@ -614,7 +610,7 @@ not_relocated:      mov     r0, #0
  */
                mov     r0, r4
                mov     r1, sp                  @ malloc space above stack
-               add     r2, sp, #0x10000        @ 64k max
+               add     r2, sp, #MALLOC_SIZE    @ 64k max
                mov     r3, r7
                bl      decompress_kernel
 
@@ -1356,7 +1352,7 @@ puts:             loadsp  r3, r2, r1
 1:             ldrb    r2, [r0], #1
                teq     r2, #0
                moveq   pc, lr
-2:             writeb  r2, r3
+2:             writeb  r2, r3, r1
                mov     r1, #0x00020000
 3:             subs    r1, r1, #1
                bne     3b
index b914be3..1bcb68a 100644 (file)
@@ -44,10 +44,12 @@ SECTIONS
   }
   .table : ALIGN(4) {
     _table_start = .;
-    LONG(ZIMAGE_MAGIC(4))
+    LONG(ZIMAGE_MAGIC(6))
     LONG(ZIMAGE_MAGIC(0x5a534c4b))
     LONG(ZIMAGE_MAGIC(__piggy_size_addr - _start))
     LONG(ZIMAGE_MAGIC(_kernel_bss_size))
+    LONG(ZIMAGE_MAGIC(TEXT_OFFSET))
+    LONG(ZIMAGE_MAGIC(MALLOC_SIZE))
     LONG(0)
     _table_end = .;
   }
index e4a036f..e3692a3 100644 (file)
                bne     1002b
                .endm
 
-               .macro  waituart,rd,rx
-#ifdef CONFIG_DEBUG_UART_8250_FLOW_CONTROL
+               .macro  waituarttxrdy,rd,rx
+               .endm
+
+               .macro  waituartcts,rd,rx
 1001:          load    \rd, [\rx, #UART_MSR << UART_SHIFT]
                tst     \rd, #UART_MSR_CTS
                beq     1001b
-#endif
                .endm
index 0da1eb6..5a0ce14 100644 (file)
                ldr     \rv, = CONFIG_DEBUG_UART_VIRT
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituarttxrdy,rd,rx
+               .endm
+
+               .macro  waituartcts,rd,rx
                .endm
 
                .macro  senduart,rd,rx
index 6c91cba..1772282 100644 (file)
        strb    \rd, [\rx, #(AT91_DBGU_THR)]            @ Write to Transmitter Holding Register
        .endm
 
-       .macro  waituart,rd,rx
+       .macro  waituarttxrdy,rd,rx
 1001:  ldr     \rd, [\rx, #(AT91_DBGU_SR)]             @ Read Status Register
        tst     \rd, #AT91_DBGU_TXRDY                   @ DBGU_TXRDY = 1 when ready to transmit
        beq     1001b
        .endm
 
+       .macro  waituartcts,rd,rx
+       .endm
+
        .macro  busyuart,rd,rx
 1001:  ldr     \rd, [\rx, #(AT91_DBGU_SR)]             @ Read Status Register
        tst     \rd, #AT91_DBGU_TXEMPTY                 @ DBGU_TXEMPTY = 1 when transmission complete
index 06a8962..da65abb 100644 (file)
        strb    \rd, [\rx, #UART_FIFO_REG]
        .endm
 
-       .macro  waituart, rd, rx
+       .macro  waituarttxrdy, rd, rx
 1001:  ldr     \rd, [\rx, #UART_IR_REG]
        tst     \rd, #(1 << UART_IR_TXEMPTY)
        beq     1001b
        .endm
 
+       .macro  waituartcts, rd, rx
+       .endm
+
        .macro  busyuart, rd, rx
 1002:  ldr     \rd, [\rx, #UART_IR_REG]
        tst     \rd, #(1 << UART_IR_TXTRESH)
index 132a20c..7ffe669 100644 (file)
@@ -142,7 +142,10 @@ ARM_BE8(   rev     \rd, \rd )
                bne     1002b
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituarttxrdy,rd,rx
+               .endm
+
+               .macro  waituartcts,rd,rx
                .endm
 
 /*
index 774a67a..a983d12 100644 (file)
        ldr     \rp, =CLPS711X_UART_PADDR
        .endm
 
-       .macro  waituart,rd,rx
+       .macro  waituartcts,rd,rx
+       .endm
+
+       .macro  waituarttxrdy,rd,rx
        .endm
 
        .macro  senduart,rd,rx
index d7e8c71..4ec0e5e 100644 (file)
@@ -34,5 +34,8 @@
                bne     1001b
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
                .endm
index 256f5f4..443674c 100644 (file)
                strb    \rd, [\rx, #UA0_EMI_REC]
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
                .endm
 
        .macro  busyuart,rd,rx
index 5ed5028..b0083d6 100644 (file)
                strb    \rd, [\rx, #UARTn_TXDATA]
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
 1001:          ldr     \rd, [\rx, #UARTn_STATUS]
                tst     \rd, #UARTn_STATUS_TXBL
                beq     1001b
index 74a0dd0..d5e65da 100644 (file)
                beq     1001b
                .endm
 
-               .macro  waituart, rd, rx
+               .macro  waituartcts, rd, rx
+               .endm
+
+               .macro  waituarttxrdy, rd, rx
                mov     \rd, #0x2000000
 1001:
                subs    \rd, \rd, #1
                beq     1001b
                .endm
 
-               .macro  waituart, rd, rx
+               .macro  waituartcts, rd, rx
+               .endm
+
+               .macro  waituarttxrdy, rd, rx
                mov     \rd, #0x10000000
 1001:
                subs    \rd, \rd, #1
 
                .endm
 
-               .macro  waituart, rd, rx
+               .macro  waituartcts, rd, rx
+               .endm
+
+               .macro  waituarttxrdy, rd, rx
                mov     \rd, #0x2000000
 1001:
                subs    \rd, \rd, #1
index 1c1b9d1..bb7b955 100644 (file)
                str     \rd, [\rx, #0x40]       @ TXDATA
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
                .endm
 
                .macro  busyuart,rd,rx
index 1e501a0..7b60e44 100644 (file)
        beq     1002b
        .endm
 
-       .macro  waituart,rd,rx
+       .macro  waituartcts,rd,rx
+       .endm
+
+       .macro  waituarttxrdy,rd,rx
 1001:  ldr     \rd, [\rx, #MESON_AO_UART_STATUS]
        tst     \rd, #MESON_AO_UART_TX_FIFO_FULL
        bne     1001b
index 9405b71..530edc7 100644 (file)
@@ -17,7 +17,10 @@ ARM_BE8(rev  \rd, \rd )
        str     \rd, [\rx, #0x70]
        .endm
 
-       .macro  waituart, rd, rx
+       .macro  waituartcts,rd,rx
+       .endm
+
+       .macro  waituarttxrdy, rd, rx
        @ check for TX_EMT in UARTDM_SR
        ldr     \rd, [\rx, #0x08]
 ARM_BE8(rev     \rd, \rd )
index b5696a3..0680be6 100644 (file)
@@ -75,5 +75,8 @@ omap_uart_lsr:        .word   0
                bne     1001b
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
                .endm
index a2a553a..0c7bfa4 100644 (file)
                strb    \rd, [\rx, #UART01x_DR]
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
 1001:          ldr     \rd, [\rx, #UART01x_FR]
  ARM_BE8(      rev     \rd, \rd )
                tst     \rd, #UART01x_FR_TXFF
index 25f0666..8e433e9 100644 (file)
        ldr     \rv, =SCIF_VIRT
        .endm
 
-       .macro  waituart, rd, rx
+       .macro  waituartcts,rd,rx
+       .endm
+
+       .macro  waituarttxrdy, rd, rx
 1001:  ldrh    \rd, [\rx, #FSR]
        tst     \rd, #TDFE
        beq     1001b
index 6109e60..7968ea5 100644 (file)
                str     \rd, [\rx, #UTDR]
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
 1001:          ldr     \rd, [\rx, #UTSR1]
                tst     \rd, #UTSR1_TNF
                beq     1001b
index 69201d7..ab474d5 100644 (file)
@@ -69,7 +69,10 @@ ARM_BE8(rev \rd, \rd)
 1002:          @ exit busyuart
        .endm
 
-       .macro  waituart,rd,rx
+       .macro  waituartcts,rd,rx
+       .endm
+
+       .macro  waituarttxrdy,rd,rx
                ldr     \rd, [\rx, # S3C2410_UFCON]
 ARM_BE8(rev \rd, \rd)
                tst     \rd, #S3C2410_UFCON_FIFOMODE    @ fifo enabled?
index e73e4de..3612c7b 100644 (file)
        .macro  busyuart,rd,rx
        .endm
 
-       .macro  waituart,rd,rx
+       .macro  waituartcts,rd,rx
+       .endm
+
+       .macro  waituarttxrdy,rd,rx
 1001:  ldr     \rd, [\rx, #SIRF_LLUART_TXFIFO_STATUS]
        tst     \rd, #SIRF_LLUART_TXFIFO_EMPTY
        beq     1001b
index 6b42c91..72d0525 100644 (file)
                 strb    \rd, [\rx, #ASC_TX_BUF_OFF]
                 .endm
 
-                .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+                .macro  waituarttxrdy,rd,rx
 1001:           ldr     \rd, [\rx, #ASC_STA_OFF]
                 tst     \rd, #ASC_STA_TX_FULL
                 bne     1001b
index f3c4a37..b6d9df3 100644 (file)
        strb    \rd, [\rx, #STM32_USART_TDR_OFF]
 .endm
 
-.macro  waituart,rd,rx
+.macro waituartcts,rd,rx
+.endm
+
+.macro  waituarttxrdy,rd,rx
 1001:  ldr     \rd, [\rx, #(STM32_USART_SR_OFF)]       @ Read Status Register
        tst     \rd, #STM32_USART_TXE                   @ TXE = 1 = tx empty
        beq     1001b
index 2148d0f..98daa7f 100644 (file)
 1002:
                .endm
 
-               .macro  waituart, rd, rx
-#ifdef FLOW_CONTROL
+               .macro  waituartcts, rd, rx
                cmp     \rx, #0
                beq     1002f
 1001:          ldrb    \rd, [\rx, #UART_MSR << UART_SHIFT]
                tst     \rd, #UART_MSR_CTS
                beq     1001b
 1002:
-#endif
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
                .endm
 
 /*
index 854d9bd..035bcbf 100644 (file)
@@ -29,5 +29,8 @@
        beq     1001b                   @ wait until transmit done
        .endm
 
-       .macro  waituart,rd,rx
+       .macro  waituartcts,rd,rx
+       .endm
+
+       .macro  waituarttxrdy,rd,rx
        .endm
index 8dc1df2..d01094f 100644 (file)
        bne     1001b
        .endm
 
-       .macro  waituart,rd,rx
+       .macro  waituartcts,rd,rx
+       .endm
+
+       .macro  waituarttxrdy,rd,rx
        .endm
 
 #endif
index 58d77c9..5d42cc3 100644 (file)
                strb    \rd, [\rx, #UART_FIFO_OFFSET]   @ TXDATA
                .endm
 
-               .macro  waituart,rd,rx
+               .macro  waituartcts,rd,rx
+               .endm
+
+               .macro  waituarttxrdy,rd,rx
 1001:          ldr     \rd, [\rx, #UART_SR_OFFSET]
 ARM_BE8(       rev     \rd, \rd )
                tst     \rd, #UART_SR_TXEMPTY
index e112072..d92f44b 100644 (file)
@@ -89,11 +89,18 @@ ENTRY(printascii)
 2:             teq     r1, #'\n'
                bne     3f
                mov     r1, #'\r'
-               waituart r2, r3
+#ifdef CONFIG_DEBUG_UART_FLOW_CONTROL
+               waituartcts r2, r3
+#endif
+               waituarttxrdy r2, r3
                senduart r1, r3
                busyuart r2, r3
                mov     r1, #'\n'
-3:             waituart r2, r3
+3:
+#ifdef CONFIG_DEBUG_UART_FLOW_CONTROL
+               waituartcts r2, r3
+#endif
+               waituarttxrdy r2, r3
                senduart r1, r3
                busyuart r2, r3
                b       1b
index 7a4853b..08660ae 100644 (file)
@@ -683,6 +683,40 @@ static void disable_single_step(struct perf_event *bp)
        arch_install_hw_breakpoint(bp);
 }
 
+/*
+ * Arm32 hardware does not always report a watchpoint hit address that matches
+ * one of the watchpoints set. It can also report an address "near" the
+ * watchpoint if a single instruction access both watched and unwatched
+ * addresses. There is no straight-forward way, short of disassembling the
+ * offending instruction, to map that address back to the watchpoint. This
+ * function computes the distance of the memory access from the watchpoint as a
+ * heuristic for the likelyhood that a given access triggered the watchpoint.
+ *
+ * See this same function in the arm64 platform code, which has the same
+ * problem.
+ *
+ * The function returns the distance of the address from the bytes watched by
+ * the watchpoint. In case of an exact match, it returns 0.
+ */
+static u32 get_distance_from_watchpoint(unsigned long addr, u32 val,
+                                       struct arch_hw_breakpoint_ctrl *ctrl)
+{
+       u32 wp_low, wp_high;
+       u32 lens, lene;
+
+       lens = __ffs(ctrl->len);
+       lene = __fls(ctrl->len);
+
+       wp_low = val + lens;
+       wp_high = val + lene;
+       if (addr < wp_low)
+               return wp_low - addr;
+       else if (addr > wp_high)
+               return addr - wp_high;
+       else
+               return 0;
+}
+
 static int watchpoint_fault_on_uaccess(struct pt_regs *regs,
                                       struct arch_hw_breakpoint *info)
 {
@@ -692,23 +726,25 @@ static int watchpoint_fault_on_uaccess(struct pt_regs *regs,
 static void watchpoint_handler(unsigned long addr, unsigned int fsr,
                               struct pt_regs *regs)
 {
-       int i, access;
-       u32 val, ctrl_reg, alignment_mask;
+       int i, access, closest_match = 0;
+       u32 min_dist = -1, dist;
+       u32 val, ctrl_reg;
        struct perf_event *wp, **slots;
        struct arch_hw_breakpoint *info;
        struct arch_hw_breakpoint_ctrl ctrl;
 
        slots = this_cpu_ptr(wp_on_reg);
 
+       /*
+        * Find all watchpoints that match the reported address. If no exact
+        * match is found. Attribute the hit to the closest watchpoint.
+        */
+       rcu_read_lock();
        for (i = 0; i < core_num_wrps; ++i) {
-               rcu_read_lock();
-
                wp = slots[i];
-
                if (wp == NULL)
-                       goto unlock;
+                       continue;
 
-               info = counter_arch_bp(wp);
                /*
                 * The DFAR is an unknown value on debug architectures prior
                 * to 7.1. Since we only allow a single watchpoint on these
@@ -717,33 +753,31 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
                 */
                if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
                        BUG_ON(i > 0);
+                       info = counter_arch_bp(wp);
                        info->trigger = wp->attr.bp_addr;
                } else {
-                       if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
-                               alignment_mask = 0x7;
-                       else
-                               alignment_mask = 0x3;
-
-                       /* Check if the watchpoint value matches. */
-                       val = read_wb_reg(ARM_BASE_WVR + i);
-                       if (val != (addr & ~alignment_mask))
-                               goto unlock;
-
-                       /* Possible match, check the byte address select. */
-                       ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
-                       decode_ctrl_reg(ctrl_reg, &ctrl);
-                       if (!((1 << (addr & alignment_mask)) & ctrl.len))
-                               goto unlock;
-
                        /* Check that the access type matches. */
                        if (debug_exception_updates_fsr()) {
                                access = (fsr & ARM_FSR_ACCESS_MASK) ?
                                          HW_BREAKPOINT_W : HW_BREAKPOINT_R;
                                if (!(access & hw_breakpoint_type(wp)))
-                                       goto unlock;
+                                       continue;
                        }
 
+                       val = read_wb_reg(ARM_BASE_WVR + i);
+                       ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
+                       decode_ctrl_reg(ctrl_reg, &ctrl);
+                       dist = get_distance_from_watchpoint(addr, val, &ctrl);
+                       if (dist < min_dist) {
+                               min_dist = dist;
+                               closest_match = i;
+                       }
+                       /* Is this an exact match? */
+                       if (dist != 0)
+                               continue;
+
                        /* We have a winner. */
+                       info = counter_arch_bp(wp);
                        info->trigger = addr;
                }
 
@@ -765,13 +799,23 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
                 * we can single-step over the watchpoint trigger.
                 */
                if (!is_default_overflow_handler(wp))
-                       goto unlock;
-
+                       continue;
 step:
                enable_single_step(wp, instruction_pointer(regs));
-unlock:
-               rcu_read_unlock();
        }
+
+       if (min_dist > 0 && min_dist != -1) {
+               /* No exact match found. */
+               wp = slots[closest_match];
+               info = counter_arch_bp(wp);
+               info->trigger = addr;
+               pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+               perf_bp_event(wp, regs);
+               if (is_default_overflow_handler(wp))
+                       enable_single_step(wp, instruction_pointer(regs));
+       }
+
+       rcu_read_unlock();
 }
 
 static void watchpoint_single_step_handler(unsigned long pc)
index 12c26eb..43d91bf 100644 (file)
@@ -1249,20 +1249,28 @@ static void __init l2c310_of_parse(const struct device_node *np,
 
        ret = of_property_read_u32(np, "prefetch-data", &val);
        if (ret == 0) {
-               if (val)
+               if (val) {
                        prefetch |= L310_PREFETCH_CTRL_DATA_PREFETCH;
-               else
+                       *aux_val |= L310_PREFETCH_CTRL_DATA_PREFETCH;
+               } else {
                        prefetch &= ~L310_PREFETCH_CTRL_DATA_PREFETCH;
+                       *aux_val &= ~L310_PREFETCH_CTRL_DATA_PREFETCH;
+               }
+               *aux_mask &= ~L310_PREFETCH_CTRL_DATA_PREFETCH;
        } else if (ret != -EINVAL) {
                pr_err("L2C-310 OF prefetch-data property value is missing\n");
        }
 
        ret = of_property_read_u32(np, "prefetch-instr", &val);
        if (ret == 0) {
-               if (val)
+               if (val) {
                        prefetch |= L310_PREFETCH_CTRL_INSTR_PREFETCH;
-               else
+                       *aux_val |= L310_PREFETCH_CTRL_INSTR_PREFETCH;
+               } else {
                        prefetch &= ~L310_PREFETCH_CTRL_INSTR_PREFETCH;
+                       *aux_val &= ~L310_PREFETCH_CTRL_INSTR_PREFETCH;
+               }
+               *aux_mask &= ~L310_PREFETCH_CTRL_INSTR_PREFETCH;
        } else if (ret != -EINVAL) {
                pr_err("L2C-310 OF prefetch-instr property value is missing\n");
        }