summaryrefslogtreecommitdiffstats
path: root/arch/xtensa
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2013-08-26 15:12:58 +0400
committerChris Zankel <chris@zankel.net>2013-09-06 09:46:35 -0700
commitaea8e7c80ab50305257838bfb04f91a76cf9fec7 (patch)
tree9fc08e6ec839f35c3f1c27398e6c67ae108594dc /arch/xtensa
parent0bc2ba94a65d2cd2ad01004d2d3f94f31c6064bd (diff)
xtensa: check thread flags atomically on return from user exception
Check pending signals and rescheduling thread flags with interrupts disabled, and don't enable them if no flags are set. Call trace_hardirqs_on after thread flags handling, so that rescheduling is done and hardirqs tracking flag is updated in the correct task context. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa')
-rw-r--r--arch/xtensa/kernel/entry.S39
1 files changed, 21 insertions, 18 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 9298742f0fd..03709ef2f3c 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -423,29 +423,14 @@ common_exception:
.global common_exception_return
common_exception_return:
-#ifdef CONFIG_TRACE_IRQFLAGS
- l32i a4, a1, PT_DEPC
- /* Double exception means we came here with an exception
- * while PS.EXCM was set, i.e. interrupts disabled.
- */
- bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
- l32i a4, a1, PT_EXCCAUSE
- bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
- /* We came here with an interrupt means interrupts were enabled
- * and we'll reenable them on return.
- */
- movi a4, trace_hardirqs_on
- callx4 a4
1:
-#endif
+ rsil a2, LOCKLEVEL
/* Jump if we are returning from kernel exceptions. */
-1: l32i a3, a1, PT_PS
+ l32i a3, a1, PT_PS
_bbci.l a3, PS_UM_BIT, 4f
- rsil a2, 0
-
/* Specific to a user exception exit:
* We need to check some flags for signal handling and rescheduling,
* and have to restore WB and WS, extra states, and all registers
@@ -465,6 +450,7 @@ common_exception_return:
/* Call do_signal() */
+ rsil a2, 0
movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*)
mov a6, a1
callx4 a4
@@ -472,6 +458,7 @@ common_exception_return:
3: /* Reschedule */
+ rsil a2, 0
movi a4, schedule # void schedule (void)
callx4 a4
j 1b
@@ -483,7 +470,23 @@ common_exception_return:
movi a4, check_tlb_sanity
callx4 a4
#endif
-4: /* Restore optional registers. */
+4:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ l32i a4, a1, PT_DEPC
+ /* Double exception means we came here with an exception
+ * while PS.EXCM was set, i.e. interrupts disabled.
+ */
+ bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
+ l32i a4, a1, PT_EXCCAUSE
+ bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
+ /* We came here with an interrupt means interrupts were enabled
+ * and we'll reenable them on return.
+ */
+ movi a4, trace_hardirqs_on
+ callx4 a4
+1:
+#endif
+ /* Restore optional registers. */
load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT