Skip to content

The kernel loads Intel's CPU microcode early on every CPU, and an AMD CPU says ToyOS has no loader for it - #886

Merged
Japabu merged 13 commits into
mainfrom
wt/toyos-microcode
Oct 13, 2026
Merged

Japabu merged 13 commits into
mainfrom
wt/toyos-microcode

Conversation

@Japabu

@Japabu Japabu commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Fix round 4. Head 56f08c24b. It builds the owner's ruling after round 2's review (ruling, points 1-4; review): this branch lands Intel's loader alone, and the AMD loader leaves it. Round 4 answers round 3's review: round 3's metal readings are published, the issue is renamed, and origin/main is merged at 52e32385d (#894). It takes up the issue now at issues/the-kernel-loads-no-amd-microcode.md, whose AMD half stays open. A draft. Before it lands: a review.

Evidence is on ToyOSOrg/evidence pr-886: round 3's gates, mutations and staging at a6963e0d, round 3's metal readings at 70025e35, round 4's host gate at eaf66e29, and round 2's metal readings at f17cea3b, whose exits are files since 70025e35. Authority is Intel's: SDM Vol. 3A (325384-093US) §12.11, Intel's Microcode Update Guidance, and the 500 Series PCH datasheet for the T14's reset.

The design (accepted in the ruling)

The kernel loads, on every CPU, the newest update Intel's embedded file holds for it, before anything reads what an update changes. On a CPU of any other vendor it reads nothing and logs by name that ToyOS has no loader for it: microcode: cpu0 Amd signature 0x860f01 loads nothing: ToyOS has no Amd microcode loader. The AMD row expects that line.

Its roast. An AMD machine runs its firmware's microcode, however stale, until the AMD half is built. That is the issue's open half, not a fallback: no AMD path runs. The line names the vendor so a bench reading tells a missing loader from a load that failed.

What this round changed

The AMD loader leaves the branch (ruling 1; review BLOCKERs 1-4)

Deleted:

  • kernel/microcode/src/amd.rs and its tests;
  • the embedded container kernel/microcode/amd-ucode/microcode_amd_fam17h.bin, its NOTICE section, licenses/AMD-ucode-license.txt, its ROOT copy and its build/licence.rs row;
  • Maker, Revision::from_patch_level;
  • the kernel's AMD_TRIGGER, load_amd, and the family-0x17 INVLPG with Patch::leaves_its_mapping_uncached (BLOCKER 4).

The review's BLOCKERs 1 to 3 asked for a rebuilt AMD reader. The ruling moves that work to the issue's exit, so no AMD reader is on this branch for them to apply to.

Added: toyos_microcode::loader(vendor) admits Intel alone, and Unloaded::Vendor reads "ToyOS has no microcode loader". The kernel calls it before it reads any MSR. Test: a_vendor_toyos_has_no_loader_for_loads_nothing.

Folded back. With one maker left, the intel module goes back into lib.rs, where main has the reader, and Choice<'a> is no longer generic. The crate's description says Intel alone again. build/build.rs's licence slice becomes the one MICROCODE_LICENCE, pushed on x86-64.

The judge. microcode_on_metal holds:

  • the T14 (0x806c1) to every CPU running 0xbe, current or loaded;
  • the AMD bench (0x860f01) to every CPU's no-loader line, with no revision read.

microcode_lines still reds the first refused line on any machine. microcode_verdict accepts both benches on eight CPUs and refuses eight machines. The eight CPUs are the roster the AMD bench brings up (SMP: roster full at 8 CPUs), which fixes the review's roster NOTE.

The issue (ruling 2; round 3's BLOCKER 2 and NOTE 1)

issues/the-kernel-loads-no-cpu-microcode.md is renamed issues/the-kernel-loads-no-amd-microcode.md, for the old slug is false of this tree (issues/README.md, "Slugs"), and its one citation, in issues/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md, moves in the same commit. It is open, records the T14 half as met by this branch, and states the clean-room rule as root CLAUDE.md ("Zero legacy") gives it. Its exit is the ruling's:

  • a loader built clean-room: one agent reads AMD's amd_ucode_info and writes from it a specification of facts citing no implementation, keeping the provenance in its own evidence; another builds from that specification alone, handed to it in its brief and never committed;
  • matching through the equivalence table, with BLOCKER 1's host test;
  • each undocumented behaviour stated with its measurement;
  • the AMD bench green, with its trigger-removed control red.

Round 2's readings are published (ruling 3, BLOCKER 5)

Each arm's judge log, kernel.log and boot.txt are masked and on pr-886 at f17cea3b. The orchestrator booted and judged every arm. Each arm's exit, as the orchestrator reported it, is recorded in r2/readings/<arm>/judge.exit at 70025e35; a failing judge log also carries its exit in its last line.

arm tree judge exit the row says readings
t14-head e2b398cb6 0 8 CPUs of signature 0x806c1 run 0xbe judge · kernel.log · boot.txt
t14-reverted (m3) 1e92b3edc 1 no microcode line judge · kernel.log · boot.txt
t14-reseal (m1), judged from b7a7b062a b7a7b062a 1 cpu0 refused the update it was handed and runs 0xbe judge · kernel.log · boot.txt
amd-head e2b398cb6 0 8 CPUs of signature 0x860f01 run 0x860010d judge · kernel.log · boot.txt
amd-reverted (m3) 406b5863d 1 no microcode line judge · kernel.log · boot.txt
amd-trigger-removed (m2) 5b029c0a8 1 cpu0 refused the update it was handed and runs 0x8600106 judge · kernel.log · boot.txt
amd-no-invlpg (m4) 0cb620cae 0 8 CPUs of signature 0x860f01 run 0x860010d judge · kernel.log · boot.txt

Each judge command was cargo test --test toyos-build -- --metal --metal-readback <arm dir> microcode, with --metal-host on the AMD arms. The t14-reseal arm also has the first judging, from the head tree: it restaged the arm (exit 2) and judged nothing.

amd-no-invlpg beside amd-head, reported only. Both read the same eight lines.

complete preamble wipe flash (dd) entry down read_log raw_log
amd-head 1318 ms 1.1 s 0.6 s 15.3 s (13.4 s) 2.9 s 11.0 s 1.4 s 2.4 s
amd-no-invlpg 1314 ms 1.1 s 0.6 s 13.9 s (12.6 s) 2.7 s 11.0 s 3.1 s 9.3 s

On this branch the family-0x17 INVLPG is deleted (BLOCKER 4). These readings are only a record of the AMD reader that left.

The NOTEs (ruling 4)

Tests, cheapest tier first

Host. The judge and the vendor admission run as mutations. Each is a checked patch, applied, run, reported and reverted, with the porcelain empty after each (run.out; patches and logs beside it, at a8130e0e4, whose tree differs from the head only by one comment in tests/toyos.rs):

mutation command exit red
j1 the judge takes a refused line cargo test --test toyos-checks microcode_verdict 101 "a T14 BSP that refused its update was refused for the wrong reason"
j3 the T14 takes any revision same 101 "a T14 CPU below Intel's update was accepted"
j4 the AMD bench takes any line same 101 "an AMD CPU that read and loaded was accepted"
h1 the loader admits AMD cargo test -p toyos-microcode 101 a_vendor_toyos_has_no_loader_for_loads_nothing

The Intel reader's tests are the build round's, moved from intel/tests.rs back to tests.rs unchanged except for the include_bytes! paths. The build round's mutations guarded that code at f126fb514 (run.out); this round did not run them again.

Guest. No guest test is added or changed. An x86-64 guest takes the hypervisor arm on an Intel host and the no-loader arm on AuthenticAMD qemu64. Neither reads past the line, and no guest test asserts it.

Metal. Staged with the harness's own --metal-readback; the request is below.

Checks (root CLAUDE.md)

  • The negative control is the whole change reverted onto b680a973b, the base this head merged, with the row kept (m3). It is staged on both benches, and each must red on "no microcode line".
  • The refusal's control is t14-reseal (m1): a header revision Intel's payload does not carry. It must red on cpu0's refused line on a completed boot.
  • Independent oracles:
    • Intel's SDM §12.11 and Microcode Update Guidance;
    • Intel's file itself;
    • the T14's own read-back of MSR 8BH;
    • for the AMD row, the bench's own CPUID vendor.
  • What the new tests see that reading cannot:
    • microcode_verdict: what the judge refuses;
    • the metal row: what two real CPUs report.

Gates

gate head exit log
cargo run -- --ci host dfee7fa3d 0 ("Host: 76 step(s), all green") ci-host.log L8966
cargo run -- --ci host a8130e0e4 0 ci-host-a8130e0e4.log L9030
cargo run -- --build-only a8130e0e4 0 build-x86_64.log L339
cargo run -- --build-only --arch aarch64 a8130e0e4 0 build-aarch64.log L337
cargo test, the whole guest suite, 62 of 62, at a one-minute load average of 24.59 to 24.73 a8130e0e4 0 guest.log L1133
five --metal-readback stagings as below 2 each (Verdict::Staged) stage.out
the metal row, five arms as below as below r3/readings
cargo run -- --ci host 56f08c24b 0 ("Host: 76 step(s), all green") ci-host.log L9421

a8130e0e4 and dfee7fa3d differ by one comment in tests/toyos.rs, which builds into no image. 56f08c24b merges origin/main at 52e32385d; since b680a973b it has taken #892, #903, #875, #874, #887, #893, #863, #896, #900 and #894, none touching a path the metal row measured (round 3's review). The merge and the issue's rename are the only changes past dfee7fa3d, and the host gate above is run at 56f08c24b.

Metal

The request gives each arm's tree, image sha256, toyos-metal invocation, judge command (row word microcode) and expected verdict. The mutation trees are local commits on a detached head, never pushed.

arm bench tree image sha256 expected
t14-head T14 dfee7fa3d acf803b1… green: 8 CPUs current 0xbe running 0xbe
t14-reseal (m1) T14 117f0d454 009a7959… red on a completed boot: cpu0 found 0xbe refused 0xbf running 0xbe
amd-head AMD dfee7fa3d ac488ca6… green: 8 CPUs loads nothing: ToyOS has no Amd microcode loader
t14-reverted (m3) T14 e4b2817c3 58d5e9a6… red: no microcode line
amd-reverted (m3) AMD 2e8aba69f 1bc2bb99… red: no microcode line

The readings. The orchestrator booted and judged each arm; its exit, judge command, judge log, kernel.log and boot.txt are on pr-886 at 70025e35, masked. Each kernel.log's supervisor: build names the arm's tree.

arm judged from judge exit the judge says readings
t14-head dfee7fa3d 0 "8 CPUs of signature 0x806c1: every CPU runs 0xbe", 1 passed cmd · judge · kernel.log · boot.txt
amd-head dfee7fa3d 0 "8 CPUs of signature 0x860f01: every CPU says ToyOS has no Amd microcode loader", 1 passed cmd · judge · kernel.log · boot.txt
t14-reverted (m3) dfee7fa3d 1 "expected one microcode line from each of {0, …, 7}, got []" cmd · judge · kernel.log · boot.txt
amd-reverted (m3) dfee7fa3d 1 "expected one microcode line from each of {0, …, 7}, got []" cmd · judge · kernel.log · boot.txt
t14-reseal (m1) 117f0d454 1 "cpu0 refused the update it was handed and runs 0xbe" cmd · judge · kernel.log · boot.txt

Every arm reads as its request expects. The images are dfee7fa3d's. Past it, 56f08c24b adds only the merge of main, which reaches no path the row measured, and the issue's rename.

The first m3 staging diffed against an origin/main that another worktree's fetch had moved past b680a973b. It failed to build (exit 101) and was discarded; stage.out records it.

What I am unsure of

  • The judge matches the kernel's reason string, "ToyOS has no Amd microcode loader", as text. Only the amd-head boot can catch a drift between the two.
  • Intel revisions with the top bit set. The SDM calls the header's revision "a signed 32-bit number", and Revision compares unsigned, as acceptance 1 ruled. No pinned file carries one.
  • 0xffffffff has no meaning in Intel's documents. The refusal stands as accepted, on its own reason only.

Size

git diff --shortstat origin/main...56f08c24b: 21 files, +718 −128, against round 2's 24 files, +1568 −521.

  • Production (kernel/microcode/src/lib.rs, kernel/src, build, manifests, Cargo.lock): +412 −43.
  • Tests (kernel/microcode/src/tests.rs, tests/): +182 −7.
  • Records (NOTICE, issues/): +124 −78, the issue's rename counted as a delete and an add.

Round 3's commit, dfee7fa3d: +680 −1141, most of it the AMD reader, its container and the intel module folded back.

🤖 Generated with Claude Code

https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy

@Japabu

Japabu commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator Author

The AMD bench's Linux microcode reading, owed by the orchestrator, is now on the evidence branch: amd-bench-linux-microcode.txt at 9e5f88e5.

  • Firmware 0x08600106; Linux early-loads 0x0860010d.
  • Family 23, model 96, stepping 1.
  • amd-ucode-firmware-20260810.

The command is recorded in the file's header.

@Japabu

Japabu commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator Author

Design review of #886 at bc44b7601, round 1, against .claude/agents/reviewer.md and root CLAUDE.md on origin/main (867ec23ed).

Size: git diff --shortstat origin/main...bc44b7601 is empty, because the head is one empty commit. The body estimates production at about +409: toyos-microcode +230, arch/x86_64/microcode.rs +110, the witness +15, licence and build +19, and the boot-actuators reseal arm +35. Tests come to about +360, plus data. I accept the production growth: the issue the branch takes up mandates it, and the tree has no loader it could be merged into.

Judged against the sources, no finding. I fetched Linux v7.2 and Xen 2c40f10b; their digests equal the log's §5.

  • AMD. Every line the body cites says what the body says:
    • container and sections: amd.c:56-61,432-460
    • chipset refusal: :543-546
    • Zen match by patch ID: :300-315,580-587
    • load at or above the running revision, BSP and AP: :818,996
    • EAX: :336
    • trigger at the header: :700-705
    • family-0x17 INVLPG: :707-718. Xen's is family 0x17 too, at the start and at +3199 (amd.c:366-370).
    • read-back: :723-729
    • EntrySign families: :246-262
    • the 4800U's cutoff 0x860010e: :196
    • Xen reads offset 12 as a minimum revision from processor ID 0xa000 up (amd.c:291-313).
  • Re-measured independently. linux-firmware 20260916 microcode_amd_fam17h.bin is 966e4b79…. Bytes 9772 to 9772+3200 hash to 86b61583…, which is amd_shas.c's 0x860010d. The section at 9764 has type 1 and size 0xc80. The offset-12 word is 0.
  • Intel. The cited rules match Linux:
    • no MSR 17H under a hypervisor, bits 52:50: intel.c:138-158
    • only a strictly newer update: :379,697
    • write 0, CPUID, read: :696-709
    • bit 31 disables the loader: core.c:114-139
  • EntrySign at build time. A runtime digest of an embedded patch would compare the image with itself. Linux's amd_shas.c has no row above its CPU's cutoff: I checked all 79 against get_cutoff_revision, amd.c:190-231.
  • The witness. Running is the right shape for the verdict. It is a compile-time order where the alternative is a static and a runtime check.
  • The licence kind. It mirrors Terms::Font and FONTS_ONLY (build/licence.rs:82-110).
  • Metal controls. The T14's reseal arm and the AMD bench's trigger-removed mutation each turn the read-back's assert red on real silicon. The revert of the whole change is root CLAUDE.md's control.

BLOCKER

  • PR body, the plan ("Tests / Host") — a CPU that reports revision 0xffffffff is not modelled. Xen takes rev == ~0 to mean that a hypervisor, or a firmware toggle on bare metal, has disabled loading, and it ignores the interface (xen/.../microcode/core.c:944-957). Linux loads nothing over it, because it compares Intel revisions unsigned (intel.c:355,379,697; microcode.h:37). This design compares them signed (kernel/microcode/src/lib.rs:65-75). An Intel CPU at -1 would be handed the update, refuse it, and the read-back would panic a machine that both references boot. The plan should refuse ~0 by name, on both makers, before select, and a host test should hold that refusal.

  • PR body, "Guest" — the guest assertion that every CPU's line says hypervisor guards one CPUID bit, which a reader checks against core.c:114-139.

    • Every x86-64 guest boot already runs that arm, so a fault there turns the whole suite red.
    • A misread bit on CI's hosts changes only the line, because no embedded file names an EPYC or qemu64.
    • On a host that a file does name, every guest boot stops at the load: at the read-back panic the body describes, or at an MSR 17H fault.

    Drop the assertion. Rewrite the guest exit of issues/the-kernel-loads-no-cpu-microcode.md, the issue the branch takes up, to rest on the QMP reading (log L256-269).

  • PR body, "Host / The plan", "which half of MSR 8BH each maker reports in" — this tests a shift. Make the half each maker's own revision constructor, test nothing, and let a reader hold it to SDM §12.11.7.1 and Linux amd.c:336. Intel's constructor already exists: Revision::from_sign_id, kernel/microcode/src/lib.rs:70-75. On either bench, the wrong half already reads found 0 and panics at the read-back.

NOTE

  • PR body, Roast 1 — false of the record on which the placement is weighed. Linux's order is not "load, then verdict, then CR4, then IDT":

    • Linux's BSP loads after an early IDT handler (head64.c:276,286).
    • Its APs load after CR4 and the IDT (smpboot.c:236,248,266), with PCIDE already applied from the BSP's post-load revision (init.c:288-307).
    • Its "plain" native_wrmsrq carries an EX_TYPE_WRMSR fixup that reports and continues (msr.h:78-84,101-102). cda64169bade's own log shows that fixup catching MSR 17H in a guest.
    • Xen uses wrmsr_safe (amd.c:352).

    Both survive a fault at the trigger and report it. ToyOS alone hangs silently on the BSP and resets on an AP. The placement still stands on Intel's guidance (log L143), because declaration reads CPUID on every AP (control_regs.rs:363,408) and random::key comes after it (main.rs:359). The body should say three things:

    • the cost is ToyOS's own;
    • today the cost buys the PCIDE verdict nothing, because no Alder Lake or Raptor Lake file is embedded, so the verdict judges the firmware's revision either way;
    • only the first of the two exits of issues/an-ap-loads-the-idt-before-its-control-registers.md covers the load, because the second leaves the AP with no table at all.
  • Linux amd.c:554-572 — the EntrySign cutoff-side rule is missing from the design's AMD rules: a CPU at or below its cutoff is offered only patches at or below it. This loader would hand a new-scheme patch to a pre-fix CPU, inside the window with no IDT. What refuses such a patch here works at build time:

    • amd_shas.c holds no digest above a cutoff;
    • Zen 3 and later new-scheme patches carry the minimum-revision word (Xen amd.c:279-313).

    Name the digest test as the build-time form of that rule, so a re-pin cannot weaken it.

  • Xen amd.c:327-334 — Xen refuses an equal AMD revision unless forced, so the reload on every thread is Linux's alone (amd.c:813-819,996; e7ad18d1169c). The body lists Xen among the sources of the AMD rules without saying that this rule goes against it.

  • PR body, "The order is a type" — Running's revision should be the unsigned dword that the verdicts compare. Linux judges PCID on boot_cpu_data.microcode < driver_data as a u32 (init.c:288-289), and toyos_cpuvuln::Facts::microcode is a u32 (kernel/cpuvuln/src/lib.rs:77-78). An i32 would withhold PCIDE at -1, where Linux keeps it. x86-64 kernel leaves are global under a declared CR4.PGE, and only a kernel-half change drops them #873's accepted fix-round design (comment 6125061009) does not say that its verdict takes Running; record the hand-off on x86-64 kernel leaves are global under a declared CR4.PGE, and only a kernel-half change drops them #873.

  • PR body, "Metal, the AMD bench" — "sixteen lines, each found 0x08600106" contradicts "What I am unsure of". e7ad18d1169c says SMT threads share the engine, so a sibling may find 0x0860010d. Set the siblings' found column from the reading.

  • PR body, opening — the body says "Every number below comes from a command that was run, logged in design-measurements.txt". Neither 0x08600106 nor Fedora's transition from 0x08600106 to 0x0860010d is in any log at 499ad40d; the evidence branch pr-886 holds that one file. The AMD load arm and its trigger-removed control judge something only if found differs from running on that bench. The owed capture is therefore needed before that row is written.

  • PR body §5 — the body says LICENSE.amd-ucode, "read whole", allows free redistribution on terms it lists as three. The text at 2103bd99… also:

    • forbids referencing AMD in promotion in a way that implies endorsement;
    • makes the redistributor responsible for the rights to "third party technologies" that the microcode may implement, which AMD says it does not convey.

    Whoever accepts the exception should read all five terms.

  • build/licence.rs:82-110 — the new kind is scoped to CPU microcode. The owner's ruling (root CLAUDE.md, Dependencies) names one category: vendor firmware that a device or CPU verifies by its maker's signature. Scope the kind to that category, so the first device firmware is a new row and not a second kind beside this one.

  • PR body, the digest test — the committed copy of Linux's amd_shas.c rows is a third-party file. Root CLAUDE.md requires a NOTICE entry for it, with its hash, upstream and licence, and the design names none.

  • kernel/src/arch/x86_64/cpu.rs:132 — the plan's vendor should be the toyos_cpuvuln::Vendor that cpu::vendor() returns. A vendor decode of its own in toyos-microcode would be a sibling.

  • kernel/microcode/Cargo.toml:6 — the description says Intel only, and becomes false once amd lands.

  • PR body, the reseal arm — after_console runs before mm::init, so the resealed copy of 112,640 bytes has to be a 16-byte-aligned static compiled only with boot-actuators. The design should say where it lives.

  • issues/the-kernel-loads-no-cpu-microcode.md — the body does not say whether the branch deletes the issue at landing, and Roast 4 says the exit holds on the benches only.

DESIGN NEEDS CHANGES: a CPU that reports revision 0xffffffff loads nothing and is refused by name on both makers, as Xen does; drop the guest assertion of the hypervisor line, and rewrite that exit in the branch's own issue; replace the host test of which half of MSR 8BH each maker reports with a revision constructor per maker.

@Japabu

Japabu commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator Author

Design acceptance, by the orchestrator, with the review's named changes and NOTEs (#886 (comment)). This follows the owner's standing ruling: the manufacturers' documents and the published state of the art, Linux and Xen. The build is the body's design with these changes:

  1. Revision 0xffffffff loads nothing on either maker and is refused by name before select, as Xen does. A host test holds it. Revisions are the unsigned dword throughout, Running's included, as Linux and toyos_cpuvuln::Facts::microcode compare them.
  2. The guest assertion of the hypervisor line is dropped. The guest exit in issues/the-kernel-loads-no-cpu-microcode.md rests on the QMP reading.
  3. One revision constructor per maker for MSR 8BH's half, with no host test of the shift.
  4. The NOTEs, taken:
    • Roast 1 restated: the cost of an unreported fault before the IDT is ToyOS's own, and it buys the PCIDE verdict nothing until an Alder Lake or Raptor Lake file is embedded;
    • the EntrySign cutoff rule, named in its build-time form;
    • Xen's equal-revision divergence stated;
    • the siblings' "found" column taken from the reading;
    • the AMD bench capture: now on pr-886 at 9e5f88e5, The kernel loads Intel's CPU microcode early on every CPU, and an AMD CPU says ToyOS has no loader for it #886 (comment);
    • LICENSE.amd-ucode's five terms stated in the body;
    • the licence kind scoped to vendor firmware a device or CPU verifies by its maker's signature, as root CLAUDE.md names the category;
    • a NOTICE entry for the committed amd_shas.c rows;
    • the vendor taken from toyos_cpuvuln::Vendor;
    • the crate description;
    • the reseal arm's 16-byte-aligned static, built only with boot-actuators;
    • the issue deleted at landing, once its exit holds on the benches.

The hand-off with #873: #873 lands first and its PCIDE verdict reads the revision from the CPU. This branch then threads Running into that verdict, so the verdict judges the revision the load verified.

Japabu and others added 5 commits October 12, 2026 16:51
…nything reads what an update changes

`toyos-microcode` gains AMD's containers beside Intel's files (`amd`, as
AMD's `amd_ucode_info.py` and Linux v7.2's `amd.c` read them: patches matched
by the CPUID their Zen patch ID decodes to, chipset-specific patches and a
nonzero minimum-revision word refused as unmodelled, a patch at or above the
running revision loaded, an equal one again on every thread as Linux's early
loader does), whether a CPU loads at all (`Maker::of` over
`toyos_cpuvuln::Vendor`, `may_load` refusing a hypervisor and revision
0xffffffff by name, as Linux and Xen do), one revision constructor per maker's
half of MSR 8BH, revisions as the unsigned dword Linux compares, and the two
files the kernel embeds 16-byte aligned: Intel's 06-8c-01 and linux-firmware
20260916's microcode_amd_fam17h.bin.

`arch::x86_64::microcode::load` runs on the BSP in `after_console`, right
after `init_cr0` and before `random::key` and `control_regs::init`, and on each
AP right after its `init_cr0`, as Intel's guidance asks. Intel's trigger takes
the update data's address, AMD's the patch's, each an `asm!` of its own that
reads memory; family 0x17 then drops the translation of the patch's first and
last byte (Linux c809b0d0e52d). The load is read back, and every CPU that
reads a revision must run the first CPU's. One line per CPU says what it found,
what the file holds and what it runs.

There is no runtime SHA-256 of an AMD patch, where Linux and Xen have one:
their patch is a file the kernel did not ship, and these are inside the kernel
image. A host test holds every patch in the embedded container to Linux v7.2's
`amd_shas.c` (committed under tests/linux/, outside every shipped package),
which records none above EntrySign's cutoff: that is the cutoff rule's
build-time form.

The licence gate gains `Terms::Firmware`, scoped to vendor firmware a device
or CPU verifies by its maker's signature, the one place
LicenseRef-Intel-Microcode and LicenseRef-AMD-ucode pass; every x86-64 ROOT
carries both makers' licence texts under share/licenses/, as each asks.

The `boot-actuators` arm `microcode-reseal` hands the BSP the T14's update with
its header's revision raised to 0xbf and its checksum resealed, a const-built
aligned static, so the read-back is shown to stop a boot on real Intel. The
`microcode` metal row holds every CPU's line to Linux's reading of the same
machine: the T14's cpuinfo, and the AMD bench's capture, committed under
tests/metal/amd-linux/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Clippy's type_complexity refused the boxed closure it held per signature.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
@Japabu

Japabu commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator Author

Ruling after the hung negative controls. The T14 t14-reseal arm and the AMD amd-trigger-removed arm both hung, and both needed a power cycle. The log partitions saved before each flash were read.

Cause. The BSP loads in after_console, before power::init_reset decodes the FADT's reset register, and on the AMD bench before any clock exists. A panic there takes the early-panic branch. That branch finds no reset to hand the machine back (and on AMD no clock to time a hold), so it holds the panel for good. On AMD the failed read-back is shown: the control read 0x8600106 where it wanted 0x860010d. On the T14 it is not yet separated from a fault at the trigger before the IDT, because the partitions cannot tell the two apart.

Ruling: a failed read-back is a refusal, not a panic. By the vendors' documentation, a microcode update the processor does not take leaves it running the revision it had. The CPU's own revision register (IA32_BIOS_SIGN_ID, 8BH) is the verdict, and that is what the kernel reports. So:

  1. verified stops asserting. A mismatch is a new Outcome (for example refused <want>: reads back <read>), the CPU runs the revision it reads back, and agree takes that value. The load sites do not move, so CPUID, RDRAND and RDSEED still read after the load.
  2. The judge's microcode_lines reds a refused line on both benches, on a boot that completes. A host case holds it.
  3. The module header and the body state this, citing Intel's SDM and AMD's documentation. The two statements this run showed false go: §8's "the panic's reset is one", and the header's "every failure … is a panic, which reports before the IDT".
  4. The microcode-reseal admission in FLASHABLE gets a reason that is true without the panic reset.

Filed separately, not fixed here: on x86-64 a panic before power::init_reset holds the machine for good, and on AMD so does every panic before clock::init. This run is its evidence.

Japabu and others added 4 commits October 12, 2026 21:43
…os-microcode

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…tes Linux or Xen

Both negative-control arms of the microcode row hung their benches: the
read-back's panic came inside after_console, before power::init_reset
decodes the reset and, on the AMD bench, before any clock can time the
panic's bound, so the panel was held until a power cycle. The ruling on
#886 (comment 6131006022) makes a failed read-back a refusal: by the SDM
(Vol. 3A §12.11.7.1, §12.11.7.2 Example 12-10) and AMD's PPR 55922
(MSR0000_008B), MSR 8BH after a load is the revision the CPU runs, so a CPU
that does not take an update runs what it reads back. The loader now says
`refused <update>` with that read-back as `running`, holds it to the
machine's like any other, and the boot goes on; the metal judge reds any
refused line.

By the owner's clean-room ruling (#902), the judge is no longer held to a
Linux reading of either bench but to the update each maker's embedded file
holds for it, Linux's amd_shas.c and the AMD bench's Linux capture are
deleted with the digest test that read them, and every Linux and Xen
citation is replaced by Intel's or AMD's document or removed. The word at
patch offset 12 is named as AMD's parser names it, mc_patch_data_checksum.

A panic before the reset register is read holds the machine for good: filed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…rocode

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
@Japabu Japabu changed the title The kernel loads pinned Intel and AMD microcode on every CPU before anything reads what an update changes The kernel loads pinned Intel and AMD microcode on every CPU before anything reads what an update changes, and a CPU that refuses one says so Oct 12, 2026
@Japabu

Japabu commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator Author

Round 2 on metal, at e2b398cb6, run by the orchestrator from agents/886-r2/metal/request.txt. Each image's hash was checked by the runner before the flash, and each stick's log partition was saved before it. No arm hung: every boot completed and came back.

arm judge reading
T14 head exit 0, 1 passed
T14 reverted (m3) exit 1 "expected one microcode line from each of {0..7}, got []"
T14 reseal exit 1 (judged from its tree b7a7b062a) cpu0 found 0xbe refused 0xbf running 0xbe; cpus 1-7 current 0xbe; red on "cpu0 refused the update it was handed and runs 0xbe"
AMD head exit 0, 1 passed
AMD reverted (m3) exit 1 no microcode line
AMD no-INVLPG (m4, reported) exit 0, 1 passed
AMD trigger removed exit 1 cpu0 refused, running 0x8600106; red on "cpu0 refused the update it was handed"

The T14 reseal arm answers round 1's open question: the old hang was the panic hold, not a fault at the trigger, since with the refusal in place the boot completes. One thing to check in review: the judge rebuilt the reseal image from b7a7b062a with sha256 55bec413…, where the booted image was c6d44fe8…. The verdict reads the booted image's kernel log. The readbacks are under agents/886-r2/metal/ (the reseal judge under t14-reseal-judge/).

@Japabu

Japabu commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #886 at e2b398cb6, round 2, against .claude/agents/reviewer.md and root CLAUDE.md on origin/main (5096551ca; b680a973b, #873, has landed since, and git merge-tree of it with this head is clean).

Size. git diff --shortstat origin/main...e2b398cb6: 24 files, +1568 −521.

  • Production: +835 −212, net +623.
  • Tests: +578 −241, net +337.
  • Records and data: NOTICE +34, licence text +64, issues +57 −68, and the container.

The deletion this review names is under BLOCKER 4.

Round 1's BLOCKERs (design review, comment 6126224559)

  • CLOSED — revision 0xffffffff loads nothing and is refused by name on both makers. Covered by may_load / Unloaded::Disabled (kernel/microcode/src/lib.rs) and revision_0xffffffff_loads_nothing; the round's run.out shows the host suite green at this head.
  • CLOSED — the guest assertion of the hypervisor line is dropped. No guest test reads the line, and the issue's guest exit rests on the QMP reading.
  • CLOSED — one constructor per maker reads MSR 8BH's half (Revision::from_sign_id, Revision::from_patch_level), and nothing tests the shift.

The ruling after the hung controls (comment 6131006022): built.

  1. taken answers Outcome::Refused { update, running }, agree takes the read-back, and the load sites have not moved (kernel/src/arch/x86_64/microcode.rs:81-88,195-200).
  2. microcode_lines reds a refused line on any machine, and microcode_verdict holds that for a T14 BSP and for the AMD bench. j1 turns it red.
  3. The module header cites SDM §12.11.7 and 55922 MSR0000_008B, and both false statements are gone.
  4. FLASHABLE's reason no longer rests on the panic reset.

On metal, both negative controls now finish their boots and red the row. The T14 reseal arm reads found 0xbe refused 0xbf running 0xbe and the AMD trigger-removed arm reads refused 0x860010d running 0x8600106, as the readbacks' kernel.logs show.

The image-hash question: the verdict stands.

  • The judge directory's kernel.log is byte-identical to the booted readback's (sha256 6f3a20ed… in both). That log names supervisor: build b7a7b062a… clean and actuators: …,microcode-reseal,….
  • The booted image is c6d44fe8…, the hash the request gives.
  • 55bec413… was rebuilt in a second checkout (toyos-microcode-reseal) of the same commit. It differs from the booted image in 2,388,453 bytes, spread over the ESP, loader and ROOT ranges. Three tracked defects account for that:
    • issues/two-checkouts-of-one-tree-build-different-guest-bytes.md (the kernel and ROOT, and the loader's per-checkout key);
    • issues/an-images-guids-are-drawn-from-the-hosts-random-source.md;
    • issues/an-images-signed-version-and-its-fat-dates-are-the-hosts-clock.md.
  • Both images contain b7a7b062a… once.
  • m1 changes only the row's registration, so the judge that read the log is this head's microcode_on_metal.
  • Every other arm's log names the tree its request gives (e2b398cb6, 1e92b3edc, 406b5863d, 5b029c0a8, 0cb620cae).

BLOCKER

  1. kernel/microcode/src/amd.rs:15-18,125,161-165 — this matches a patch by the CPUID its patch ID decodes to and never reads the equivalence table. The owner has ruled that a patch is matched the way AMD's own parser matches it, through the equivalence table. Required:

    • read the table and match the CPU's CPUID.01H:EAX to its processor ID, and that ID to the patch;
    • refuse a malformed table by name;
    • delete named;
    • add a host test whose container's table maps 0x00860f01 to a processor ID other than the one in a patch whose ID decodes to 0x00860f01, and which expects NoMatch.

    The implementer then runs the mutation that puts back named(patch.revision.0) == signature.0 in place of the table lookup, and that test must turn red. Every container the current tests build has a zeroed 16-byte table (amd/tests.rs container), so the table is never read and no test today can fail on how a patch is matched.

  2. kernel/microcode/src/amd.rs (whole module), amd/tests.rs — the AMD reader was not built clean-room. Root CLAUDE.md, as Another implementation's source is read only clean-room, and the tree names Linux only as a host platform or a libc interface #902 left it, and the owner's ruling require two steps: a reader writes the facts of AMD's amd_ucode_info with no implementation cited, and a builder works from those facts alone. Nothing on the record is such a facts specification:

    • r2/sources/excerpts.txt holds no fact from the tool;
    • the body cites amd_ucode_info.py directly as the builder's source.

    The behaviours this round kept are the ones round 1's design took from reading Linux's amd.c and Xen:

    • the patch-ID decode;
    • skipping the table;
    • the chipset refusal;
    • the family-0x17 INVLPG;
    • the equal-revision reload.

    Taking out the citations did not change where they came from. amd.rs:41 still names the field layout by a C struct name, struct microcode_header_amd, which the cited Python tool does not declare. Fix: rebuild the container reader from a facts specification written by a separate reader of amd_ucode_info (provenance kept in the reader's evidence, the specification never committed), and drop every behaviour that specification and AMD's documents do not state from the parser, unless it is kept under BLOCKER 3.

  3. kernel/microcode/src/amd.rs:24-26, :63-67 — the owner's third ruling is not met. Each undocumented behaviour has to be stated as undocumented in the module header, with the measurement behind it where one exists. The header names no measurement for either behaviour.

    • Its claim that "the read-back is the CPU's verdict on both" is false of the equal reload. On amd-head, cpus 1, 3, 5 and 7 read found 0x860010d loaded 0x860010d, so their read-back is the same with or without the reload. If the rule were strictly newer they would read current 0x860010d, and microcode_on_metal would still pass.
    • The header says nothing about what m4 measured for INVLPG.
  4. kernel/microcode/src/amd.rs:61-67,167-170, kernel/src/arch/x86_64/microcode.rs:170-173, amd/tests.rs:93 — the family-0x17 INVLPG has no document and no measurement behind it. The only measurement on record goes the other way: amd-no-invlpg (m4, tree 0cb620cae) reads the same eight lines as amd-head, passes the row, and completes in 1314 ms against 1318 ms. Delete Patch::leaves_its_mapping_uncached, family, the two cpu::invlpg calls in load_amd, and a_family_0x17_patch_drops_its_mapping_and_a_later_familys_does_not. The alternative is to put on the record a measurement that backs the step, and none does today. Root CLAUDE.md: not knowing whether code is needed is no reason to keep it.

  5. PR body, "Gates" and "Metal" — the hardware readings are not evidence at this head.

    • The body still reads "every metal row: not run".
    • The readings sit in an orchestrator comment that links local scratch paths.
    • ToyOSOrg/evidence pr-886 at 8b6b8027 holds only the staging (r2/metal/*.stage.log): no judge log, no kernel.log, no boot.txt.

    Publish each arm's judge command, exit and judge log, with its readback's kernel.log and boot.txt, on the evidence branch, and write them into the body:

    • t14-head 0;
    • t14-reverted 1;
    • t14-reseal 1, judged from b7a7b062a;
    • amd-head 0;
    • amd-reverted 1;
    • amd-trigger-removed 1;
    • amd-no-invlpg 0, with its phase times beside amd-head's.

    BLOCKERs 1 to 3 change the AMD reader, so its AMD arms have to be booted again at the new head.

NOTE

  • PR body, "Metal" — false of the record. It expects "sixteen CPUs loaded 0x860010d" on the AMD bench, but every AMD readback says SMP: roster full at 8 CPUs and 8 of 16 MADT cpus online.
  • PR body, "Before it lands" / design acceptance's hand-off — x86-64 kernel leaves are global under a declared CR4.PGE, and only a kernel-half change drops them #873 has landed as b680a973b. Its PCIDE is decided by PCID and INVPCID (control_regs.rs:539-546) and reads no microcode revision, so the accepted Running witness has nothing to thread into, and this head builds none. Merge origin/main and have the body say the hand-off is void, citing b680a973b.
  • issues/the-kernel-loads-no-cpu-microcode.md — the T14 half of its exit is now met at this head. Delete it in the head whose AMD readings meet the AMD half, with the evidence in the commit message.
  • tests/common/metal.rs:872-892 (off this branch; file it, don't fix it here) — read_readback does not hold the booted log's supervisor: build to the tree doing the judging. The t14-reseal-judge run also overwrote that directory's image.img at 01:41 with an image that was never booted, so a readback directory no longer proves which image produced its log.
  • ToyOSOrg/evidence pr-886 r2/metal/make.py, stage.sh, r2/mut/run.sh, make.py — this round's evidence was produced by Python and shell scripts of ToyOS's own making. Root CLAUDE.md says ToyOS writes none, and the harness's own --metal-readback staging and cargo test filters already do the job.

SEND BACK

@Japabu

Japabu commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

Ruling after round 2's review (#886 (comment)): #886 lands Intel's loader alone, and the AMD loader leaves this branch.

Intel's half is built from the SDM, judged on the T14 (head green, both controls red, the reseal arm refused as ruled), and owes nothing. AMD's half owes a clean-room reader (BLOCKER 2), matching by the equivalence table (1), and undocumented behaviours stated with their measurements (3). Holding Intel's half for that work delays it for nothing. So:

  1. The AMD container reader, amd.rs, its tests and the family-0x17 INVLPG (BLOCKER 4) are deleted from this branch. On an AMD CPU the kernel loads nothing and logs by name that it has no AMD loader. The AMD row expects that line.
  2. issues/the-kernel-loads-no-cpu-microcode.md keeps the AMD half open. Its exit is a loader built from a facts specification written by a separate reader of AMD's amd_ucode_info (never committed). It matches through the equivalence table, with the host test BLOCKER 1 names, and states each undocumented behaviour with its measurement. The T14 half is recorded as met by this branch.
  3. BLOCKER 5: publish every arm's judge log, kernel.log and boot.txt on pr-886, and write them into the body. The arms at the new head are run again: T14 head and the reseal control, and AMD head, which must show the no-loader line.
  4. The NOTEs are taken: the roster count, the void x86-64 kernel leaves are global under a declared CR4.PGE, and only a kernel-half change drops them #873 hand-off citing b680a973b, and the readback-provenance issue filed. The evidence is produced with the harness and cargo, not scripts of ToyOS's own.

Japabu and others added 2 commits October 13, 2026 02:24
…as no loader for it

The owner's ruling after round 2's review
(#886 (comment)): the
AMD container reader was not built clean-room, matched a patch by its decoded
ID rather than the equivalence table, and carried behaviours no document or
measurement backs, among them the family-0x17 INVLPG that the no-invlpg arm
showed changes nothing. It leaves this branch.

- amd.rs, its tests, the embedded container, its NOTICE section, its licence
  text, its ROOT copy and its licence-gate row are deleted, and with them
  Maker, Revision::from_patch_level and the kernel's AMD trigger and INVLPG.
- toyos_microcode::loader admits Intel alone; any other vendor's CPU logs
  "loads nothing: ToyOS has no <Vendor> microcode loader" and reads nothing
  more.
- With one maker left, the intel module folds back into lib.rs, where main
  has the reader, and Choice is no longer generic.
- The metal judge holds the AMD bench to that line on every CPU; the host
  test accepts it on eight CPUs, the roster the bench brings up, and refuses
  an AMD line that read and loaded.
- issues/the-kernel-loads-no-cpu-microcode.md keeps the AMD half open with
  the ruling's exit; the T14 half is recorded as met.
- issues/a-metal-readback-does-not-prove-which-image-wrote-its-log.md files
  the review's readback-provenance note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
@Japabu Japabu changed the title The kernel loads pinned Intel and AMD microcode on every CPU before anything reads what an update changes, and a CPU that refuses one says so The kernel loads Intel's CPU microcode early on every CPU, and an AMD CPU says ToyOS has no loader for it Oct 13, 2026
@Japabu

Japabu commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

Round 3 on metal, at dfee7fa3d, run by the orchestrator from agents/886-r3/metal/request.txt. Each image hash was checked by the runner, and each stick's log partition was saved before its flash.

arm judge (microcode) reading
T14 head exit 0, 1 passed
AMD head exit 0, 1 passed the no-loader line
T14 reverted (m3) exit 1 "expected one microcode line from each of {0..7}, got []"
AMD reverted (m3) exit 1 the same
T14 reseal (judged from 117f0d454) exit 1 cpu0 refused, runs 0xbe

Every arm reads as the request predicted. The judge logs are beside each readback under agents/886-r3/metal/.

@Japabu

Japabu commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #886 at dfee7fa3d, round 3, against .claude/agents/reviewer.md and root CLAUDE.md on origin/main (52e32385d; the brief named 6080e839d, and #894 has landed since).

Size. git diff --shortstat origin/main...dfee7fa3d: 19 files, +705 −119.

  • Production: +412 −43, net +369.
  • Tests: +182 −7, net +175.
  • Records: NOTICE and issues/, +111 −69.

The production growth is the loader the issue asks for. Nothing in it can be deleted or merged into something that already exists.

Round 2's BLOCKERs (comment 6135201083)

  1. CLOSED: the equivalence table. The reader has been deleted (ruling 1). At this head, git grep finds no amd.rs, named, Maker, from_patch_level, AMD_TRIGGER, load_amd, amd-ucode or AMD-ucode-license outside issues/. The issue's exit carries the host test the BLOCKER named.
  2. CLOSED: clean-room. Deleted with the reader. The issue's exit holds the requirement.
  3. CLOSED: undocumented behaviours. Deleted with the reader. The issue's exit holds the requirement.
  4. CLOSED: the family-0x17 INVLPG. leaves_its_mapping_uncached, both invlpg calls and the test are gone.
  5. OPEN: readings published. Round 2's seven arms are on pr-886 at f17cea3b, each with a judge log, kernel.log and boot.txt, masked, and each log's supervisor: build names its tree. The arms at the new head, which ruling 3 requires, are not published. See BLOCKER 1.

The split ruling (comment 6135209087)

  1. Built. toyos_microcode::loader admits Vendor::Intel alone, and load returns before any MSR read on any other vendor. The AMD row expects the no-loader line. The AMD reader is gone whole: its module, tests, container, licence, NOTICE section, build/licence.rs row, kernel trigger and INVLPG. FIRMWARE_ONLY holds only LicenseRef-Intel-Microcode. h1 reds a_vendor_toyos_has_no_loader_for_loads_nothing (r3/mut/h1-loader-admits-amd.log L19, exit 101).
  2. Built, apart from the slug (BLOCKER 2). The issue is open, its AMD half is open, its T14 half is recorded as met, and its exit is the ruling's.
  3. Half built. Round 2 is published. Round 3 is not (BLOCKER 1).
  4. Built:
    • microcode_verdict uses 8 CPUs on both benches;
    • the body voids the hand-off, citing b680a973b;
    • issues/a-metal-readback-does-not-prove-which-image-wrote-its-log.md is filed, with an owner and an exit;
    • r3/ holds no script.

Evidence, checked

  • a6963e0d r3/ holds:
    • host at dfee7fa3d, exit 0 ("Host: 76 step(s), all green", L8966);
    • host at a8130e0e4, exit 0. git diff a8130e0e4 dfee7fa3d is two comment lines in tests/toyos.rs;
    • both --build-only runs, exit 0;
    • the guest suite at a8130e0e4, exit 0, 62 of 62 (L1133), with its load;
    • j1, j3, j4 and h1, each with its patch and log, exit 101, and the porcelain restored;
    • the staging, the request, and m1 and m3.
  • m3 reverts every production file and keeps the row and the tests, as a negative control should.

Round 3's metal run, read from the readbacks the brief names

  • Every image.img hashes to its request's sha256 (acf803b1…, 009a7959…, ac488ca6…, 58d5e9a6…, 1bc2bb99…), so no judging overwrote one.
  • Each kernel.log's supervisor: build names its arm's tree.
  • t14-head: 8 lines, current 0xbe running 0xbe. The judge passes ("1 passed, 0 failed").
  • amd-head: 8 no-loader lines, with roster full at 8 CPUs. The judge passes.
  • t14-reseal, judged from 117f0d454: cpu0 reads found 0xbe refused 0xbf running 0xbe on a completed boot, and the judge exits 1 on "cpu0 refused".
  • Both m3 arms: "got []", and the judge exits 1.

The run says what the orchestrator's comment says. None of it is on the record the body cites.

main moving past b680a973b does not matter here.

  • git merge-tree --write-tree dfee7fa3d 52e32385d exits 0 (8ebec1136).
  • Ten first-parent commits have landed since b680a973b. None of them touches:
    • kernel/src/arch/x86_64/{boot,smp,cpu}.rs or kernel/src/actuator.rs;
    • kernel/src/main.rs's order;
    • kernel/cpuvuln, whose Vendor loader matches exhaustively;
    • kernel/microcode, build/licence.rs, NOTICE or tests/metal.
  • main and the branch both change tests/toyos.rs, tests/checks.rs and build/build.rs, but in disjoint hunks. The merged tree still has METALCASE, the BTreeSet import, Readback::cpus and microcode_on_metal.
  • The merge queue runs host and guest / suite on the merged commit, and that is the gate for semantic drift.
  • No path the metal readings measured has moved, so they stand.

BLOCKER

  1. PR body "Gates" / "Metal", ToyOSOrg/evidence pr-886. Ruling 3 and round 2's BLOCKER 5 are not met at this head:

    • the body still says "every metal row at this head: not run";
    • the five arms' readings exist only in the orchestrator's local scratch and in comment 6139079680;
    • r3/ at a6963e0d has no readings/.

    Publish under r3/readings/ each arm's judge command, its exit as a recorded number, its judge log, kernel.log and boot.txt, and write them into the body's table. The arms are t14-head 0, amd-head 0, t14-reverted 1, amd-reverted 1, and t14-reseal 1 judged from 117f0d454.

    Mask them as r2/readings was masked. The local boot.txt files carry each machine's vendor, model and BIOS in the clear, and the judge logs carry home-directory paths.

  2. issues/the-kernel-loads-no-cpu-microcode.md. The slug is now false of the tree: the kernel loads Intel's microcode. issues/README.md ("Slugs") requires that a slug the tree has refuted be "renamed by the work that takes it up, with every citation moved". Rename it, for example to issues/the-kernel-loads-no-amd-microcode.md, and move its one citation in issues/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md:30 in the same diff.

    • That edit is the one a rule names, so Prose allows it.
    • Ruling 2 keeps the AMD half open. It does not fix the path.

NOTE

SEND BACK

Japabu and others added 2 commits October 13, 2026 07:48
…clean-room rule as root CLAUDE.md gives it

The kernel loads Intel's microcode at this branch, so "the kernel loads no
CPU microcode" is refuted; issues/README.md's "Slugs" has the work that
takes an issue up rename it and move every citation, here the security
track's list.

The AMD paragraph and the exit said the reader must have read no other
implementation. Root CLAUDE.md lets the source be read, and asks only that
one agent write a specification of facts citing no implementation and
another build from it alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
@Japabu

Japabu commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #886 at 56f08c24b, round 4, against .claude/agents/reviewer.md and root CLAUDE.md on origin/main (52e32385d).

Size. git diff --shortstat origin/main...56f08c24b: 21 files, +718 −128.

  • Production: +412 −43.
  • Tests: +182 −7.
  • Records (NOTICE, issues/): +124 −78.

These match the body's figures, read from --numstat. Production is unchanged since round 3, and round 3 accepted its growth.

What changed since dfee7fa3d

  • 7cae6b13c merges origin/main at 52e32385d. Its tree is 8ebec1136, the same tree git merge-tree --write-tree dfee7fa3d 52e32385d writes (exit 0, empty diff), so the merge resolved nothing by hand.
  • 56f08c24b renames the issue and moves its one citation.
  • The branch's own patch against its merge base differs from round 3's only in issues/.

Round 3's BLOCKERs (comment 6139149316)

  1. CLOSED: metal readings published. pr-886 70025e35 r3/readings/{t14-head,amd-head,t14-reverted,amd-reverted,t14-reseal}/ each hold judge.cmd, judge.exit, judge.log, kernel.log and boot.txt.
    • The exits read 0, 0, 1, 1, 1.
    • Each kernel.log's supervisor: build names its arm's tree: dfee7fa3d ×2, e4b2817c3, 2e8aba69f, 117f0d454.
    • t14-head: 8 lines current 0xbe running 0xbe. Judge: "every CPU runs 0xbe", "1 passed".
    • amd-head: 8 no-loader lines and roster full at 8 CPUs. Judge: "1 passed".
    • Both m3 arms read "got []", and both judges exit 1.
    • t14-reseal: cpu0 reads found 0xbe refused 0xbf running 0xbe on a completed boot. The judge, run from 117f0d454, exits 1 on "cpu0 refused".
    • boot.txt and the judge logs are masked: <vendor>, <model>, <bios>, <path>, <user>@<amd-bench>.
    • The body's table links each file.
  2. CLOSED: the slug. issues/the-kernel-loads-no-cpu-microcode.md is now issues/the-kernel-loads-no-amd-microcode.md. git grep at 56f08c24b finds neither the old path nor the old heading anywhere, and finds the new slug cited once, at issues/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md:30.

Round 3's NOTEs

  • Applied: the issue states the clean-room rule. Its AMD. paragraph and exit now give root CLAUDE.md's "Zero legacy" sentence: one agent writes a specification of facts citing no implementation, keeping the provenance in its own evidence, and another builds from it alone, handed it in its brief and never committed.
  • Applied: the body's list of what main has taken. The ten first-parent commits b680a973b..52e32385d are the ones the body names. None of them touches kernel/src/arch/x86_64/{boot,smp,cpu,control_regs}.rs, kernel/src/actuator.rs, kernel/src/main.rs, kernel/cpuvuln, kernel/microcode, build/licence.rs, NOTICE or tests/metal (git diff --stat, empty).
  • Applied: round 2's exits. r2/readings/*/judge.exit at 70025e35 records all seven: 0, 0, 0, 1, 1, 1, 1.

Evidence at this head. pr-886 eaf66e29, r4/gates/:

  • gates.head is 56f08c24ba0b…;
  • ci-host.exit is 0;
  • ci-host.log L9421 reads "Host: 76 step(s), all green". Every FAILED in the log falls inside a === [ci] control step, which must go red.

The guest suite was measured at a8130e0e4. Past that, the branch changes only a comment in tests/toyos.rs, the issue rename, and a merge that main's queue gates. That stands as round 3 accepted it.

No BLOCKER and no NOTE remains.

LAND

@Japabu
Japabu marked this pull request as ready for review October 13, 2026 06:34
@Japabu
Japabu added this pull request to the merge queue Oct 13, 2026
Merged via the queue into main with commit bc8429e Oct 13, 2026
6 checks passed
@Japabu
Japabu deleted the wt/toyos-microcode branch October 13, 2026 06:52
Japabu added a commit that referenced this pull request Oct 13, 2026
Japabu added a commit that referenced this pull request Oct 13, 2026
tests/toyos.rs: #886's `microcode` row and this branch's `ps2server_arms`
were each added after `metal_sim_scanout_wc`; both are kept, each on
METALCASE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant