ARM: 8036/1: Enable IRQs before attempting to read user space in __und_usr
authorCatalin Marinas <catalin.marinas@arm.com>
Tue, 22 Apr 2014 15:14:29 +0000 (16:14 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 25 Apr 2014 11:06:38 +0000 (12:06 +0100)
The Undef abort handler in the kernel reads the undefined instruction
from user space. If the page table was modified from another CPU, the
user access could fail and do_page_fault() will be executed with
interrupts disabled. This can potentially deadlock on ARM11MPCore or on
Cortex-A15 with erratum 798181 workaround enabled (both implying IPI for
TLB maintenance with page table lock held).

This patch enables the IRQs in __und_usr before attempting to read the
instruction from user space.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Arun KS <getarunks@gmail.com>
Cc: Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ryan Mallon <rmallon@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/kernel/entry-armv.S
arch/arm/kernel/iwmmxt.S
arch/arm/mach-ep93xx/crunch-bits.S
arch/arm/vfp/entry.S

index 1879e8dd2acc18a7837f0eee71beb8241c1aa9c0..5fc897cf409b2182a9d3f60f5cb3e63c7ed84eed 100644 (file)
@@ -413,6 +413,11 @@ __und_usr:
        @
        adr     r9, BSYM(ret_from_exception)
 
+       @ IRQs must be enabled before attempting to read the instruction from
+       @ user space since that could cause a page/translation fault if the
+       @ page table was modified by another CPU.
+       enable_irq
+
        tst     r3, #PSR_T_BIT                  @ Thumb mode?
        bne     __und_usr_thumb
        sub     r4, r2, #4                      @ ARM instr at LR - 4
@@ -517,7 +522,7 @@ ENDPROC(__und_usr)
  *  r9  = normal "successful" return address
  *  r10 = this threads thread_info structure
  *  lr  = unrecognised instruction return address
- * IRQs disabled, FIQs enabled.
+ * IRQs enabled, FIQs enabled.
  */
        @
        @ Fall-through from Thumb-2 __und_usr
@@ -624,7 +629,6 @@ call_fpe:
 #endif
 
 do_fpe:
-       enable_irq
        ldr     r4, .LCfp
        add     r10, r10, #TI_FPSTATE           @ r10 = workspace
        ldr     pc, [r4]                        @ Call FP module USR entry point
@@ -652,8 +656,7 @@ __und_usr_fault_32:
        b       1f
 __und_usr_fault_16:
        mov     r1, #2
-1:     enable_irq
-       mov     r0, sp
+1:     mov     r0, sp
        adr     lr, BSYM(ret_from_exception)
        b       __und_fault
 ENDPROC(__und_usr_fault_32)
index fcb33a70a35f143e951a7879a6aa3c40e311d6fe..4bb029ea89170611919ef2414b99227753c6fd67 100644 (file)
@@ -62,7 +62,7 @@
  * r9  = ret_from_exception
  * lr  = undefined instr exit
  *
- * called from prefetch exception handler with interrupts disabled
+ * called from prefetch exception handler with interrupts enabled
  */
 
 ENTRY(iwmmxt_task_enable)
index eaa5e34729d333d22f5db2cf4db930f35d30dcbd..e96923a3017b16ddb92ce75437ad594f80ab1566 100644 (file)
@@ -63,7 +63,7 @@
  * r9  = ret_from_exception
  * lr  = undefined instr exit
  *
- * called from prefetch exception handler with interrupts disabled
+ * called from prefetch exception handler with interrupts enabled
  */
 ENTRY(crunch_task_enable)
        inc_preempt_count r10, r3
index f0759e70fb865b4d24370a46b58b37564e49f871..fe6ca574d0931dc93d5114f2995ae553e769242b 100644 (file)
 @  r9  = normal "successful" return address
 @  r10 = this threads thread_info structure
 @  lr  = unrecognised instruction return address
-@  IRQs disabled.
+@  IRQs enabled.
 @
 ENTRY(do_vfp)
        inc_preempt_count r10, r4
-       enable_irq
        ldr     r4, .LCvfp
        ldr     r11, [r10, #TI_CPU]     @ CPU number
        add     r10, r10, #TI_VFPSTATE  @ r10 = workspace