FABRIC.md §25: GAP-B2 verified and fixed, GAP-B3 fixed — FP state and EL scope

B2, verified against Makefile.starkernel: no architecture restricts FP register
use. amd64 has no -mno-sse (:124) -- works with live interrupts today, save-set
adequacy unverified. aarch64 lacks -mgeneral-regs-only (:146). riscv64 builds
-march=rv64gc -mabi=lp64d (:162) -- hard-float ABI, and kernel code genuinely
uses doubles (hotwords_stats_print). Items 0.2 and 0.5 now require saving the
ABI caller-saved FP set plus control/status registers, with the exact lists
verified against the psABI/AAPCS64 rather than this document, and explicitly
forbid "fixing" it via soft-float, which would break existing code.

B3: item 0.4's EL detection now governs everything EL-dependent -- vector base
register (today's isr.S writes VBAR_EL1 unconditionally, never consulted for
exceptions taken at EL2), saved-state pair, eret target, and timer registers.
Item 0.5's hardcoded ELR_EL1/SPSR_EL1 wording replaced accordingly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-03 11:31:26 -04:00
co-authored by Claude Fable 5
parent 09d0067b65
commit 8ac284f8c1
+24 -6
View File
@@ -2009,6 +2009,12 @@ on until there is a tick on all three architectures (§16.1, §16.5).*
Replace the one-way `riscv64_trap_entry` in `arch/riscv64/isr.S` with save / dispatch /
restore / `sret`. Route `scause` bit 63 + cause 5 to the timer path; everything else keeps
falling through to the existing fatal handler.
**FP state is not optional (B2 verified):** the kernel builds `-march=rv64gc -mabi=lp64d`
(`Makefile.starkernel:162`) — hard-float ABI, and kernel code genuinely uses doubles
(`hotwords_stats_print`). The trap entry must save the ABI's caller-saved FP registers
plus `fcsr` alongside the integer set; verify the exact register list against the RISC-V
psABI, not this document. Do not "fix" this by switching to soft-float — that breaks
existing code and is a build-system decision nobody has made.
*Done when:* riscv64 boots to the prompt unchanged, having taken and returned from at
least one trap. Exceptions still halt with the same diagnostic as before.
@@ -2025,15 +2031,27 @@ on until there is a tick on all three architectures (§16.1, §16.5).*
relying on it; if it is absent, stop and report rather than falling back silently.
- [ ] **0.4 — aarch64: determine the exception level at runtime.**
Read `CurrentEL` in `timer_init()` and select the `CNTP_*_EL0` or `CNTHP_*_EL2` register
set accordingly. Do not hardcode either.
Read `CurrentEL` once, early, and let it govern **everything EL-dependent**, not just the
timer (B3): the vector base register (`VBAR_EL1` vs `VBAR_EL2` — today's `isr.S` writes
`VBAR_EL1` unconditionally, which is never consulted for exceptions taken at EL2), the
saved-state pair (`ELR_ELx`/`SPSR_ELx`), and the timer register set (`CNTP_*_EL0` vs
`CNTHP_*_EL2`). Do not hardcode either level anywhere.
*Done when:* the boot log states which EL was detected, on real QEMU output.
- [ ] **0.5 — aarch64: IRQ vector split.**
Split `irq_spx` out of the shared fatal handler in `arch/aarch64/isr.S`: save `x0``x30`,
`ELR_EL1`, `SPSR_EL1`, call a C handler, restore, `eret`. The other fifteen vectors are
unchanged. Note the 128-byte slot limit — the save sequence will not fit inline and must
branch to a trampoline.
Split `irq_spx` out of the shared fatal handler in `arch/aarch64/isr.S`: save `x0``x30`
plus the saved-state registers (see B3 note below), call a C handler, restore, `eret`.
The other fifteen vectors are unchanged. Note the 128-byte slot limit — the save sequence
will not fit inline and must branch to a trampoline.
**FP state is not optional (B2 verified):** the kernel builds without
`-mgeneral-regs-only` (`Makefile.starkernel:146`), so the compiler may use SIMD registers
anywhere. Save the ABI's caller-saved SIMD set plus `FPSR`/`FPCR` alongside the integer
set; verify the exact list against the AAPCS64, not this document.
**EL governs the whole path (B3):** this item previously hardcoded `ELR_EL1`/`SPSR_EL1`,
while 0.4 refuses to hardcode the EL — and today's `isr.S` installs `VBAR_EL1`, which is
never consulted for exceptions taken at EL2. The EL detected in 0.4 must select the
vector base register (`VBAR_ELx`), the saved-state pair (`ELR_ELx`/`SPSR_ELx`), and the
`eret` target state, not just the timer registers.
*Done when:* aarch64 boots to the prompt having taken and returned from at least one IRQ.
- [ ] **0.6 — aarch64: minimal GICv2.**