diff --git a/CLAUDE.md b/CLAUDE.md index 75c911e..8dfe3ec 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,8 +12,8 @@ on its own: whoever runs a guest supplies its init. Diagnostic input is different from release content. A test or experiment may use a caller supplied initrd, a temporary guest helper, a disposable overlay, or a separately built firmware image when it is isolated from `task build` and `task release`. State clearly what -is diagnostic, who supplies it, and what it is measuring. The qboot probe is the model: -it does not change a release tree and compares both variants with the same diagnostic initrd. +is diagnostic, who supplies it, and what it is measuring. `task boot:firmware` is the model: +it leaves the release tree as it is and boots each firmware with the same diagnostic initrd. **Keep consumer-specific implementation out of this tree, but record real contracts.** Do not copy consumer code, paths, or an ADR as a substitute for an explanation. It is correct to diff --git a/README.md b/README.md index e8fffc1..a5437c8 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ One tarball: | `SOURCES` | every upstream source by version, URL and SHA-256, and the written offer | | `packages.txt` | every package and exact version in the base image | -`LICENSE` and `NOTICE` sit at the root of the tarball, next to `install.sh`. +`LICENSE` and `NOTICE` sit at the root of the tarball. `task build` writes that same tree into `_output/`, byte for byte the layout above, and `machine.OpenRelease` reads either. There is one layout: nothing rearranges the files on the way diff --git a/docs/releasing.md b/docs/releasing.md index 56c62bd..94dabbd 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -2,7 +2,7 @@ ## CI -Five workflows, and the split is about cost. `ci.yml` runs on every push and builds none of +The workflows are split by cost. `ci.yml` runs on every push and builds none of the three artefacts — it is `task lint` and `task test`, which is fast and catches most mistakes. It also *pulls* one: `task qemu:fetch` unpacks the published QEMU of the pinned version in seconds, and `task verify:args` hands it the command line `machine.Spec.Args` diff --git a/qemu/README.md b/qemu/README.md index 60b0a35..9473ef7 100644 --- a/qemu/README.md +++ b/qemu/README.md @@ -27,5 +27,5 @@ deliberately not shipped — it exports a disk over NBD, which nothing here does **PVH, not BIOS.** The kernel is an ELF `vmlinux` with Xen PVH notes and QEMU enters it through `pvh.bin`. There is no bootloader and no UEFI: the same guest under UEFI + Secure -Boot was measured at +356 ms and rejected. Replacing SeaBIOS with qboot was measured too and -cannot run this machine; see [qboot/README.md](qboot/README.md). +Boot was measured at +356 ms and rejected. The BIOS is qboot, patched and built here, with +SeaBIOS shipped as the fallback; see [qboot/README.md](qboot/README.md). diff --git a/qemu/qboot/README.md b/qemu/qboot/README.md index cf0dbe6..76aca5b 100644 --- a/qemu/qboot/README.md +++ b/qemu/qboot/README.md @@ -62,42 +62,13 @@ Measured on the lab runner (AMD Ryzen 9 5900X, run 36650049960, 2026-09-29), 20 interleaved: SeaBIOS 121.89 ms p50, qboot 114.76, 7.14 ms saved; and `report`'s whole matrix, 106 rows, boots on qboot (run 36650559189). -## Measurements, 2026-09-21 - -QEMU 11.1.1, KVM, i9-13900HK, q35 with SATA and SMBus disabled, 2 vCPUs, -2 GiB, CPU host, no disks or NICs, vmgenid present. The diagnostic initrd used a -static BusyBox and printed the marker after mounting proc/sysfs and filtering -dmesg. No cache dropping or warmup phase; 20 boots per firmware per run for the -first two rows and 10 for the third, interleaved, host wall clock before spawning -QEMU to receipt of SPIN-READY. These are diagnostic init timings, not PVH-entry, -systemd readiness, SSH, or full machine topology measurements. - -| Run | Firmware built by | SeaBIOS p50 / p95 | Patched qboot p50 / p95 | p50 reduction | -|---|---|---|---|---| -| Initial | host GCC 15.2.0 | 101.32 / 112.25 ms | 96.50 / 105.25 ms | 4.83 ms | -| Rebuilt using checked-in recipe and probe | host GCC 15.2.0 | 100.89 / 107.40 ms | 94.57 / 101.68 ms | 6.32 ms | -| Containerised recipe, 10 boots, 2026-09-26 | Debian 14.2.0 in `Dockerfile` | 98.43 / 100.41 ms | 94.57 / 97.62 ms | 3.86 ms | - -All three reproduced the original stall and observed reseeding after restoration. Raw -samples and artifact hashes for the first two are in `measurements.json`. - ## The toolchain is part of the number -The first two rows were built by whatever GCC the host had — 15.2.0 — and produced -`7a316e3c…` for the patched binary. `Dockerfile` pins Debian trixie, whose GCC is -14.2.0, and produces `bf7ddddc…`. Same commit, same patch, same flags, different -compiler, and the saving moved from 6.32 ms to 3.86 ms: **the compiler accounts for -more of the difference than a third of what qboot itself saves.** - -This is the same result the SeaBIOS experiment recorded in `boot/phases.go` — two -builds of one firmware differing by as much as the change being measured — and it is -why the recipe is pinned rather than convenient. It also means a number in this file -is only comparable to another number built the same way, and the third row is the only -one that can be reproduced from the repository as it stands. - -The 3.9–6.3 ms observed reduction is useful but is not evidence of a larger saving in a -complete userspace boot: measured against this machine's real boot, the firmware is -about 10 ms of a few hundred. +The same commit, patch and flags saved 6.3 ms over SeaBIOS built by a host's GCC 15.2.0 and +3.9 ms built by Debian trixie's GCC 14.2.0 (i9-13900HK, a diagnostic initrd, 2026-09-21 and +-26): the compiler moved the result by more than a third of what qboot saves. That is why the +recipe is pinned rather than convenient, and why a number here compares only with one built +the same way. Against this machine's real boot, the firmware is about 10 ms of a few hundred. Firmware contents are part of Spec.Fingerprint — the BIOS and pvh.bin, by content — so two firmware builds are two machines, and a checkpoint saved under one does not resume diff --git a/qemu/qboot/measurements.json b/qemu/qboot/measurements.json deleted file mode 100644 index 05e190a..0000000 --- a/qemu/qboot/measurements.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "date": "2026-09-21", - "unit": "milliseconds", - "sha256": { - "qemu": "a135a0fd89360f8ffdef7e236ce66569d165de3b775c6b6e45350d9d2514290c", - "kernel": "701d1e83197df124a11d45cc3c1a47311cf35a487f163d8132f5af7c38062e71", - "seabios": "e26615f9ad430328f49ca105e570b2dc4490a08a34ea73d27cae8b809a30ee06", - "qboot": "7a316e3c29b2e0b849376f6c5b37074ca9fb984d88d3045e934ebbc5737cc2ed", - "initrd": "6f8cf8c0e670de2f13f7c21eb1cdcea3a652b26c9afbfdc0f0805b33c5a51d4d" - }, - "initial": { - "seabios": [ - 102.35880105756223, - 112.25439293775707, - 100.28889798559248, - 102.86838398315012, - 106.50323098525405, - 95.72425403166562, - 103.96376601420343, - 98.84804906323552, - 95.40718595962971, - 95.57203890290111, - 96.29417199175805, - 102.55006595980376, - 97.11084398441017, - 104.83874299097806, - 104.32299203239381, - 104.44100107997656, - 95.78418591991067, - 99.08312698826194, - 112.93924308847636, - 100.08574498351663 - ], - "patched": [ - 105.25433393195271, - 104.18533394113183, - 95.48435593023896, - 92.9054650478065, - 100.82862700801343, - 106.84246802702546, - 91.82357206009328, - 92.10725710727274, - 98.81736896932125, - 97.9178820271045, - 95.58443701826036, - 98.44549710396677, - 89.6216289838776, - 97.40561689250171, - 99.78291497100145, - 101.97925101965666, - 92.17968105804175, - 95.42261098977178, - 95.19110899418592, - 92.55115292035043 - ] - }, - "reproduced": { - "seabios": [ - 101.16701200604439, - 103.21687301620841, - 107.40157507825643, - 98.19312707986683, - 99.13265891373158, - 98.06142502930015, - 106.07362200971693, - 100.60387197881937, - 95.82762001082301, - 104.51311303768307, - 97.46884589549154, - 104.29908195510507, - 102.68541902769357, - 108.04147704038769, - 95.84080509375781, - 100.32242396846414, - 104.31455611251295, - 103.8352029863745, - 98.56852795928717, - 95.68912896793336 - ], - "patched": [ - 97.24596794694662, - 99.0585049148649, - 100.83345102611929, - 94.59814697038382, - 94.47652101516724, - 95.54792603012174, - 93.29728805460036, - 100.17871099989861, - 92.76608400978148, - 91.13843296654522, - 90.2360409963876, - 101.68317402713001, - 93.5989060672, - 93.3470360469073, - 95.62408505007625, - 95.18794994801283, - 109.41709589678794, - 94.53495510388166, - 91.33945091161877, - 93.85259903501719 - ] - } -} diff --git a/versions.yaml b/versions.yaml index b22d052..360301b 100644 --- a/versions.yaml +++ b/versions.yaml @@ -20,6 +20,8 @@ # git: a repository built here; version the branch it is on, pin the commit. # download: a file; source its URL with {version} (and {major}), pin its sha256. # date: a point in time; version the date, no pin. +# module: a Go command; source its package, version the module's, no pin (the +# checksum database holds it to its bytes). # track how check finds the newest: # digest the tag's digest now: the version stays, the image moves # today today's date @@ -29,6 +31,8 @@ # commit # the commit of is at now: a download whose version is # a commit, from a project whose releases do not carry the file +# github-release +# the newest release of a GitHub repository # note why it is pinned where it is, and what a bump has to be checked with. - name: qemu diff --git a/versions/gate_test.go b/versions/gate_test.go index 7c1fc63..1e3b670 100644 --- a/versions/gate_test.go +++ b/versions/gate_test.go @@ -26,8 +26,6 @@ func TestVersionsYAMLIsTheOnlyPin(t *testing.T) { // has to rebase the patch and restate both; versions.yaml's note says so. "NOTICE", "qemu/qboot/README.md", - // The hashes of the artefacts a measurement was taken with. - "qemu/qboot/measurements.json", }} if err := g.Check(); err != nil { t.Error(err)