arm: Enable IRQs before attempting to read user space in __und_usr
Catalin Marinas [Tue, 20 Aug 2013 17:37:02 +0000 (18:37 +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>
Signed-off-by: Bharat Nihalani <bnihalani@nvidia.com>
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Change-Id: Ie5164d8ada9646d723b2b6ef65797e9307718292
Reviewed-on: http://git-master/r/264300
(cherry picked from commit 099ae886a528059cdda926ce1701caaaeaa9e0e8)
Reviewed-on: http://git-master/r/270036
GVS: Gerrit_Virtual_Submit

arch/arm/kernel/entry-armv.S

index d43c7e5..eff4193 100644 (file)
@@ -411,6 +411,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
@@ -514,7 +519,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
@@ -621,7 +626,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
@@ -649,8 +653,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)