aarch64: split irq_spx into a real save/dispatch/restore/ERET trampoline
Punch list §25 item 0.5 complete.
irq_spx now branches (one instruction, well inside the 128-byte vector slot)
to irq_spx_trampoline, a 672-byte-frame save/restore sequence that calls a
C handler and returns via ERET. The other fifteen vectors are untouched,
still routing to the existing fatal handler.
EL selection (B3) happens once, in aarch64_install_vectors(), not per
interrupt: aarch64_current_el() (item 0.4) picks VBAR_EL1 or VBAR_EL2, and
the same answer is cached in a byte flag (el2_mode_flag) that the trampoline
reads to choose ELR_EL1/SPSR_EL1 vs ELR_EL2/SPSR_EL2 -- the two forms are
genuinely different MRS/MSR encodings, not runtime-selectable operands, so
this is the cheapest correct design: decide once at install time, branch
twice (save, restore) per interrupt afterward. VBAR_EL1 was previously
written unconditionally; this closes that half of item 0.4's known gap.
EL2 is coded from the architecture reference and cannot be boot-tested in
this environment (QEMU's aarch64 virt/EDK2 combination here yields EL1) --
reported as unverified rather than asserted as tested.
FP/SIMD save is not optional (B2, carried from item 0.4's finding that the
build has no -mgeneral-regs-only): the AAPCS64 caller-saved set -- v0-v7,
v16-v31, full 128 bits each -- plus FPSR/FPCR is saved and restored around
the C handler call. v8-v15 are callee-saved by the ABI and deliberately
excluded: the handler, being ordinary compiled C, preserves those itself.
aarch64_irq_handler() (interrupts.c) is deliberately empty. Distinguishing
which interrupt fired needs the GIC's IAR, which does not exist until item
0.6; nothing unmasks or routes any source to this vector yet, so the
function is not reachable during a normal boot. Per the item's own text,
no attempt was made to manufacture an interrupt to exercise this path early
-- 0.6 (GIC) and 0.7 (timer) are what prove it took and returned one.
Verified: every hand-computed frame offset (0, 16, 32 ... 640, frame size
0x2a0=672) checked against the actual disassembly of the built kernel, not
just visually reviewed -- save and restore sequences mirror exactly, and
aarch64_install_vectors' branch on the detected EL, the flag write, and the
trampoline's read of the same flag address all confirmed consistent. Boots
clean on real QEMU output, no regression: dict_hash 0x3d4e1daf289da94f
unchanged from the item 0.1-0.4 baseline, and the item 0.4 EL banner
("AArch64: running at EL1") still prints correctly ahead of "IDT installed.".
Only aarch64-scoped files touched (isr.S, interrupts.c) -- no shared loader
or header changed, so amd64 and riscv64 are provably unaffected; not
rebuilt for this item.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
f43f3f4482
commit
8d8f3aaae2
@@ -23,6 +23,29 @@ extern void aarch64_install_vectors(void);
|
||||
* arch/riscv64/interrupts.c. */
|
||||
extern int aarch64_current_el(void);
|
||||
|
||||
/**
|
||||
* @brief Dispatch an IRQ taken at current-EL with SPx (punch-list item 0.5).
|
||||
*
|
||||
* Called from @c irq_spx_trampoline in @c isr.S, which has already saved the
|
||||
* full caller-saved integer and FP/SIMD register sets plus @c ELR_ELx /
|
||||
* @c SPSR_ELx, and will restore all of it and @c ERET after this function
|
||||
* returns — unlike @c aarch64_exception_handler(), this path is designed to
|
||||
* return normally.
|
||||
*
|
||||
* **Deliberately empty at this item.** Distinguishing which interrupt fired
|
||||
* requires reading the GIC's Interrupt Acknowledge Register, and
|
||||
* acknowledging it requires writing EOIR — neither exists yet (item 0.6).
|
||||
* Nothing currently unmasks or routes any interrupt source to this vector,
|
||||
* so it is not reachable during a normal boot; item 0.5's own acceptance is
|
||||
* "boots with no regression," not having observed a call here (C2). This
|
||||
* function exists so the vector split is complete and linkable now, ready
|
||||
* for item 0.6 to add the IAR read / cause dispatch / EOIR write, and item
|
||||
* 0.7 to route the timer PPI to @c heartbeat_tick() through it.
|
||||
*/
|
||||
void aarch64_irq_handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a 64-bit value as "0xNNNNNNNNNNNNNNNN" to the kernel console.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user