ADR-004 — EL1 VBAR and resumable BRK
- Status: Accepted
- Date: 2026-09-09
Context
FR-06 requires synchronous exceptions via VBAR_EL1 (at least a breakpoint / fault path). Roadmap M3 is that path. M4 (FR-07) is a dedicated fatal stack. M5 (FR-08) is GIC IRQs.
QEMU virt -kernel usually starts the guest at EL1. -machine virt,virtualization=on starts at EL2. Exceptions taken to the current EL use that EL’s VBAR_*. Staying at EL2 and programming only VBAR_EL2 would not satisfy FR-06.
Decision
- Live at EL1.
exception::initcallsensure_el1: ifCurrentELis EL2, setHCR_EL2.RW, copySPtoSP_EL1, andERETto EL1h (DAIF masked). If the EL is not 1 after that, print and park. Do not treatVBAR_EL2as the primary table. - One 2 KiB-aligned table at
exception_vectors, written toVBAR_EL1. All sixteen AArch64 slots exist. Current EL / SP_EL0 / synchronous saves a frame and mayERET. Current EL / SP_EL0 / IRQ is live as of ADR-006. Every other slot parks (UART line +wfe, or semihosting fail undercargo test/force-fail). - Context format (current-EL sync only):
x0–x29,x30,ELR_EL1,SPSR_EL1,ESR_EL1. No SIMD/FP save (soft-float, ADR-003). BRKis resumable. ESR exception class0x3C(AArch64BRK) increments a counter, printsexception: sync BRK, adds 4 toELR_EL1, and returns. Other synchronous exceptions are fatal for this milestone (print + park). That is not FR-07’s dedicated overflow stack.
Consequences
#[test_case]can executebrk #0and continue. The hello kernel fires oneBRKsoscripts/qemu-smoke.shcan require the handler string on serial.- Lower-EL and FIQ/SError stubs are parks. Current-EL IRQ is M5 / ADR-006, not a syscall ABI.
- A nested fault while
println!holds the UART mutex can deadlock. ADR-005 (M4 / FR-07) splitsSP_EL0/SP_EL1, adds a fatal stack, and uses a raw UART write on that path. - This ADR does not claim Raspberry Pi, EL0, or a taken lower-EL exception.