mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-09-10 06:29:32 +00:00
esp32s3: fix register-window corruption under interrupt load
Remove the C3 bluetooth hook addresses from esp32s3.ld (on the S3 they point into the ROM md5/crc thunk table, and being bare assignments they also shadowed the blob's own definitions), keep the interrupt frame clear of the 16-byte windowed-ABI save area below SP, and make tinygo_swapTask hold INTLEVEL across the stack switch while keeping the running frame's WINDOWSTART bit set. Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
//go:build tinygo
|
||||
|
||||
// See Xtensa ISA Reference Manual for details.
|
||||
// https://www.cadence.com/content/dam/cadence-www/global/en_US/documents/tools/silicon-solutions/compute-ip/isa-summary.pdf
|
||||
|
||||
.section .text.tinygo_startTask,"ax",@progbits
|
||||
.global tinygo_startTask
|
||||
.type tinygo_startTask, %function
|
||||
@@ -68,14 +71,12 @@ tinygo_swapTask:
|
||||
|
||||
// After the recursive spill returns, the physical register file still
|
||||
// has WindowStart bits set for the spill helper frames.
|
||||
// We will clear WindowStart completely (to 0) right before the retw.n
|
||||
// below, after the stack switch is done. This prevents stale overflow
|
||||
// when the new goroutine's calls rotate back into these panes.
|
||||
// These are dropped below, once the stack switch is done.
|
||||
|
||||
// Restore interrupts.
|
||||
l32i a4, sp, 4 // reload saved PS
|
||||
wsr.ps a4
|
||||
rsync
|
||||
// Mask interrupts until WindowStart matches the new stack, or one lands in
|
||||
// the gap and clobbers the a0-a3 that retw.n reloads.
|
||||
// Xtensa ISA Reference Manual, RETW, section 8.3.253, p.565.
|
||||
l32i a4, sp, 4 // reload saved PS, restored below
|
||||
|
||||
// At this point, the following is true:
|
||||
// WindowStart == 1 << WindowBase
|
||||
@@ -97,16 +98,20 @@ tinygo_swapTask:
|
||||
// register also stores the parent register window.
|
||||
l32i.n a0, sp, 0
|
||||
|
||||
// Clear ALL WindowStart bits. With all windows spilled to the stack,
|
||||
// we must ensure no stale WS bits remain: the retw.n below will trigger
|
||||
// underflow4 to load the new goroutine's registers from the new stack
|
||||
// (which sets the appropriate WS bit via rfwu). Any stale WS bits
|
||||
// (from spill helpers or the old goroutine) would cause spurious
|
||||
// overflows of garbage register values into memory.
|
||||
movi a5, 0
|
||||
// Drop every WindowStart bit but this window's: stale bits overflow garbage,
|
||||
// and an all-zero WindowStart marks the running frame dead.
|
||||
// Xtensa ISA Reference Manual, WINDOWSTART (SR 73), Table 5-148.
|
||||
rsr a6, WINDOWBASE
|
||||
movi a5, 1
|
||||
ssl a6
|
||||
sll a5, a5 // a5 = 1 << WindowBase
|
||||
wsr a5, WINDOWSTART
|
||||
rsync
|
||||
|
||||
// Window state now matches the new stack, so unmask interrupts.
|
||||
wsr.ps a4
|
||||
rsync
|
||||
|
||||
// Return into the new stack. This instruction will trigger a window
|
||||
// underflow, reloading the saved registers from the stack.
|
||||
retw.n
|
||||
|
||||
@@ -9,7 +9,7 @@ package task
|
||||
// a7: stack frame pointer (optional, normally unused in TinyGo)
|
||||
// Sources:
|
||||
// http://cholla.mmto.org/esp8266/xtensa.html
|
||||
// https://0x04.net/~mwk/doc/xtensa.pdf
|
||||
// https://www.cadence.com/content/dam/cadence-www/global/en_US/documents/tools/silicon-solutions/compute-ip/isa-summary.pdf
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
Reference in New Issue
Block a user