xtensa/asm2: Fix stack pointer during preemption spills
When returning into a different thread than we interrupted, we obviously need to spill all the existing register windows to make sure all their values are in the old thread's stack. But the code to do this forgot to reset the current stack pointer to the value it had at interrupt time (it was still pointing to the saved context below that), so the caller of the interrupted function was spilling to the wrong spot. This wouldn't show up as an instant failure, it would only happen when switching BACK to the improperly-spilled thread. And even then it would be a noop if the original interrupt handler was deep enough to have spilled that function naturally. In practice, this happened only in some instances on ESP-32 (which has more windowed registers than qemu) when interrupting the idle thread (which is very shallow) with a (very simple) timer interrupt. Trivial to see, hard to find. See https://github.com/zephyrproject-rtos/zephyr/issues/6346 for more detail. Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
6ce863763d
commit
bdac8d070f
1 changed files with 8 additions and 3 deletions
|
@ -297,12 +297,17 @@ _do_call_\@:
|
|||
* to restore to in A6 (the call4'd function's A2). If this
|
||||
* is not the same handle as we started with, we need to do a
|
||||
* register spill before restoring, for obvious reasons.
|
||||
* Remember to mask interrupts (which have been unmasked
|
||||
* during the handler execution) while we muck with the
|
||||
* windows. The restore will unmask them as needed.
|
||||
* Remember to restore the A1 stack pointer as it existed at
|
||||
* interrupt time so the caller of the interrupted function
|
||||
* spills to the right place. Also mask interrupts (which
|
||||
* have been unmasked during the handler execution) while we
|
||||
* muck with the windows. The restore will unmask them
|
||||
* correctly.
|
||||
*/
|
||||
beq a6, a1, _restore_\@
|
||||
rsil a0, XCHAL_NMILEVEL
|
||||
l32i a1, a1, 0
|
||||
addi a1, a1, BASE_SAVE_AREA_SIZE
|
||||
SPILL_ALL_WINDOWS
|
||||
mov a1, a6
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue