diff --git a/arch/xtensa/include/xtensa_asm2_s.h b/arch/xtensa/include/xtensa_asm2_s.h index 40b61c2013d..a6c57cd1e03 100644 --- a/arch/xtensa/include/xtensa_asm2_s.h +++ b/arch/xtensa/include/xtensa_asm2_s.h @@ -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_\@: * 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_\@: * 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