docs: full docs-vs-code audit — fix every stale claim across 40 docs

Every doc verified claim-by-claim against the code by parallel audit agents,
then fixed and adversarially re-verified. Two waves of staleness corrected:
the originally audited findings (higher-half boot handoff, kernel VFS
takeover, fault isolation + claim release + driver restart, AML/S5 moving to
ring 3, threading's shipped design, USB+FAT landing) and a second pass of
adjacent claims the verifiers caught (smp.md 'not built yet' intro,
system-requirements' PS/2-only and no-storage claims, halting.md's red-panic
and no-IDT text, testing.md's serial mirroring, router-era vfs-protocol
wording, capsule-first boot loading).

threading.md now documents the shared-fate gap explicitly: the design says a
process dies whole, the kernel today kills only the offending thread.

Also fixes three stale code comments (isr.s exceptionHandler, acpi.zig
sleepValue, build.zig boot-volume) — comments only, no behavior change.
This commit is contained in:
Daniel Samson
2026-07-22 09:09:53 +01:00
parent 52df2ba6f6
commit e854f65623
43 changed files with 821 additions and 546 deletions
+11 -3
View File
@@ -87,7 +87,9 @@ because they decide whether we read time with a cheap `rdtsc` or fall back to th
frequency scaling — useless as wall time. Modern CPUs (all of danos's targets) provide an
**invariant TSC**: a constant rate across P/C-states that never stops. The guarantee is a
CPUID bit — leaf `0x80000007`, EDX bit 8 — on both Intel *and* AMD. danos reads it in
`calibrate`, and a TSC that doesn't advertise it is not used as the clocksource. AMD is
`calibrate`, and a TSC that doesn't advertise it is demoted to the HPET clocksource —
provided a usable HPET exists (64-bit; a 32-bit one wraps too fast to stay monotonic).
With no such fallback the TSC stays, there being nothing steadier to switch to. AMD is
why this matters in practice: it doesn't populate the Intel leaf `0x15` that enumerates
the TSC *frequency*, so danos already measures AMD's rate against the HPET — but a
measured frequency without the invariance guarantee is not enough.
@@ -127,6 +129,10 @@ if (state.vector < 32) {
// else: spurious/unhandled — deliberately no EOI
```
(A third branch has since joined for user mode, elided here:
`state.vector == system_call_vector` (128) hands the trap frame to the ring-3
syscall handler.)
Two things make device interrupts *return* where exceptions don't:
1. **The handler returns.** The timer handler just bumps a tick counter. Control
@@ -151,8 +157,10 @@ needs, so only the handler can sequence it. See [drivers.md](drivers.md), where
device is quieted by a driver in ring 3, long after the ISR has returned.
A device handler is a plain `fn () void` — a timer or keyboard handler doesn't need
the interrupted registers. (Note: the stubs don't save the SSE/vector registers, so
a handler must not use them; ours don't.)
the interrupted registers. (The stubs originally didn't save the SSE/vector
registers, so a handler couldn't use them; `isr_common` now does an
`fxsave`/`fxrstor` of the full SSE/x87 state around dispatch — see
[interrupts.md](interrupts.md).)
## Turning them on