Skip to content

A metal row declares its benches, a boot names its bench, and judges name the one they judged - #1254

Merged
Japabu merged 4 commits into
mainfrom
metalrows
Nov 11, 2026
Merged

Japabu merged 4 commits into
mainfrom
metalrows

Conversation

@Japabu

@Japabu Japabu commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

A METAL row named its boots and its judge and nothing of the machine it was written for, so a boot of one bench carried every row riding its label:

  • the T14's testcases boot ran the AMD-Vi rows' deliberate DMA fault (test_rs_usbd_spare_fault) and was red on amdvi_*, idle_entered and every judge that requires a clean kernel log;
  • the AMD bench's testcases boot ran the T14's I219 claim (test_rs_pci_reclaim exited 1 there), and its boot:benchcase judge was red on the two I219 rows;
  • every failed job read "exited N on the T14", whichever bench ran it;
  • a MACHINE_TESTS/SCREEN_TESTS name with no dispatch arm compiled and was found only by a boot.

Resulting behavior

  • A row declares its benches (on:): On::Every, On::Having(&[Device::…]) (each bench that has those parts: I219, embedded controller, HWP, Tiger Lake GPU, VT-d, AMD-Vi), or On::Only(Bench) where the judge is written against one bench's own tables. select takes a row only for the run's bench and prints each left row with why ([metal] not run on the AMD bench: claim_reuses_its_remapping_entry needs an I219, which the AMD bench has not); a left row's jobs are in no image; a run whose every row is left is refused; a row no bench runs fails the registration check.
  • A boot names its bench itself. The kernel's first record already carries CPUID.01H:EAX (microcode: cpu0 Intel signature 0x806c1 …). Bench::of_log maps it to t14/amd, every Readback carries it, and the judges that told the benches apart three different ways (signature, ACPI row, a search of both benches' tables) match on Readback::bench exhaustively. A failed job says on the AMD bench; a run names its bench in its opening line, each boot's line and the timings line, which no longer prints SMBIOS vendor, product and BIOS strings.
  • Judging needs no bench flag. A run's bench is its readbacks' where its directory holds any; a directory mixing benches, or a --metal-bench disagreeing with its readbacks, is refused by name; a boot that ran on another bench than the run's is red with every row. Readbacks written before this change judge unchanged (every boot has written that record).
  • A run's machine is its bench's own. Bench::host names each bench's machine (toyos@bench-t14, toyos@bench-amd), and target_of resolves a run's bench and machine together. The machine is the bench's own unless --metal-host names another, and a --metal-host that is the other bench's machine is refused by name, whether the run stages, drives or judges. Every invocation names its --host, the T14's too, and toyos-metal's own default is the T14's Bench::host. Staging the AMD bench is --metal-bench amd alone; the T14 needs no flag. A directory only one of whose boots answered, which is staged again, is staged for its readback's bench and that bench's machine. --metal --list --metal-bench amd prints the AMD plan.
  • MACHINE_TESTS and SCREEN_TESTS carry each test's function, so a registration with no dispatch arm does not compile. run_machine_test/run_screen_test and their catch-all arms are deleted; the eight screen tests whose bodies were arms are functions.

The T14's plan is main's less exactly the AMD bench's three jobs (test_rs_idle_entered, test_rs_usbd_spare_fault, test_rs_usbd_spare_vector), in main's order: test_rs_pci_reclaim leaves the shared TESTCASES arm for the one row that judges it.

Consequential decisions

  • The bench label is derived from the boot, not from the host or Ubuntu. The CPUID signature is a processor model, not a machine identifier, and it is in every readback ever written. Two benches with one signature would need a second fact; bench.rs says so and a host test holds the signatures distinct.
  • The timing record still keys on SMBIOS strings read over ssh before the flash (boot.txt's machine_*). Moving it to the bench needs a firmware identity the boot itself reports and keeps the pre-flash gate; that remainder is issues/a-metal-timing-record-names-its-machine-by-what-ubuntu-reads.md (rewritten from the record this closes).
  • Rows declared On::Every are those whose code names no bench-specific part; that is not a claim that each has passed on the AMD bench: issues/no-unfiltered-amd-bench-run-has-been-judged-since-rows-declare-their-benches.md.
  • The bench names its machine; the line only overrides it (the orchestrator's ruling on review). The first round refused --metal-bench amd without --metal-host and --metal-host without --metal-bench instead, which missed a partly answered directory. The default removes both rules, and the one remaining check (no bench's boots on the other bench's machine) sits where bench and machine are resolved for every mode.
  • The staging and judging contract is unchanged: cargo test --test toyos-build -- --metal --metal-readback <dir> <row> stages the T14 with no new flag, the request's lines are cargo run -p toyos-metal -- --image … --readback … --fat32-check --host …, and judging an existing readback directory touches no machine. toyos-metal's command line and boot.txt/verdict.txt are untouched.

Records closed: a-metal-job-that-fails-on-the-amd-bench-is-reported-as-failing-on-the-t14, a-metal-jobs-failure-names-the-t14-on-every-bench, a-metal-judge-says-on-the-t14-for-every-bench (the three duplicates), a-metal-row-names-no-machine-so-another-benchs-boot-carries-it, a-machine-tests-row-with-no-dispatch-arm-is-found-only-by-booting-it. Rewritten to what is left: a-metal-row-names-no-hardware-and-a-bench-without-it-reds → no-unfiltered-amd-bench-run-has-been-judged-since-rows-declare-their-benches; a-metal-run-asks-ubuntu-which-machine-it-is-and-the-boot-says-nothing → a-metal-timing-record-names-its-machine-by-what-ubuntu-reads.

Checks and evidence

Evidence: ToyOSOrg/evidence@c0f6aba8e890 (paths masked; readbacks' SMBIOS strings never published). The second round's logs live under r2/, at 307457007 on main b0533900e. Every log opens with its revision and diff hash; all are e3b0c44298fc1c14, the clean tree. The first round's logs at fbe836956 stay at the branch's root and are cited below where the rebase cannot have changed them.

The change is the harness (tests/toyos.rs, tests/common/metal.rs, tests/checks) and toyos-metal's library, so the checks are the harness's own and that crate's:

  • Rebased onto main d17f22cc3 (head cba026be9), a mechanical rebase; the evidence is under r5/.
  • Earlier, rebased onto main e10b6fd49 (head b7a90efc1) because main conflicted. The evidence is under r4/, all on the clean tree.
  • Earlier, rebased onto main be76e6f85 (head 4e529a08c) for A screen row waits for every line it reads off the panel #1247, which changed screendump_until to take every line a caller reads and edited four run_screen_test arms this branch moves into functions. The evidence is under r3/, all on the clean tree.
    • The four functions (screen_panic_muted, virt_early_panic, virt_early_fault, screen_fatal_behind_a_painter) carry A screen row waits for every line it reads off the panel #1247's wanted/on_the_panel arrays and PLAIN constants. Each equals main's arm at be76e6f85 (armcmp.txt: leading whitespace stripped, name read as the literal; the branch before this rebase, the control, differs in all four).
    • git range-diff of the branch before and after (range-diff.txt): the review commit is unchanged, and the first commit differs only in those four bodies, on both sides of the move. The whole tests/toyos.rs change against main is in toyos-rs-against-main.diff.
    • cargo test --test toyos-build --no-run compiles (exit 0), and cargo test --test toyos-checks passed 49 (log).
  • At 307457007:
    • cargo test -p toyos-metal: 77 passed (log).
    • cargo test --test toyos-checks: 49 passed (log). Among them are the metal ones over masked fixture readbacks of each bench: metal_each_benchs_own_readback_is_judged_as_that_bench, metal_judge_names_the_bench_it_judged, metal_profile_gives_each_bench_its_own_jobs, metal_bench_takes_its_own_rows_and_names_the_rest, and metal_runs_bench_is_its_readbacks_and_else_the_lines. That last one now covers both cases review found: the AMD bench's testcases readback without its watchdog companion stages the AMD bench on toyos@bench-amd, and the T14's readback with --metal-host toyos@bench-amd is refused.
    • Clippy on toyos-build and toyos-metal, all targets, the workspace's adopted lints, -D warnings: exit 0 (log).
    • The build system's lib tests (cargo test --lib): 384 passed, 1 failed (log). The failure is llvm::tests::the_caller_s_environment_reaches_neither_the_build_nor_the_key, the macOS git/SDKROOT defect recorded in issues/the-llvm-environment-test-breaks-git-on-macos.md, in build/llvm.rs, which this PR does not touch.
  • Negative controls for this round (dir), each a checked patch applied, built, run and reverted. Each fails the harness tests (exit 101), and the restored tree passes:
    • target_of allowing the other bench's machine (host-unchecked);
    • target_of defaulting every bench to the T14's machine (t14-by-default, the defect review found).
  • Plans: both benches' plans at 307457007 are identical to the first round's (dir). compare.txt: the T14's plan is main's less exactly test_rs_idle_entered, test_rs_usbd_spare_fault and test_rs_usbd_spare_vector, in main's order, every other boot identical. The AMD bench's drops the I219, EC, HWP, Tiger Lake and VT-d jobs and the T14-only acpicase boot. Main's METAL rows did not move with the rebase.
  • Readbacks written before this change (first round, dir; kept local because their boot files carry SMBIOS strings) judge with no bench flag, as the bench their boot names. The T14 one passed 4; the AMD one passed 3, with claim_reuses_its_remapping_entry left out by name.
  • The first round's negative control (dir) is the I219 row declared On::Every. With it, the AMD readback's judge reds the row with "test_rs_pci_reclaim exited 1 on the AMD bench", the original defect, and two host tests fail. Reverted, the 25 metal host tests pass.
  • Staging at 307457007 (dir): boot:testcases for each bench, exit 2, the harness's "staged, not judged". Each prints the rows it leaves out and why. Every invocation names its --host.

Metal. Both benches went down on 2026-11-11, so metal is no longer this PR's landing condition.

  • What ran. The AMD bench booted both boot:testcases images staged at 307457007 before the benches went down, and its loop passed both. Those readbacks were deleted before a judge read them, and the T14 booted neither.
  • Owed on metal, recorded in issues/no-unfiltered-amd-bench-run-has-been-judged-since-rows-declare-their-benches.md. The rows are boot:testcases (testcases and testcases-watchdog), staged with --metal-bench t14 and with --metal-bench amd, on both benches. They are judged with neither --metal-bench nor --metal-host. Main must show:
    • the opening, boot and timings lines name the bench the readbacks name, and request.txt's invocations carry that bench's --host;
    • each image's job list equals main's plan for that bench;
    • on the T14:
      • the testcases log has none of test_rs_usbd_spare_fault, test_rs_usbd_spare_vector or test_rs_idle_entered, and no iommu: DMA FAULT owner=process;
      • no red comes from the formerly carried AMD rows, and every remaining red has its own record;
    • on the AMD bench:
      • the log has none of test_rs_pci_reclaim, test_rs_i219_msi, test_rs_counters_metal or test_rs_acpi_counted;
      • no I219 row is red, failures read "on the AMD bench", and its reds are that record's first slice;
    • loader_watchdog_arms is judged across both boots on each bench.

Not run: the full --ci host (the merge queue runs it), guest rows (no guest behavior changed).

Risks

🤖 Generated with Claude Code

@Japabu

Japabu commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #1254 at fbe8369 (on b566931)

Architecture. This is a simplification. A bench is declared once, as data on the row. The plan is derived from those declarations. The bench of a boot is read from a fact every x86-64 boot already logs. Judges match Readback::bench exhaustively instead of telling the benches apart three ad hoc ways. The dispatch tables carry their functions, so an orphan registration cannot compile. Device earns its place: it gives the reason in each "not run" line and meets the exit of the record it closes ("every metal row declares the hardware it needs"). Having(Vtd) on the Type-C row is honest, since usbd_on_metal reads only VT-d's remappable format. Net: about +180 production lines (common/metal.rs +112, bench.rs about +115, testargs about +18, toyos.rs −68 including the dispatch refactor), about +290 test lines plus 114 fixture lines, and −147 issue lines.

Bench from the CPU signature. It does not identify a machine: CPUID.01H:EAX is family, model and stepping, shared by every unit of that part. It is robust: both branches of microcode::load log signature {eax:#x} on every x86-64 boot, cpu0 before any program runs. Failures are loud: a replaced CPU or stepping reads "names no bench". Two caveats, both acceptable:

  • A boot that dies before cpu0's record is now refused whole ("names no bench") instead of being judged on its loader.log. It is still red.
  • The kernel's message text is the contract.

Plan. I compared plans/list-{main,t14,amd}.out myself. The T14 plan is main's less exactly test_rs_idle_entered, test_rs_usbd_spare_fault and test_rs_usbd_spare_vector, in main's order, and every other boot is identical. The AMD plan drops acpicase and the I219, EC, HWP and Tiger Lake jobs.

Staging contract. It is intact: T14 staging with no new flag, toyos-metal's command line unchanged, and offline judging calls no drive.

Records. All five closures meet their exits. The dispatch-arm record goes further than its exit, by type. The rewrites carry the remainders. a-metal-row-names-no-machine…'s exit said "by the SMBIOS identity"; the orchestrator's non-identifying-label brief replaces that, and the change is fine. No citation of a deleted slug remains in the tree.

Blockers

  1. tests/common/metal.rs:893-935 (bench_of) with run at :1016-1066: the "another bench needs --metal-host" guard misses a directory that is only partly answered.
    • answered requires a readback for every boot. A directory holding one of testcases/testcases-watchdog is therefore not judging, and run stages again. This happens, for example, after toyos-metal refused one flash and cleared its readback.
    • bench_of returns the AMD bench from the readback that is there (:921), before the guard arm at :922.
    • With no --metal-host, which the PR says judging does not need, run rebuilds the images and overwrites request.txt with "staged for the AMD bench" invocations that carry no --host. Those invocations boot the T14.
    • The mirror case: T14 readbacks plus --metal-host <AMD machine> and no --metal-bench stage the T14 plan for the AMD machine.
    • Either way, one bench's jobs ride the other's boot, which is the defect this PR closes. It also contradicts the PR's statement that such a request is refused.
    • Fix: check bench and host where invocations are written or run (offline and not judging, or Drive), not only when there are no readbacks. Alternatively, derive the default host from the bench (see suggestions).
    • Test: extend metal_runs_bench_is_its_readbacks_and_else_the_lines with one of two readbacks present.
  2. Rebase required. Current main (Every kernel stack sits above unmapped memory, and an overflow names its stack #1211) conflicts in tests/toyos.rs: it adds the MACHINE_TESTS entry a_kernel_stack_overflow_names_its_stack and its run_machine_test arm, which must become ("a_kernel_stack_overflow_names_its_stack", |test_config| faults::a_kernel_stack_overflow_names_its_stack(test_config)). This is mechanical. The rebase adds only a QEMU machine test, so evidence from the queued metal run at fbe8369 stays valid for the harness. The PR body's "Comments and the README no longer say the kernel writes the log through toyos-fat32 or tell a deleted syscall's history #1224, which touches no file here" is out of date.

Suggestions

  • Simplification. Map the default host from the bench (amd → the AMD bench's alias, just as toyos-metal already defaults to bench-t14) and keep --metal-host as an override. --metal-bench amd would then be enough to stage, two refusal arms would go, and blocker 1 would be fixed by construction.
  • tests/toyos.rs:7463: let bench = match back.bench { … } binds AcpiTables to the name bench. Rename it tables.
  • issues/there-is-no-wifi.md: rows "declare … the radio it needs (toyos_metal::bench::Device)", but Device has no radio. Say that a radio row adds its Device.
  • Evidence. The host/ logs open with rev only, while the README says every log carries its diff hash.
  • Testing policy. The harness is touched, so the orchestrator's policy asks for the full --ci host. The merge queue runs it; whether to run it earlier is the orchestrator's call.

Metal (LAND-pending-metal once the blockers are fixed)

Judge each bench's testcases and testcases-watchdog with no --metal-bench or --metal-host on the judge line. The results should show:

  • the opening and boot lines name the bench, and the left rows match the staging evidence;
  • the images' job lists equal plans/list-*.out;
  • the T14 testcases log carries none of test_rs_usbd_spare_fault, _vector or idle_entered, and no iommu: DMA FAULT owner=process;
  • the AMD log carries none of test_rs_pci_reclaim, i219_msi, counters_metal or acpi_counted;
  • on the T14, no red comes from the formerly carried AMD rows (console_uart_driven/klogd, idle_entered, amdvi_*), and every red that remains has its own record;
  • on the AMD bench, no I219 red, failures read "on the AMD bench", and its reds go to no-unfiltered-amd-bench-run… as its first slice;
  • loader_watchdog_arms is judged across both boots on each bench.

SEND BACK

Japabu added a commit that referenced this pull request Nov 11, 2026
…ends one bench's boots to the other's

A run's bench came from its readbacks, but its machine from `--metal-host`
alone, with the T14 behind no flag. Two refusals guarded that only where no
readback was there, so a directory one boot of two had answered, which is
staged again, was staged for its readback's bench with invocations that named
no host and so booted the T14; and the T14's readbacks with `--metal-host`
naming the AMD bench's machine staged the T14's rows for that machine.

`Bench::host` now names each bench's machine, and `target_of` resolves a run's
bench and machine together: the machine is the bench's own unless
`--metal-host` names another, and one that is another bench's is refused by
name, whether the run stages, drives or judges. Every invocation names its
`--host`, the T14's too, and `toyos-metal`'s own default is the T14's
`Bench::host`. The two refusals go: `--metal-bench amd` alone stages the AMD
bench. The harness test covers both cases above, and the README and records
say how a run reaches its bench.

The judge that binds a bench's ACPI tables calls them `tables`, and the Wi-Fi
record says a radio row adds its own `Device`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu

Japabu commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up review of #1254 at 3074570 (d9495c1 rebased onto b053390, plus a review commit)

Scope. This round checks the round-1 blockers and the review commit d9495c1..3074570: +132/−101 over 11 files.

  • About 40 lines are production: common/metal.rs 32/29, bench.rs +10, lib.rs 3/2 and testargs 3/3.
  • Tests are +50/−37; the rest is the records and the osbench README.

Round-1 blockers

  1. Resolved, by construction. target_of (tests/common/metal.rs:891-905) resolves a run's bench and machine together.

    • The bench comes from bench_of: the readbacks, else --metal-bench, else the T14.
    • The machine is that bench's Bench::host unless --metal-host overrides it. An override that names another bench's machine is refused.

    Every path goes through target_of.

    • main (tests/toyos.rs:8916) is its only caller in the suite, and run takes bench and host: &str from it alone.
    • Both places that write or run commands, request.txt (:1058) and drive (:1083), build their words with invocation(…, host), which now always carries --host.
    • The judge uses the same bench.
    • invocation is the only code that spawns toyos-metal. The other run call (tests/checks.rs:1169) is List mode, which returns before any invocation.

    The tests cover round 1's case and its mirror. a_runs_bench_is_its_readbacks_and_else_the_lines holds all four of these:

    • An AMD testcases readback without its watchdog companion, with no flags, now resolves to (Amd, toyos@bench-amd), so staging again names the AMD machine.
    • The same directory with --metal-host toyos@bench-t14 is refused.
    • The mirror, the T14's readback with --metal-host toyos@bench-amd, is refused.
    • An empty directory with --metal-host toyos@bench-amd is refused.

    Both mutations are effective (r2/negative-control/mutants.log, at 3074570 on a clean tree):

    • host-unchecked fails that test.
    • t14-by-default fails it and the_bench_reaches_the_loop_as_its_host.
    • The restored tree passes.

    Staging and the defaults agree.

    • The staged requests at 3074570 carry --host toyos@bench-amd and --host toyos@bench-t14. toyos@bench-amd is the alias the orchestrator's own run scripts use.
    • A test holds the two benches' machines distinct.
    • Target::bench_t14 reads Bench::T14.host(), so toyos-metal's default cannot drift from the harness's.

    Overrides are compared by name. Another spelling of a bench's machine passes. That is the PR's stated risk, and the readback's own bench check still reds such a boot. It is acceptable for an override.

    The prose matches the code. The records, the osbench README and testargs's docs agree with it, and no instruction file or docs/ page names either flag.

  2. Resolved at b053390. tests/toyos.rs:593 is ("a_kernel_stack_overflow_names_its_stack", |test_config| faults::a_kernel_stack_overflow_names_its_stack(test_config)). Both plans in r2/plans/ match round 1's line for line, apart from their rev/cmd headers.

Suggestions taken:

  • tables;
  • the Wi-Fi record;
  • every r2 log opens with rev 307457007… diff e3b0c44298fc1c14.

The lib red is llvm::tests::the_caller_s_environment_reaches_neither_the_build_nor_the_key. There, xcode-select finds no git under the test's fake SDK, in build/ code this PR does not touch.

Blocker

  1. tests/toyos.rs: the branch conflicts with current main be76e6f.

    • A screen row waits for every line it reads off the panel #1247 (d7a876b) changed screendump_until to take every line a caller reads (&[&str]) and edited four run_screen_test arms.
    • This branch deletes those arms. Their bodies now live in screen_panic_muted (:4502), virt_early_panic (:4558), virt_early_fault (:4645) and screen_fatal_behind_a_painter (:4727).
    • git merge-tree origin/main 307457007 reports a content conflict there.

    The resolution is semantic. Wrapping the old needle as &["PANIC:"] compiles but silently reverts A screen row waits for every line it reads off the panel #1247's fix. Those polls would again stop before late_panic::Nest, the console-check lines, ACPI: GTDT timers: or undefined instruction are painted.

    Fix. Carry A screen row waits for every line it reads off the panel #1247's wanted/on_the_panel arrays and PLAIN constants into the four functions.

    Check.

    • Each function body equals main's arm, so git diff origin/main <head> -- tests/toyos.rs shows only the move.
    • --test toyos-build compiles.

    Inspection settles the move, so no screen row needs to run. Main's two new commits change only issue records, tests/common/qemu.rs and these QEMU screen tests. So no plan, image or metal judge changes: the queued metal run at 3074570 stays valid for the rebased head, and no other host check needs repeating.

    The PR body's "The quit's walk stays in the kernel, and the manual says what a quit request does #1218, tests: two shared-boot members assert what a spawn does on main #1219 and Comments and the README no longer say the kernel writes the log through toyos-fat32 or tell a deleted syscall's history #1224, which touch no file here" also needs A screen row waits for every line it reads off the panel #1247; correcting it is the orchestrator's job.

Metal (LAND-pending-metal once rebased)

Judge each bench's testcases and testcases-watchdog with neither --metal-bench nor --metal-host on the judge line. The results must show:

  • the opening, boot and timings lines name the bench the readbacks name, and request.txt's invocations carry that bench's --host;
  • the images' job lists equal r2/plans/list-*.out;
  • the T14's testcases log has none of test_rs_usbd_spare_fault, _vector or idle_entered, and no iommu: DMA FAULT owner=process;
  • on the T14, no red comes from the formerly carried AMD rows, and every remaining red has its own record;
  • the AMD bench's log has none of test_rs_pci_reclaim, i219_msi, counters_metal or acpi_counted;
  • on the AMD bench there is no I219 red, failures read "on the AMD bench", and its reds go to no-unfiltered-amd-bench-run…;
  • loader_watchdog_arms is judged across both boots on each bench.

SEND BACK. The rebase alone remains. The next round needs to check only the four moved bodies and the compile.

Japabu added a commit that referenced this pull request Nov 11, 2026
…ends one bench's boots to the other's

A run's bench came from its readbacks, but its machine from `--metal-host`
alone, with the T14 behind no flag. Two refusals guarded that only where no
readback was there, so a directory one boot of two had answered, which is
staged again, was staged for its readback's bench with invocations that named
no host and so booted the T14; and the T14's readbacks with `--metal-host`
naming the AMD bench's machine staged the T14's rows for that machine.

`Bench::host` now names each bench's machine, and `target_of` resolves a run's
bench and machine together: the machine is the bench's own unless
`--metal-host` names another, and one that is another bench's is refused by
name, whether the run stages, drives or judges. Every invocation names its
`--host`, the T14's too, and `toyos-metal`'s own default is the T14's
`Bench::host`. The two refusals go: `--metal-bench amd` alone stages the AMD
bench. The harness test covers both cases above, and the README and records
say how a run reaches its bench.

The judge that binds a bench's ACPI tables calls them `tables`, and the Wi-Fi
record says a radio row adds its own `Device`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu

Japabu commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Round-3 review of #1254 at 4e529a0 (rebased onto be76e6f)

Scope. This round checks only round 2's blocker: carrying #1247's screen polls into the four moved functions. Everything else was settled at 3074570.

Architecture. Nothing changed. The head differs from 3074570 only by #1247 and #1249, which came in from main.

Round-2 blocker: resolved

The four bodies equal main's arms. I compared them independently of armcmp.pl. I extracted each arm from run_screen_test at be76e6f, removed 8 spaces of indentation and replaced print_screen(name, with the literal name. The result is byte-identical to the branch's function body, blank lines included, for all four:

  • screen_panic_muted (tests/toyos.rs:4502)
  • virt_early_panic (:4560)
  • virt_early_fault (:4649)
  • screen_fatal_behind_a_painter (:4732)

Each one carries #1247's polls:

  • screen_panic_muted has PLAIN = "late_panic::Nest", and wanted includes PLAIN and &armed.
  • virt_early_panic has PLAIN = "ACPI: GTDT timers:", and its on_the_panel has three entries.
  • virt_early_fault has on_the_panel = ["EARLY PANIC:", "undefined instruction"].
  • screen_fatal_behind_a_painter has &[HELD].

None of them wraps a single needle like &["PANIC:"].

The diff against main shows only the move. git diff origin/main 4e529a08c -- tests/toyos.rs removes every screendump_until, wanted, on_the_panel and PLAIN line from the old arms and adds the same lines in the new functions. There are 13 removed and 13 added, matching one for one, with none missing or changed. The only callers of screendump_until are these four, so no other caller's poll was narrowed.

The range-diff contains nothing else. git range-diff b0533900e..307457007 be76e6f85..4e529a08c gives these results:

It compiles. r3/toyos-build-compiles.log shows cargo test --test toyos-build --no-run at rev 4e529a08c… diff e3b0c44298fc1c14 (the clean tree), with exit 0. r3/toyos-checks.log shows 49 passed, exit 0, at the same revision. I did not rerun them. The moved code is identical to code that compiles on main, against the same screendump_until(&mut self, needles: &[&str], …) signature.

Base be76e6f rather than dda500c: acceptable

Findings

None. The PR body now names #1247 among the rebased-in changes and describes the base choice accurately.

Metal

The criteria in round 2 stand unchanged for the queued run at 3074570.

LAND (pending metal).

Japabu added a commit that referenced this pull request Nov 11, 2026
…on metal

Both benches are down. The AMD bench booted both `boot:testcases` images
before they went, but no judge read the readbacks and the T14 booted neither,
so the judged runs are owed: the record of rows that declare their benches
names the runs, the benches and what main must show.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu

Japabu commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Orchestrator verification, landing under the benches-down rule (metal unavailable): review r3 LAND pending metal. Head 2bde8bd adds only the owed-on-metal record to the reviewed 4e529a0 (verified). The unfiltered boot:testcases judgement on both benches is owed, as recorded.

@Japabu
Japabu marked this pull request as ready for review November 11, 2026 20:03
@Japabu
Japabu enabled auto-merge November 11, 2026 20:03
Japabu added a commit that referenced this pull request Nov 11, 2026
…ends one bench's boots to the other's

A run's bench came from its readbacks, but its machine from `--metal-host`
alone, with the T14 behind no flag. Two refusals guarded that only where no
readback was there, so a directory one boot of two had answered, which is
staged again, was staged for its readback's bench with invocations that named
no host and so booted the T14; and the T14's readbacks with `--metal-host`
naming the AMD bench's machine staged the T14's rows for that machine.

`Bench::host` now names each bench's machine, and `target_of` resolves a run's
bench and machine together: the machine is the bench's own unless
`--metal-host` names another, and one that is another bench's is refused by
name, whether the run stages, drives or judges. Every invocation names its
`--host`, the T14's too, and `toyos-metal`'s own default is the T14's
`Bench::host`. The two refusals go: `--metal-bench amd` alone stages the AMD
bench. The harness test covers both cases above, and the README and records
say how a run reaches its bench.

The judge that binds a bench's ACPI tables calls them `tables`, and the Wi-Fi
record says a radio row adds its own `Device`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Japabu added a commit that referenced this pull request Nov 11, 2026
…on metal

Both benches are down. The AMD bench booted both `boot:testcases` images
before they went, but no judge read the readbacks and the T14 booted neither,
so the judged runs are owed: the record of rows that declare their benches
names the runs, the benches and what main must show.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Japabu added a commit that referenced this pull request Nov 11, 2026
…cks' spawn records in main's form

Main moved under the branch in three places this branch also changes:
#1241 renamed `machine_shutdown_short_stop` to
`machine_shutdown_with_a_thread_spinning`, which is now that name's
`MACHINE_TESTS` entry; #1238 changed `virt_user_mode`'s arm, which this branch
moved into a function and which now carries the change; and #1238 changed the
kernel's spawn record to `spawn: pid=N (total=Xms) <path>` and the
supervisor's to `started logkeeper pid=N`, which the one-clock check's planted
log now writes beside the T14's first record.

#1238's readers no longer read the older form, so the two bench readbacks
this branch carries as fixtures, written before it, read as a boot with no
record of logkeeper's spawn and a job with no spawn record. Their three
lines each are rewritten in the form the kernel and the supervisor now write,
with the same pids and times.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu
Japabu added this pull request to the merge queue Nov 11, 2026
@Japabu
Japabu marked this pull request as draft November 11, 2026 20:09
@Japabu
Japabu removed this pull request from the merge queue due to a manual request Nov 11, 2026
@Japabu

Japabu commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Review r4 of #1254: the rebase onto main e10b6fd49 (head b7a90efc1)

Architecture. This is unchanged since the LAND at round 3. The rebase adds no production code. b7a90efc1 is +9/−7 across three test files: the two fixture logs and one doc comment. The rest of the rebase only carries main's lines into the code this branch moves.

The rebase is mechanical (verified)

  • The range-diff is as claimed. I ran git range-diff be76e6f85..2bde8bdaf e10b6fd49..b7a90efc1. Both review commits (2d41e356c, 149aaf72e) show =. The first commit differs in only three ways:
  • Main is preserved. I compared main's own change (be76e6f85..e10b6fd49) with what the rebase applied to the branch (2bde8bdaf..149aaf72e), ignoring hunk headers and index lines.
    • Outside tests/toyos.rs, the only difference is the one-clock test's planted first record. That record carries the branch's own bench prefix, which was reviewed earlier.
    • In tests/toyos.rs, there are two differences. The moved virt_user_mode body is indented differently. The machine's stop keeps its gate and waits for no thread #1241's rename lands in the (name, fn) entry instead of the deleted run_machine_test arm.
    • Nothing of main is dropped or reverted.
  • virt_user_mode matches main. With leading whitespace stripped, the function body equals main's arm at e10b6fd49 line for line.

The fixture rewrite is faithful

  • The rewritten lines match main's writers.
    • The kernel writes log!("spawn: pid={} (total={}ms) {}", pid, …, path) (kernel/src/loader/mod.rs:247).
    • The supervisor writes say!("supervisor: started {} pid={}", program.name, pid), where pid = child.id() (system/supervisor/src/main.rs:3319-3329). That is the pid the kernel recorded for the spawn, and the one the child's own lines are tagged with.
    • Each rewritten line keeps its timestamp, CPU, pid and total.
    • The only added value is pid=3 on the supervisor's line. It is the pid in the kernel's own record of that boot's single logkeeper spawn.
    • Each fixture is therefore what main's kernel and supervisor would have written for that boot.
  • The rewritten spellings are checked against source, not taken from the fixture alone. build/bootlog.rs:574 (the_writers_write_the_lines_the_host_reads) holds SPAWN and LOGKEEPER_STARTED to the writers' source, and the fixture parses only through those readers.
    • What is lost is independent proof that a real boot prints these two lines in this form. The source check covers that, and the owed boot:testcases runs will produce fresh readbacks.
    • If the record changes again, this test fails, which is the correct pressure to update the fixtures.
  • The test still checks what it claims.
    • The rewritten lines feed only one_clock (through logkeeper_spawn) and claims::job_records (through spawned_pid).
    • The pre-rewrite failure at 149aaf72e (r4/toyos-checks-before-fixtures.log) shows exactly those two readers failing: "no timed spawn record of logkeeper's pid…" and "no spawn record names test_rs_pci_reclaim's pid 115". It also shows the expected wrong-bench reds.
    • The test's actual claims are that the boot names its bench, that rows are taken and judged for that bench, and that the claim job's exit 1 is no row of the other bench. Those rest on lines left as captured: the microcode, exit:, PCI, iommu: and pcidev: records.
  • Rewriting is the right choice. The alternative is teaching the readers the old form, and A spawn's path is one line, and no judge finds a child by it #1238 removed that form on purpose because the caller's path came first.

Identifying data in the fixtures

The fixtures contain no hostnames, SMBIOS strings (each boot.txt has them masked), serial numbers, MAC addresses or network identifiers. They do carry CPUID signatures and microcode revisions and paths. Those are processor-model facts, and round 1 settled them as the bench key. The rewrite adds nothing except a pid that was already in the record.

Checks I ran at b7a90efc1 (detached worktree, clean tree)

  • cargo test --test toyos-checks: 50 passed, exit 0. This includes metal_each_benchs_own_readback_is_judged_as_that_bench.
  • cargo test -p toyos-metal: 77 passed, exit 0.
  • cargo clippy -p toyos-build -p toyos-metal --all-targets --keep-going with build/clippy.rs's six adopted lints and -D warnings: exit 0.

These match the PR body's figures. They also confirm that the author's toyos-metal and clippy runs at 149aaf72e still hold: b7a90efc1 changes no code. The PR body's r4 section is accurate. Its moves.txt notes the two MACHINE_TESTS entries that differ only by a trailing comma.

Findings

No blockers.

  • SUGGESTION tests/checks/metal.rs:850-853: the comment's headline still says the readback is "as its loop wrote it", and the edits it lists now qualify that claim. The reflow also leaves "it names" alone at the end of a short line. A shorter version would be: "Each bench's own readback (its testcases boot of 2026-11-11, cut to the lines read here, its machine masked, its spawn lines in the writers' current form): it names its bench, …". This is optional.

LAND

@Japabu

Japabu commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Orchestrator: review r4 LAND at b7a90ef (mechanical rebase onto e10b6fd verified by range-diff; fixture lines rewritten to the writers' current spawn format, held to source by build/bootlog.rs). Landing under the benches-down rule; the unfiltered boot:testcases judgement on both benches stays owed, as recorded.

@Japabu
Japabu marked this pull request as ready for review November 11, 2026 20:15
@Japabu
Japabu added this pull request to the merge queue Nov 11, 2026
@Japabu
Japabu removed this pull request from the merge queue due to a manual request Nov 11, 2026
@Japabu
Japabu added this pull request to the merge queue Nov 11, 2026
Japabu and others added 4 commits November 11, 2026 23:40
…name the one they judged

A METAL row said its boots and its judge and nothing of the machine it was
written for, so a boot of one bench carried every row riding its label: the
T14's `testcases` boot ran the AMD-Vi rows' deliberate DMA fault and was red
on `amdvi_*` and `idle_entered`, the AMD bench's ran the T14's I219 claim
(`test_rs_pci_reclaim` exited 1 there), a judge of `boot:benchcase` on the AMD
bench was red on the two I219 rows, and every failed job read "on the T14".

A row's registration now carries `on`: every bench, each bench having the
devices it names (`toyos_metal::bench::Device`), or one bench alone. `select`
takes a row only for a bench that runs it and leaves the rest by name with
why, so a left row's jobs are in no image; a run whose every row is left is
refused. A row no bench runs fails the registration check.

A boot already says which machine it is: the kernel's first record carries
the processor's signature. `Bench::of_log` reads the bench from that, a
`Readback` carries it, and the judges that told the benches apart by three
means of their own (the signature, the ACPI row, a search of both benches'
tables) match on it instead. A failed job names its readback's bench; a run
names its bench in its opening line, each boot's line and the timings line,
which no longer prints the machine's vendor, product and BIOS strings.

A run's bench is its readbacks' where its directory holds any, so judging
needs neither `--metal-bench` nor `--metal-host`; a readback written before
this change judges as before, since every boot has had that record. Staging
takes `--metal-bench <t14|amd>`, the T14 without it, and `--metal-host` with
no `--metal-bench` and no readback is refused, since the host names a machine
and not which rows ride its boot; so is `--metal-bench amd` with no
`--metal-host`, since `toyos-metal` boots the T14 unless told otherwise. A
boot that ran on another bench than the run's is red with every row on it.
The osbench README stages the AMD bench's run with both.

The T14's plan is main's less the AMD bench's three jobs, in main's order
(`--metal --list` before and after): `test_rs_pci_reclaim` leaves the shared
`TESTCASES` arm for the one row that judges it, and that row and the Type-C
row move so the order stands.

`MACHINE_TESTS` and `SCREEN_TESTS` carry each test's function, so a
registration with no dispatch arm does not compile; `run_machine_test` and
`run_screen_test` go, and the eight screen tests whose bodies were arms are
functions.

Closes five records: the three that reported "on the T14" on every bench,
the row that names no machine, and the registration with no dispatch arm. Two
are rewritten to what is left: no unfiltered AMD-bench run has been judged
since, and the timing record still names its machine by what Ubuntu reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ends one bench's boots to the other's

A run's bench came from its readbacks, but its machine from `--metal-host`
alone, with the T14 behind no flag. Two refusals guarded that only where no
readback was there, so a directory one boot of two had answered, which is
staged again, was staged for its readback's bench with invocations that named
no host and so booted the T14; and the T14's readbacks with `--metal-host`
naming the AMD bench's machine staged the T14's rows for that machine.

`Bench::host` now names each bench's machine, and `target_of` resolves a run's
bench and machine together: the machine is the bench's own unless
`--metal-host` names another, and one that is another bench's is refused by
name, whether the run stages, drives or judges. Every invocation names its
`--host`, the T14's too, and `toyos-metal`'s own default is the T14's
`Bench::host`. The two refusals go: `--metal-bench amd` alone stages the AMD
bench. The harness test covers both cases above, and the README and records
say how a run reaches its bench.

The judge that binds a bench's ACPI tables calls them `tables`, and the Wi-Fi
record says a radio row adds its own `Device`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on metal

Both benches are down. The AMD bench booted both `boot:testcases` images
before they went, but no judge read the readbacks and the T14 booted neither,
so the judged runs are owed: the record of rows that declare their benches
names the runs, the benches and what main must show.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cks' spawn records in main's form

Main moved under the branch in three places this branch also changes:
#1241 renamed `machine_shutdown_short_stop` to
`machine_shutdown_with_a_thread_spinning`, which is now that name's
`MACHINE_TESTS` entry; #1238 changed `virt_user_mode`'s arm, which this branch
moved into a function and which now carries the change; and #1238 changed the
kernel's spawn record to `spawn: pid=N (total=Xms) <path>` and the
supervisor's to `started logkeeper pid=N`, which the one-clock check's planted
log now writes beside the T14's first record.

#1238's readers no longer read the older form, so the two bench readbacks
this branch carries as fixtures, written before it, read as a boot with no
record of logkeeper's spawn and a job with no spawn record. Their three
lines each are rewritten in the form the kernel and the supervisor now write,
with the same pids and times.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu
Japabu removed this pull request from the merge queue due to a manual request Nov 11, 2026
@Japabu

Japabu commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Orchestrator verification of the rebase onto d17f22c (cba026b): git range-diff shows the three review commits unchanged; the first commit differs only by carrying #1244's two machine tests into MACHINE_TESTS entries (read at tests/toyos.rs:689-697; same call, same parameter, main's comment). Mechanical; host checks per the author (toyos-checks 50, toyos-metal 77, clippy 0). Re-queued.

@Japabu
Japabu added this pull request to the merge queue Nov 11, 2026
Merged via the queue into main with commit 7d8fa5b Nov 11, 2026
5 checks passed
@Japabu
Japabu deleted the metalrows branch November 11, 2026 22:11
Japabu added a commit that referenced this pull request Nov 11, 2026
#1254 made every metal row say which benches it runs on. The `mitigations`
row's judge holds a boot to its own bench's pinned words, and it ran on both
benches, so it is `On::Every`, as the `microcode` row it rides with is. The
comment stops listing the benches the field now names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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