summaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/entry.S
diff options
context:
space:
mode:
authorMarc Gauthier <marc@tensilica.com>2013-01-05 04:57:17 +0400
committerChris Zankel <chris@zankel.net>2013-02-23 19:12:52 -0800
commit2d1c645cc50b8f5a718b24bad9eb3931e7105d12 (patch)
treec385e5064cee10f79b9c359ddd99bd5d1b9f838a /arch/xtensa/kernel/entry.S
parentd0b73b488c55df905ea8faaad079f8535629ed26 (diff)
xtensa: dispatch medium-priority interrupts
Add support for dispatching medium-priority interrupts, that is, interrupts of priority levels 2 to EXCM_LEVEL. IRQ handling may be preempted by higher priority IRQ. Signed-off-by: Marc Gauthier <marc@tensilica.com> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa/kernel/entry.S')
-rw-r--r--arch/xtensa/kernel/entry.S55
1 files changed, 44 insertions, 11 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 3777fec85e7..0ace2acbbad 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -7,7 +7,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2004-2007 by Tensilica Inc.
+ * Copyright (C) 2004 - 2008 by Tensilica Inc.
*
* Chris Zankel <chris@zankel.net>
*
@@ -349,15 +349,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 if PS.INTLEVEL was not set to 1 before
- * (interrupts disabled) and if this exception is not an interrupt.
+ * (*) We only allow interrupts of higher priority than current IRQ
*/
rsr a3, ps
addi a0, a0, -4
movi a2, 1
- extui a3, a3, 0, 1 # a3 = PS.INTLEVEL[0]
- moveqz a3, a2, a0 # a3 = 1 iff interrupt exception
+ 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
movi a2, 1 << PS_WOE_BIT
or a3, a3, a2
rsr a0, exccause
@@ -641,19 +642,51 @@ 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
- _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
+ l32i a0, a1, PT_AREG0
+ l32i a1, a1, PT_AREG1
+ rfde
+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
- rfe
+ rfi \level
+ .endif
+ .endm
-1: wsr a0, depc
+ .align 16
+2:
l32i a0, a1, PT_AREG0
l32i a1, a1, PT_AREG1
- rfde
+ 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
ENDPROC(kernel_exception)
@@ -753,7 +786,7 @@ ENTRY(unrecoverable_exception)
wsr a1, windowbase
rsync
- movi a1, (1 << PS_WOE_BIT) | 1
+ movi a1, (1 << PS_WOE_BIT) | LOCKLEVEL
wsr a1, ps
rsync
@@ -1474,7 +1507,7 @@ ENTRY(_spill_registers)
l32i a1, a3, EXC_TABLE_KSTK
wsr a3, excsave1
- movi a4, (1 << PS_WOE_BIT) | 1
+ movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL
wsr a4, ps
rsync