G.1: xHCI bulk-endpoint stall recovery (per F.14), built + verified

Full BOT-spec stall recovery per FABRIC-3.md F.14: new STALL_ERROR handling,
Reset Endpoint + Set TR Dequeue Pointer commands, CLEAR_FEATURE(ENDPOINT_HALT),
escalating to Bulk-Only Mass Storage Reset, capped retries
(XHCI_BOT_STALL_MAX_RECOVERIES=2) mirroring bot_tur_retries, clean terminal
failure via xhci_stall_fail().

Purely additive recovery path off the non-success transfer-event branch; the
normal path is unchanged. Builds clean on amd64/aarch64/riscv64. QEMU amd64
boot regression passes: zero stalls, BOT attach (READ CAPACITY10 -> READ10 ->
home-blocks) completes, normal-path xHCI trace identical to baseline. Live
stall injection is not provable under qemu-xhci; deferred to v2.5.0 hardware.

FABRIC-3.md G.1 documented; ROADMAP release-versioning policy folded in.
This commit is contained in:
Robert Allan James
2026-08-29 00:58:59 -04:00
parent 5689c397fc
commit 49a3faa331
7 changed files with 730 additions and 5 deletions
+162
View File
@@ -3264,3 +3264,165 @@ of the pump's own cadence), `USE bob` and `WELCOME` both still work correctly. F
three-architecture regression clean (amd64 fresh Zuse reload + the fix compiled in; aarch64/
riscv64 clean Zuse reload, unaffected — the fix only touches content written at `MINT` time, no
change to the boot path itself).
---
## G. v2.0.0 / v2.5.0 RELEASE plan — recommendation and punch lists (2026-08-28)
**Context.** This is the continuation section of record for the release decision. Opening it
as its own lettered section (§G) so it stands apart from the carried-forward item review
(§A), the design-scope sections (§B–§E), and the built-and-verified backlog (§F). Everything
before this section describes work already committed to `origin/master` (`5689c39` and
earlier). This section records the **versioning split** (v2.0.0 = QEMU, v2.5.0 = real
hardware), the **release-gate recommendation**, and the **punch lists to completion** for
each.
**The versioning split, decided 2026-08-28 — now standing policy, see
`docs/lithosananke/ROADMAP.md` "Release Versioning Policy" for the authoritative form.**
v2.0.0 is the **QEMU release** — the point
where the QEMU-only story is complete and defensible on its own terms. v2.5.0 is the
**real-hardware release** — the point where the same story transfers to bare metal on a real
board. This is one instance of a general policy: **`X.0.0` = QEMU release, `X.5.0` =
hardware bare-metal release, even major numbers are LTS.** The rationale for the split is
practical, not arbitrary: v2.0.0
is the natural, honest cut for what exists *today and is fully verifiable today* (three-arch
QEMU), and v2.5.0 bundles the real-hardware-only work (per-arch RNG drivers, real-board boot
validation) that cannot be green-lit or verified until the boards physically exist (the
author expects to have money for the SBCs — RasPi 6, Milk-V — within about a month of the
v2.0.0 cut). Nothing
is deferred that QEMU alone could already prove out; only what genuinely needs real silicon.
Everything about the state being shipped by v2.0.0 is unchanged by this versioning: the
current tree is a complete, deterministic, three-architecture OS that boots UEFI under QEMU
(M0M9 core milestones complete, M7.1 Capsules live, M9 Block I/O live, terminal/REPL I/O
wired, real virtio-blk persistence proven, a working first-boot Zuse mint via the block
fence).
---
### v2.0.0 (QEMU) — release gates
The v2.0.0 punch list is the set of items that must be green on QEMU (all three of
amd64/aarch64/riscv64) before the QEMU story is complete. Each item states its own exit
criterion so closure is unambiguous and independently verifiable, per this project's
standing discipline.
#### G.1 [v2.0.0] Stall/short-packet recovery for xHCI (scoped §F.14 — **BUILT 2026-08-29**)
Implemented per §F.14 exactly as designed: new `STALL_ERROR` completion code handling, xHCI
Reset Endpoint + Set TR Dequeue Pointer commands, `CLEAR_FEATURE(ENDPOINT_HALT)`, escalating
to a full Bulk-Only Mass Storage Reset, and a recovery counter (`XHCI_BOT_STALL_MAX_RECOVERIES
= 2`) mirroring `bot_tur_retries`.
The code is a purely additive recovery path gated off the *non-success* transfer-event branch
(`xhci.c` transfer-event gate + `xhci_handle_bulk_stall()`, the two new command-completion
states `XHCI_CONN_AWAIT_RESET_ENDPOINT`/`AWAIT_SET_TR_DEQUEUE`, the two new transfer purposes
`XHCI_XFER_CLEAR_HALT`/`XHCI_XFER_BOT_RESET`, and the two new deferred `next_action` values
`XHCI_NEXT_ACTION_CLEAR_HALT`/`XHCI_NEXT_ACTION_BOT_RESET`). The normal (non-stall) path is
byte-for-byte unchanged — the only touched shared line was the single `"control transfer
failed"` gate, now with an else-branch for the recoverable-STALL case.
- **Built clean on all three archs** — `make -f Makefile.starkernel ARCH={amd64,aarch64,riscv64} all`.
- **QEMU amd64 boot regression:** clean enumeration + BOT attach (READ CAPACITY10 → READ10 →
home-blocks) completing with **zero stalls and zero failures**; normal-path xHCI trace
identical to the pre-change baseline. Repeated across fresh boots (all attach=SUCCESS).
- **Exit criterion — partial, honest:** the recovery path itself is not exercised live because
QEMU's `qemu-xhci` model does not produce a `STALL_ERROR` for the injected bad transfers this
driver can stage (no real hardware stall behavior). The design (§F.14) is reviewed and the
code paths are structured and reviewed; **live `STALL_ERROR` → recover → retry verification
is deferred to hardware (v2.5.0/Artemis bare-metal)**, where a real bad transfer can be
staged. This is the last QEMU-verifiable storage-integrity gap and the recovery logic is in
place; the one thing QEMU cannot prove is the live stall injection itself.
- **Note (pre-existing, NOT G.1):** during verification an intermittent boot-time attach race
was observed (the `sk_repl_idle()` `bot_msc_attach_pending` handoff occasionally does not
progress on a cold QEMU boot, independent of source, with baseline `HEAD` exhibiting it too).
Unrelated to G.1; tracked for a separate follow-up.
#### G.2 [v2.0.0] Real-hardware RNG driver plumbing, QEMU-verifiable slice (rest of it lands at v2.5.0)
The full real per-arch RNG driver (`rng_get_bytes()` backing off virtio-rng to RDRAND /
Zkr / peripheral-RNG) is a v2.5.0 item because it cannot be verified on hardware that does
not exist yet. What *is* a v2.0.0 gate is the *shape* of the driver — the unified
`rng_get_bytes()` entry point, the probe-and-refuse-loudly contract (never silently
degrading to a deterministic seed — the exact failure Phase A existed to avoid), and the
QEMU path staying on virtio-rng unchanged — all taken up **before** v2.0.0 so the
single entropy entry point is stable and the v2.5.0 work is purely per-arch backends, not a
redesign of the call path.
- **Exit criterion (v2.0.0 slice):** `rng_get_bytes()` exists as the single entropy entry
point, virtio-rng is its sole active backend on all three QEMU arches, the code refuses
loudly (boot-time message, safe fallback to this-boot-only cert) if no backend is present,
and the pre-existing Zuse mint/cert behavior is unchanged on all three arches. The
per-arch backends themselves are parked, explicitly, for v2.5.0.
- **Exit criterion (v2.5.0 completion, for reference):** on each real board `rng_get_bytes()`
returns genuinely non-deterministic bytes (two boots differ) and the Zuse mint path seeded
from it produces a valid distinct cert per boot when bleached.
#### G.3 [v2.0.0] NVRAM persistence decision — **DECIDED 2026-08-28: permanently de-scoped**
The NVRAM `SetVariable` crash is root-caused (this kernel's VMM never maps the flash-window
region OVMF's variable service needs; also the exposed-seed design defect) and, since the
Zuse cert now lives on the block fence on Artemis, functionally superseded. **DECIDED
(Captain Bob, 2026-08-28): de-scope NVRAM-backed identity permanently.** The block fence on
Artemis is the substrate of record for Zuse's cert. The alternative — scoping the real VMM
memory-map work to make OVMF's flash window writable — is not being scheduled: it is large,
unscoped VMM work with no live consumer now that the fence carries the cert, and the NVRAM
approach carried a real exposed-seed security defect regardless of the crash.
- **Exit criterion (MET):** a dated decision recorded in this section (de-scope), and the
ROADMAP/backlog updated to match. Decision required, not necessarily work — **closed,
no work required beyond this record.**
---
### v2.5.0 (real hardware) — release gates
These are the real-hardware-only items. None can be verified until the boards exist (RasPi 6,
Milk-V; SER5 either in hand or not — see G.5). They are the entire v2.5.0 gate and are listed
together so the v2.5.0 scope is explicit and closed.
#### G.4 [v2.5.0] Per-arch RNG backends behind `rng_get_bytes()` (the G.2 body)
The real RNG driver backends, completed behind the v2.0.0-formed entry point. The existing
VM-UUID finding already maps the primitives: amd64/SER5 RDRAND, riscv64/Milk-V Zkr (RNDR),
aarch64/RasPi peripheral RNG. On QEMU all three arches stay on virtio-rng; nothing changes
there.
- **Exit criterion:** on each real board (`rng_get_bytes()` falling back through the real
primitive) returns genuinely non-deterministic bytes (two boots differ), the Zuse mint
path seeded from it produces a valid distinct cert per boot when bleached, and QEMU
behavior is unchanged.
#### G.5 [v2.5.0] Real-machine boot validation (SER5 / RasPi 6 / Milk-V)
Flash `starkernel.iso` to real media and boot each real board in hand, confirming the same
acceptance story QEMU keeps green: POST `1012/0/0` + `ok>`, block-fence Zuse load true to the
already-minted Artemis image, and the G.4 RNG backend working live. The board pool is
SER5 (if still in hand), RasPi 6 (aarch64), Milk-V (riscv64) — the goal is at least one
board per architecture, but each board that boots is a separate, recorded data point.
This is the genuine transfer proof that the zero-degradation QEMU claim holds on real
silicon — the thing v2.0.0 cannot honestly claim.
- **Exit criterion:** each board in hand cold-boots to `ok>` with Arena conservation
(43691/21845/65536), Zuse cert loads from the fence (or mints fresh on bleached media),
and its G.4 RNG backend returns non-deterministic bytes live. v2.5.0 does not close on any
board's G.4/G.x item being build-only.
---
### Post-release tracking (not gating either milestone)
Beyond the v2.0.0/v2.5.0 gates, the carried-forward open items (§A) and open design questions
(§D) remain genuinely open. Not release-gating; tracked here so nothing silently ages and so
the punch lists above explicitly delimit what is excluded from each milestone:
- Block-map on-drive format field edit (scoped §F.4) and associated §F.6/§F.11 allocation.
- CA-signed-cert verification path + DER signature extraction (scoped §F.7) and
`CERTVERIFY`/`BINDSTEP` consumers (§F.8/§F.9).
- Migration state machine design (§A item, §B Stadium unification reframe).
- Console umbrella closure (§A 4.3) and `(user)` prompt segment (§A 4.4s) once 4.3's blocker
clears.
- `DETACH`/unclean-removal wiring into `sk_repl_idle()` (scoped §F.10).
- Dirty-event granularity (1.11, blocked on 4.3) and the §17.4 framebuffer heat/decay design.
- Re-run the DoE on the new substrate (§A 5.1).
- First-touch allocation first-call-free.