Stage 0: trap-frame parity across all 3 arches (FABRIC-3.md §XXVIII)
First stage of the preemptive context-switching plan (see ~/.claude/plans/logical-snuggling-bear.md). Pure foundation work -- every arch's ISR now saves the full register set on interrupt entry, so a trap frame is in principle sufficient to resume execution anywhere it was taken. No FORTH-visible behavior changes. amd64: added FXSAVE/FXRSTOR, closing a genuine pre-existing correctness gap (not just future-preemption prep) -- confirmed live double-precision FP code reachable from ordinary interpreter dispatch (vm_runtime.c Loop #5/#6), and the ISR previously saved zero FP/SSE state. rbp repurposed as a fixed anchor so the 16-byte-aligned FXSAVE area can be carved out of an unpredictably-aligned rsp without disturbing existing argument reads. aarch64: extended the trap frame 672->800 bytes, adding v8-v15 (AAPCS64 callee-saved, previously excluded on call-site-only reasoning that doesn't hold for an async trap). riscv64: extended the trap frame 320->512 bytes, adding s0-s11 and fs0-fs11 (the latter still correctly gated behind sstatus.FS != Off). All 3 architectures re-verified clean boot to ok> under the new frames -- amd64 through hundreds of timer ticks with FXSAVE/FXRSTOR live on every interrupt, aarch64 through 987 ticks, riscv64 clean on the now-larger FS-conditional block. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UNhH1mhi52i6Qihh7ZV5S
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
2a30212bd3
commit
15672ce17c
@@ -148,7 +148,7 @@ aarch64_install_vectors:
|
||||
/* ---------------------------------------------------------------------------
|
||||
* irq_spx_trampoline — save / call C handler / restore / ERET.
|
||||
*
|
||||
* Frame layout (672 bytes, 16-byte aligned; SP is guaranteed 16-aligned at
|
||||
* Frame layout (800 bytes, 16-byte aligned; SP is guaranteed 16-aligned at
|
||||
* any point AAPCS64 code can be asynchronously interrupted, so no extra
|
||||
* alignment handling is needed around the initial SUB):
|
||||
*
|
||||
@@ -160,11 +160,20 @@ aarch64_install_vectors:
|
||||
* 272 FPCR
|
||||
* 280 (8 bytes unused -- keeps the V-register block 16-aligned)
|
||||
* 288..415 v0-v7 (4 STP Q-pairs) -- AAPCS64 caller-saved
|
||||
* 416..671 v16-v31 (8 STP Q-pairs) -- AAPCS64 caller-saved
|
||||
* 416..543 v8-v15 (4 STP Q-pairs) -- AAPCS64 callee-saved
|
||||
* 544..799 v16-v31 (8 STP Q-pairs) -- AAPCS64 caller-saved
|
||||
*
|
||||
* v8-v15 are AAPCS64 callee-saved and are deliberately not here: the C
|
||||
* handler below is ordinary compiled code and preserves those itself if it
|
||||
* touches them, per the same ABI the save list is drawn from.
|
||||
* FABRIC-3.md SXXVIII (Stage 0, preemptive-context-switch trap-frame parity,
|
||||
* 2026-09-13): v8-v15 now saved too. They are AAPCS64 callee-saved, so
|
||||
* ordinary compiled code (the C handler below, or anything else called
|
||||
* through a normal ABI boundary) already preserves them across a *call* --
|
||||
* but an interrupt is not a call the interrupted code's own compiled
|
||||
* instructions know about. A value the interrupted function is genuinely
|
||||
* live-using in v8-v15 at the moment of interrupt has no ABI guarantee of
|
||||
* surviving an async trap at all; only a frame that saves everything makes
|
||||
* "resume execution anywhere it was taken" actually true. This trap frame
|
||||
* is not yet copied into any per-VM saved context (that's Stage 2) -- this
|
||||
* stage only makes the frame itself complete.
|
||||
* ------------------------------------------------------------------------- */
|
||||
.equ TF_X0, 0
|
||||
.equ TF_X2, 16
|
||||
@@ -190,15 +199,19 @@ aarch64_install_vectors:
|
||||
.equ TF_V2, 320
|
||||
.equ TF_V4, 352
|
||||
.equ TF_V6, 384
|
||||
.equ TF_V16, 416
|
||||
.equ TF_V18, 448
|
||||
.equ TF_V20, 480
|
||||
.equ TF_V22, 512
|
||||
.equ TF_V24, 544
|
||||
.equ TF_V26, 576
|
||||
.equ TF_V28, 608
|
||||
.equ TF_V30, 640
|
||||
.equ TF_SIZE, 672
|
||||
.equ TF_V8, 416
|
||||
.equ TF_V10, 448
|
||||
.equ TF_V12, 480
|
||||
.equ TF_V14, 512
|
||||
.equ TF_V16, 544
|
||||
.equ TF_V18, 576
|
||||
.equ TF_V20, 608
|
||||
.equ TF_V22, 640
|
||||
.equ TF_V24, 672
|
||||
.equ TF_V26, 704
|
||||
.equ TF_V28, 736
|
||||
.equ TF_V30, 768
|
||||
.equ TF_SIZE, 800
|
||||
|
||||
.balign 4
|
||||
irq_spx_trampoline:
|
||||
@@ -247,6 +260,10 @@ irq_spx_trampoline:
|
||||
stp q2, q3, [sp, #TF_V2]
|
||||
stp q4, q5, [sp, #TF_V4]
|
||||
stp q6, q7, [sp, #TF_V6]
|
||||
stp q8, q9, [sp, #TF_V8]
|
||||
stp q10, q11, [sp, #TF_V10]
|
||||
stp q12, q13, [sp, #TF_V12]
|
||||
stp q14, q15, [sp, #TF_V14]
|
||||
stp q16, q17, [sp, #TF_V16]
|
||||
stp q18, q19, [sp, #TF_V18]
|
||||
stp q20, q21, [sp, #TF_V20]
|
||||
@@ -262,6 +279,10 @@ irq_spx_trampoline:
|
||||
ldp q2, q3, [sp, #TF_V2]
|
||||
ldp q4, q5, [sp, #TF_V4]
|
||||
ldp q6, q7, [sp, #TF_V6]
|
||||
ldp q8, q9, [sp, #TF_V8]
|
||||
ldp q10, q11, [sp, #TF_V10]
|
||||
ldp q12, q13, [sp, #TF_V12]
|
||||
ldp q14, q15, [sp, #TF_V14]
|
||||
ldp q16, q17, [sp, #TF_V16]
|
||||
ldp q18, q19, [sp, #TF_V18]
|
||||
ldp q20, q21, [sp, #TF_V20]
|
||||
|
||||
Reference in New Issue
Block a user