aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2014-04-22 11:14:29 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-04-25 07:06:38 -0400
commit1417a6b8dc4db73055be9a3aa288b050e9dc06ab (patch)
tree82fe7a3cb59ff82ddb74a8ebc6ff2d2e9237733b
parentbc94081c6ac823c4723d8e36e9604c6cf3eba0ef (diff)
ARM: 8036/1: Enable IRQs before attempting to read user space in __und_usr
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>
-rw-r--r--arch/arm/kernel/entry-armv.S11
-rw-r--r--arch/arm/kernel/iwmmxt.S2
-rw-r--r--arch/arm/mach-ep93xx/crunch-bits.S2
-rw-r--r--arch/arm/vfp/entry.S3
4 files changed, 10 insertions, 8 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 1879e8dd2acc..5fc897cf409b 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -413,6 +413,11 @@ __und_usr:
413 @ 413 @
414 adr r9, BSYM(ret_from_exception) 414 adr r9, BSYM(ret_from_exception)
415 415
416 @ IRQs must be enabled before attempting to read the instruction from
417 @ user space since that could cause a page/translation fault if the
418 @ page table was modified by another CPU.
419 enable_irq
420
416 tst r3, #PSR_T_BIT @ Thumb mode? 421 tst r3, #PSR_T_BIT @ Thumb mode?
417 bne __und_usr_thumb 422 bne __und_usr_thumb
418 sub r4, r2, #4 @ ARM instr at LR - 4 423 sub r4, r2, #4 @ ARM instr at LR - 4
@@ -517,7 +522,7 @@ ENDPROC(__und_usr)
517 * r9 = normal "successful" return address 522 * r9 = normal "successful" return address
518 * r10 = this threads thread_info structure 523 * r10 = this threads thread_info structure
519 * lr = unrecognised instruction return address 524 * lr = unrecognised instruction return address
520 * IRQs disabled, FIQs enabled. 525 * IRQs enabled, FIQs enabled.
521 */ 526 */
522 @ 527 @
523 @ Fall-through from Thumb-2 __und_usr 528 @ Fall-through from Thumb-2 __und_usr
@@ -624,7 +629,6 @@ call_fpe:
624#endif 629#endif
625 630
626do_fpe: 631do_fpe:
627 enable_irq
628 ldr r4, .LCfp 632 ldr r4, .LCfp
629 add r10, r10, #TI_FPSTATE @ r10 = workspace 633 add r10, r10, #TI_FPSTATE @ r10 = workspace
630 ldr pc, [r4] @ Call FP module USR entry point 634 ldr pc, [r4] @ Call FP module USR entry point
@@ -652,8 +656,7 @@ __und_usr_fault_32:
652 b 1f 656 b 1f
653__und_usr_fault_16: 657__und_usr_fault_16:
654 mov r1, #2 658 mov r1, #2
6551: enable_irq 6591: mov r0, sp
656 mov r0, sp
657 adr lr, BSYM(ret_from_exception) 660 adr lr, BSYM(ret_from_exception)
658 b __und_fault 661 b __und_fault
659ENDPROC(__und_usr_fault_32) 662ENDPROC(__und_usr_fault_32)
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index fcb33a70a35f..4bb029ea8917 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -62,7 +62,7 @@
62 * r9 = ret_from_exception 62 * r9 = ret_from_exception
63 * lr = undefined instr exit 63 * lr = undefined instr exit
64 * 64 *
65 * called from prefetch exception handler with interrupts disabled 65 * called from prefetch exception handler with interrupts enabled
66 */ 66 */
67 67
68ENTRY(iwmmxt_task_enable) 68ENTRY(iwmmxt_task_enable)
diff --git a/arch/arm/mach-ep93xx/crunch-bits.S b/arch/arm/mach-ep93xx/crunch-bits.S
index eaa5e34729d3..e96923a3017b 100644
--- a/arch/arm/mach-ep93xx/crunch-bits.S
+++ b/arch/arm/mach-ep93xx/crunch-bits.S
@@ -63,7 +63,7 @@
63 * r9 = ret_from_exception 63 * r9 = ret_from_exception
64 * lr = undefined instr exit 64 * lr = undefined instr exit
65 * 65 *
66 * called from prefetch exception handler with interrupts disabled 66 * called from prefetch exception handler with interrupts enabled
67 */ 67 */
68ENTRY(crunch_task_enable) 68ENTRY(crunch_task_enable)
69 inc_preempt_count r10, r3 69 inc_preempt_count r10, r3
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index f0759e70fb86..fe6ca574d093 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -22,11 +22,10 @@
22@ r9 = normal "successful" return address 22@ r9 = normal "successful" return address
23@ r10 = this threads thread_info structure 23@ r10 = this threads thread_info structure
24@ lr = unrecognised instruction return address 24@ lr = unrecognised instruction return address
25@ IRQs disabled. 25@ IRQs enabled.
26@ 26@
27ENTRY(do_vfp) 27ENTRY(do_vfp)
28 inc_preempt_count r10, r4 28 inc_preempt_count r10, r4
29 enable_irq
30 ldr r4, .LCvfp 29 ldr r4, .LCvfp
31 ldr r11, [r10, #TI_CPU] @ CPU number 30 ldr r11, [r10, #TI_CPU] @ CPU number
32 add r10, r10, #TI_VFPSTATE @ r10 = workspace 31 add r10, r10, #TI_VFPSTATE @ r10 = workspace