Browse Source

xtensa: rework IRQ masking during IRQ entrance

Before cross stack call is setup correctly, we cannot allow
interrupts to be triggered or it may interfere with register
window spilling since we are clobbering registers needed for
that to work. However, there was a brief period where higher
level interrupts could fire due to code writing to PS with
lowered interrupt mask before raising it again. So rework
that part to avoid writing PS with intermediate value, and
now we mask interrupt until everything is setup correctly
before interrupt is enabled again.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
pull/88739/head
Daniel Leung 4 months ago committed by Benjamin Cabé
parent
commit
3f8e4d7400
  1. 49
      arch/xtensa/include/xtensa_asm2_s.h

49
arch/xtensa/include/xtensa_asm2_s.h

@ -373,6 +373,23 @@ _xstack_returned_\@: @@ -373,6 +373,23 @@ _xstack_returned_\@:
wur.THREADPTR a0
#endif /* XCHAL_HAVE_THREADPTR && CONFIG_USERSPACE */
/* Setting up the cross stack call below has states where the
* resulting frames are invalid/non-reentrant, so we can't
* allow nested interrupts. But we do need EXCM unmasked, as
* we use CALL/ENTRY instructions in the process and need to
* handle exceptions to spill caller/interruptee frames. Use
* PS.INTLEVEL at maximum to mask all interrupts and stash the
* current value in our designated EPS register (which is
* guaranteed unused across the call)
*/
rsil a0, 0xf
/* Since we are unmasking EXCM, we need to set RING bits to kernel
* mode, otherwise we won't be able to run the exception handler in C.
*/
movi a3, ~(PS_EXCM_MASK) & ~(PS_RING_MASK)
and a0, a0, a3
#ifdef CONFIG_XTENSA_INTERRUPT_NONPREEMPTABLE
/* Setting the interrupt mask to the max non-debug level
@ -380,12 +397,11 @@ _xstack_returned_\@: @@ -380,12 +397,11 @@ _xstack_returned_\@:
* high level interrupts until processing of that lower level
* interrupt has completed.
*/
rsr.ps a0
movi a3, ~(PS_INTLEVEL_MASK)
and a0, a0, a3
movi a3, PS_INTLEVEL(ZSR_RFI_LEVEL)
or a0, a0, a3
wsr.ps a0
wsr.ZSR_EPS a0
#else
@ -401,35 +417,20 @@ _xstack_returned_\@: @@ -401,35 +417,20 @@ _xstack_returned_\@:
* argument and expand two versions of this handler. An
* optimization FIXME, I guess.
*/
rsr.ps a0
movi a3, PS_INTLEVEL_MASK
and a0, a0, a3
bnez a0, _not_l1
rsr.ps a0
and a3, a0, a3
bnez a3, _not_l1
/* interrupt masking is zero, so no need to zero it before OR-ing. */
movi a3, PS_INTLEVEL(1)
or a0, a0, a3
wsr.ps a0
_not_l1:
wsr.ZSR_EPS a0
#endif /* CONFIG_XTENSA_INTERRUPT_NONPREEMPTABLE */
/* Setting up the cross stack call below has states where the
* resulting frames are invalid/non-reentrant, so we can't
* allow nested interrupts. But we do need EXCM unmasked, as
* we use CALL/ENTRY instructions in the process and need to
* handle exceptions to spill caller/interruptee frames. Use
* PS.INTLEVEL at maximum to mask all interrupts and stash the
* current value in our designated EPS register (which is
* guaranteed unused across the call)
*/
rsil a0, 0xf
/* Since we are unmasking EXCM, we need to set RING bits to kernel
* mode, otherwise we won't be able to run the exception handler in C.
*/
movi a3, ~(PS_EXCM_MASK) & ~(PS_RING_MASK)
and a0, a0, a3
wsr.ZSR_EPS a0
movi a3, PS_INTLEVEL(0xf)
or a0, a0, a3
wsr.ps a0
rsync

Loading…
Cancel
Save