Skip to content

Commit de0c9a2

Browse files
committed
esp32: handle the alloca exception
MOVSP raises AllocaCause (EXCCAUSE 5) when the caller register window is not yet spilled. This is a request to spill, not a fault, but the handler treated every cause other than 4 as fatal and stopped the chip. The Bluetooth controller blob is the first code on this chip that uses MOVSP. Without this change btdm_controller_init stops with "EXC 00000005" as soon as the blob creates its controller task. _xt_alloca_exc rotates back to the caller window and enters the matching window underflow routine, which does the spill and returns to the MOVSP. The ESP32-S3 already has the same handler.
1 parent 9d00e05 commit de0c9a2

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

targets/esp32-interrupts.S

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,15 @@ _handle_kernel_exc:
258258

259259
.global _handle_level1
260260
_handle_level1:
261+
// EXCCAUSE 5 (AllocaCause) is a MOVSP window-spill request, not a fault, so
262+
// it is checked before any state is touched: a0 is still in EXCSAVE1.
263+
// Xtensa ISA Reference Manual, Table 4-64 "Exception Causes".
264+
rsr a0, EXCCAUSE
265+
bnei a0, 5, 1f
266+
j _xt_alloca_exc
267+
1:
268+
rsr a0, EXCSAVE1 // restore a0 clobbered by the EXCCAUSE read
269+
261270
// --- allocate 96-byte exception frame on the interrupted stack ---
262271
// Layout (offsets from a1 after adjustment):
263272
// 0: a0 4: a1(orig) 8: a2 12: a3 16: a4 20: a5
@@ -436,3 +445,35 @@ _handle_level1:
436445
mov a0, a10 // restore return address
437446
ret
438447

448+
// -----------------------------------------------------------------------
449+
// MOVSP raises AllocaCause when the caller window is not yet spilled. The
450+
// handler rotates back to the caller window and enters the matching window
451+
// underflow routine, which does the spill and returns to the MOVSP.
452+
// Ported from ESP-IDF components/xtensa/xtensa_vectors.S, _xt_alloca_exc.
453+
// -----------------------------------------------------------------------
454+
.balign 4
455+
.global _xt_alloca_exc
456+
_xt_alloca_exc:
457+
rsr a0, WINDOWBASE // grab WINDOWBASE before rotw changes it
458+
rotw -1 // WINDOWBASE goes to a4, new a0-a3 are scratch
459+
rsr a2, PS
460+
extui a3, a2, 8, 4 // a3 = PS.OWB (shift 8, 4 bits)
461+
xor a3, a3, a4 // bits that changed from old to current WB
462+
rsr a4, EXCSAVE1 // restore the interruptee's a0 (now in a4)
463+
slli a3, a3, 8
464+
xor a2, a2, a3 // flip those bits in PS.OWB
465+
wsr a2, PS // PS.OWB now matches the new WINDOWBASE
466+
rsync
467+
468+
// Dispatch on the call size in bits 31:30 of the interruptee's a0; plain `j`
469+
// because _bbci.l's 8-bit range cannot reach the underflow vectors.
470+
// Xtensa ISA Reference Manual, RETW, section 8.3.253, p.565 (a0 encoding).
471+
_bbsi.l a4, 31, 1f
472+
j _window_underflow4
473+
1:
474+
rotw -1 // interruptee's a0 moves to a8
475+
_bbsi.l a8, 30, 2f
476+
j _window_underflow8
477+
2:
478+
rotw -1
479+
j _window_underflow12

0 commit comments

Comments
 (0)