From 7b2d4037a4388ecacb533b2d4aa118f7e7adcb4d Mon Sep 17 00:00:00 2001 From: Nexoniarz Date: Sun, 9 Aug 2026 22:46:00 +0200 Subject: [PATCH] Rebuild when RAMROOT is toggled, and add an opt-in KVM target `make ramroot` wiped the objects on the way in, and nothing wiped on the way out. So a plain `make` afterwards kept every RAMDISK_ROOT object and linked the 24 MB ramdisk back into a kernel that no longer used it: 25 MB where a clean build is 836 KB. It still booted -- from the ramdisk -- and the only outward symptom was stage2 having thirty times as much to load through PIO, one sector at a time. That is the "booting got slower" report this came from. A stamp file records which setting the objects were built with, and the tree is dropped when it changes in either direction. qemu-kvm is opt-in and the default stays TCG, because the suite's timings were established there. Measured with the guest timing itself, `ls /bin | wc -l` goes 2.9s -> 1.1s. Boot does not improve and gets slightly worse: every PIO port access in stage2 is a VM exit under KVM. Retracts a claim from earlier today. The "2.2x speedup" attributed to the region-based allocator was a measurement artifact -- the probe sent a command, slept a fixed 50s on the host, then read /proc/uptime, so it timed the sleep rather than the command, through a guest clock that drifts under load. Bracketing the command inside one guest command line shows no measurable difference. The e820 change is still correct; it is simply not a performance change. Co-Authored-By: Claude Opus 5 --- .claude/memory/schos-bootcheck-trust.md | 28 ++++++++++++++++--- .claude/memory/schos-uefi-loader.md | 16 ++++++----- Makefile | 36 ++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/.claude/memory/schos-bootcheck-trust.md b/.claude/memory/schos-bootcheck-trust.md index 154f057..d8f7427 100644 --- a/.claude/memory/schos-bootcheck-trust.md +++ b/.claude/memory/schos-bootcheck-trust.md @@ -4,7 +4,7 @@ description: bootcheck silently stopped running and five of seven modes asserted metadata: node_type: memory originSessionId: 9d8a2aef-bcf0-47a0-96c6-f706efab4a95 - modified: 2026-08-09T19:17:56.770Z + modified: 2026-08-09T20:44:14.569Z --- **A green run is only green if you counted the checks.** On 2026-08-09 the @@ -83,5 +83,27 @@ confounds each produced a confident wrong answer in one session: `make build/schfs.img` before every timed boot. 3. **Ordering / host drift** — alternate the variants and run each twice. -Time it from inside: `cat /proc/uptime` either side of the command. The guest's -tick does not care what the host is doing. See [[schunix-verify-by-driving-shell]]. +Time it from inside — **and bracket the command in a single guest command line**: + +```sh +cat /proc/uptime; ls /bin | wc -l; cat /proc/uptime +``` + +Sending the command, sleeping a fixed interval on the host, then asking for +uptime **measures the host's sleep, not the command**. That produced a confident +and completely fictional "2.2x speedup" for the e820 work: the two readings were +50 s apart because the host slept 50 s, and the arm that looked faster only had +a guest clock lagging under load. One command line, two readings, no host timing +in the loop. + +4. **The guest clock drifts under TCG.** Missed timer ticks mean `/proc/uptime` + undercounts during heavy load, so it is trustworthy for bracketing a short + command and not for comparing long intervals across runs. + +Baselines, measured correctly 2026-08-09 with an 836 KB kernel: +`ls /bin | wc -l` **2.9 s TCG / 1.1 s KVM**; boot to `schinit: ready` ~3.7 s TCG. +`make qemu-kvm` is the opt-in KVM target. **KVM does not speed up boot** and +slightly slows it: stage2 loads the kernel by PIO one sector at a time, and each +port access is a VM exit. + +See [[schunix-verify-by-driving-shell]]. diff --git a/.claude/memory/schos-uefi-loader.md b/.claude/memory/schos-uefi-loader.md index 3f65cf6..ebed542 100644 --- a/.claude/memory/schos-uefi-loader.md +++ b/.claude/memory/schos-uefi-loader.md @@ -4,7 +4,7 @@ description: "boot/uefi works under OVMF; the SCH64 entry, the GDT trap, and the metadata: node_type: memory originSessionId: d4821aa9-2e49-40da-91e7-90ef9ed9997e - modified: 2026-08-09T20:03:43.364Z + modified: 2026-08-09T20:44:02.893Z --- **`boot/uefi/` boots.** `make uefi`, `make esp`, `make qemu-uefi`. Verified @@ -61,12 +61,14 @@ raising the bound past a hole. Result: 1018 MB in 7 regions under OVMF, 1023 MB in 2 under BIOS. -**It is also a large speedup, which was not the goal and is worth knowing.** -Measured from inside the guest (`/proc/uptime`, fresh image each boot, -alternating rounds): boot to prompt **14.8 s vs 21.2 s**, and a cold -`ls /bin | wc -l` **23.6 s vs 51.2 s** — 2.2x. Both rounds agreed within -0.3 s. So if the allocator ever looks slow again, this is the baseline to -compare against. +**A "2.2x speedup" was claimed for this change on 2026-08-09. It was wrong, +and the retraction matters more than the claim did.** The measurement sent a +command, slept a fixed 50 s on the *host*, and then read `/proc/uptime` — so it +timed the sleep, not the command, through a guest clock that drifts under load. +Correctly measured (see [[schos-bootcheck-trust]]), `ls /bin | wc -l` is **2.9 s +under TCG, 1.1 s under KVM**, and the region-based allocator has no measurable +effect on it either way. The change is still right; it simply is not a +performance change. ## UEFI reaches userspace — 2026-08-09 diff --git a/Makefile b/Makefile index fa81ba7..e8c8ecb 100644 --- a/Makefile +++ b/Makefile @@ -320,6 +320,26 @@ else RAMDISK_OBJ = endif +# Drop the objects when RAMROOT is toggled, in *either* direction. +# +# RAMROOT changes CFLAGS, and make cannot see that: an object compiled one way +# is happily reused the other way. The `ramroot` target already wiped on the way +# in, and nothing wiped on the way out -- so a plain `make` after `make ramroot` +# kept every RAMDISK_ROOT object and linked the 24 MB ramdisk back in. The +# result still booted, from the ramdisk, and the only outward symptom was that +# stage2 now had 25 MB to load through PIO one sector at a time. Measured: +# 25,413,120 bytes against 836,840 for the same kernel built clean. +# +# Evaluated when the Makefile is read, so the wipe happens before anything is +# compiled against the wrong setting. +RAMROOT_STATE := $(if $(RAMROOT),on,off) +RAMROOT_STAMP := $(BUILD)/ramroot.state +$(shell mkdir -p $(BUILD); \ + if [ "$$(cat $(RAMROOT_STAMP) 2>/dev/null)" != "$(RAMROOT_STATE)" ]; then \ + rm -rf $(BUILD)/kernel $(BUILD)/lib $(BUILD)/cmd; \ + printf '%s' '$(RAMROOT_STATE)' > $(RAMROOT_STAMP); \ + fi) + # ----------------------------------------------------------------------- # Top-level targets # ----------------------------------------------------------------------- @@ -856,6 +876,20 @@ $(BUILD)/fs.img: $(MKFS) $(BUILD)/sysroot.stamp # ----------------------------------------------------------------------- # QEMU # ----------------------------------------------------------------------- +# The same thing with hardware virtualisation. Opt-in, never the default: the +# test suite's timings were established under TCG and changing the execution +# engine underneath them is a variable to introduce on purpose. +# +# Worth knowing what it does and does not buy. Measured with the guest timing +# itself, `ls /bin | wc -l` goes from 2.9s to 1.1s. Boot does *not* improve -- +# it gets worse -- because stage2 loads the kernel by PIO one sector at a time, +# and under KVM every one of those port accesses is a VM exit, where under TCG +# it is cheap. +qemu-kvm: schos.img $(BUILD)/schfs.img + $(QEMU) -enable-kvm -serial mon:stdio $(QEMU_DISPLAY) -cpu host \ + -hda schos.img -hdb $(BUILD)/schfs.img \ + -m 1G -smp 2 -machine pc-i440fx-9.2 + qemu: schos.img $(BUILD)/schfs.img $(QEMU) -serial mon:stdio $(QEMU_DISPLAY) -cpu qemu64,+rdtscp \ -hda schos.img -hdb $(BUILD)/schfs.img \ @@ -955,7 +989,7 @@ qrtest: $(QRTEST) qrcheck: $(QRTEST) $(PYTHON) tools/python/qrcheck.py -.PHONY: all kernel ramroot cmd ports sysroot-install qemu \ +.PHONY: all kernel ramroot cmd ports sysroot-install qemu qemu-kvm \ schfs-test schfs-objtest schfs-image-test schfs-check mkschfs \ schfs-fsck crashshot qemu-schfs iso qemu-iso clean distclean \ logo qrtest qrcheck crashqr usb-ids