summaryrefslogtreecommitdiff
path: root/arch/xtensa/kernel/entry.S
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-09 14:38:16 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-09 14:38:16 -0700
commitc61c48dfe00907007df3b87e4ed271a5c143bdda (patch)
tree6d26bd3a8b4aa3cf35cad35fa27d1e0afe715db3 /arch/xtensa/kernel/entry.S
parente30f4192456971623b40c97a027346b69457ef69 (diff)
parentb341d84c8ac5ecbf7aa0b3ccd0745d87e881953c (diff)
Merge tag 'xtensa-next-20130508' of git://github.com/czankel/xtensa-linux
Pull xtensa updates from Chris Zankel: "Support for the latest MMU architecture that allows for a larger accessible memory region, and various bug-fixes" * tag 'xtensa-next-20130508' of git://github.com/czankel/xtensa-linux: xtensa: Switch to asm-generic/linkage.h xtensa: fix redboot load address xtensa: ISS: fix timer_lock usage in rs_open xtensa: disable IRQs while IRQ handler is running xtensa: enable lockdep support xtensa: fix arch_irqs_disabled_flags implementation xtensa: add irq flags trace support xtensa: provide custom CALLER_ADDR* implementations xtensa: add stacktrace support xtensa: clean up stpill_registers xtensa: don't use a7 in simcalls xtensa: don't attempt to use unconfigured timers xtensa: provide default platform_pcibios_init implementation xtensa: remove KCORE_ELF again xtensa: document MMUv3 setup sequence xtensa: add MMU v3 support xtensa: fix ibreakenable register update xtensa: fix oprofile building as module
Diffstat (limited to 'arch/xtensa/kernel/entry.S')
-rw-r--r--arch/xtensa/kernel/entry.S84
1 files changed, 43 insertions, 41 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 63845f950792..5082507d5631 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -354,16 +354,16 @@ common_exception:
* so we can allow exceptions and interrupts (*) again.
* Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
*
- * (*) We only allow interrupts of higher priority than current IRQ
+ * (*) We only allow interrupts if they were previously enabled and
+ * we're not handling an IRQ
*/
rsr a3, ps
- addi a0, a0, -4
- movi a2, 1
+ addi a0, a0, -EXCCAUSE_LEVEL1_INTERRUPT
+ movi a2, LOCKLEVEL
extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
# a3 = PS.INTLEVEL
- movnez a2, a3, a3 # a2 = 1: level-1, > 1: high priority
- moveqz a3, a2, a0 # a3 = IRQ level iff interrupt
+ moveqz a3, a2, a0 # a3 = LOCKLEVEL iff interrupt
movi a2, 1 << PS_WOE_BIT
or a3, a3, a2
rsr a0, exccause
@@ -389,6 +389,22 @@ common_exception:
save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
+#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've just disabled them.
+ */
+ movi a4, trace_hardirqs_off
+ callx4 a4
+1:
+#endif
+
/* Go to second-level dispatcher. Set up parameters to pass to the
* exception handler and call the exception handler.
*/
@@ -407,11 +423,29 @@ 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
+
/* Jump if we are returning from kernel exceptions. */
1: 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
@@ -652,51 +686,19 @@ common_exception_exit:
l32i a0, a1, PT_DEPC
l32i a3, a1, PT_AREG3
- _bltui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
-
- wsr a0, depc
l32i a2, a1, PT_AREG2
- l32i a0, a1, PT_AREG0
- l32i a1, a1, PT_AREG1
- rfde
+ _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
-1:
/* Restore a0...a3 and return */
- rsr a0, ps
- extui a2, a0, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
- movi a0, 2f
- slli a2, a2, 4
- add a0, a2, a0
- l32i a2, a1, PT_AREG2
- jx a0
-
- .macro irq_exit_level level
- .align 16
- .if XCHAL_EXCM_LEVEL >= \level
- l32i a0, a1, PT_PC
- wsr a0, epc\level
l32i a0, a1, PT_AREG0
l32i a1, a1, PT_AREG1
- rfi \level
- .endif
- .endm
+ rfe
- .align 16
-2:
+1: wsr a0, depc
l32i a0, a1, PT_AREG0
l32i a1, a1, PT_AREG1
- rfe
-
- .align 16
- /* no rfi for level-1 irq, handled by rfe above*/
- nop
-
- irq_exit_level 2
- irq_exit_level 3
- irq_exit_level 4
- irq_exit_level 5
- irq_exit_level 6
+ rfde
ENDPROC(kernel_exception)