xtensa/sigdeliver: fix signal deliver when task is running

The Inter-Processor Interrupt that pauses the other CPU generates
a level-1 interrupt which sets the PS.EXCM. This level-1 interrupt
is treated as an Exception and the bit PS.EXCM bit is automatically
reset on return from Exception. However, this is not the case here
because we are changing the execution to the signal trampoline.
Restoring the PS register with the PS.EXCM bit set would cause any
other exception to deviate execution to the DEC (double exception
vector), avoiding it to be treated correctly. According to the
xtensa ISA: "The process of taking an interrupt does not clear
the interrupt request. The process does set PS.EXCM to 1, which
disables level-1 interrupts in the interrupt handler. Typically,
the PS.EXCM is reset to 0 by the handler, after it has set up the
stack frame and masked the interrupt." Clean the saved PS.EXCM to
1) avoid an exception from being properly treated and 2) avoid
interrupts to be masked while delivering the signal.
This commit is contained in:
Tiago Medicci Serrano 2023-04-12 14:48:01 -03:00 committed by Masayuki Ishikawa
parent b94cc5ff92
commit 869aee6a78
1 changed files with 25 additions and 0 deletions

View File

@ -287,6 +287,31 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.sigdeliver = sigdeliver;
tcb->xcp.saved_regs = tcb->xcp.regs;
/* The Inter-Processor Interrupt that pauses the other CPU
* generates a level-1 interrupt which sets the PS.EXCM.
* This level-1 interrupt is treated as an Exception and
* the bit PS.EXCM bit is automatically reset on return
* from Exception. However, this is not the case here
* because we are changing the execution to the signal
* trampoline. Restoring the PS register with PS.EXCM bit
* set would cause any other exception to deviate execution
* to the DEC (double exception vector), avoiding it to be
* treated correctly. According to xtensa ISA: "The process
* of taking an interrupt does not clear the interrupt
* request. The process does set PS.EXCM to 1, which
* disables level-1 interrupts in the interrupt handler.
* Typically, PS.EXCM is reset to 0 by the handler, after
* it has set up the stack frame and masked the interrupt."
* Clean the saved PS.EXCM to 1) avoid an exception from
* being properly treated and 2) avoid interrupts to be
* masked while delivering the signal.
*/
if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0)
{
tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK;
}
/* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has
* been delivered.