Conversation
`pcidev::bring_up` armed exactly one mechanism — `enable_msix(...).ok_or(Refusal::NoMsix)?` — so a function that publishes no MSI-X capability was refused by name and its holder never ran. Every function this project had handed to a process so far was a virtio one and every one of those has MSI-X, so the refusal had only ever been reached by `virtio_net_no_msix`'s deliberate `vectors=0`. The ThinkPad T14's onboard NIC is not one of those. Measured on the machine, not assumed: `/proc/interrupts` names its interrupt `IR-PCI-MSI-0000:00:1f.6 ... enp0s31f6` and `/sys/bus/pci/devices/0000:00:1f.6/msi_irqs/162` reads `mode=msi`, so Linux drives that function on MSI. Flashed and booted (run 28), this kernel wrote `pcidev: PCI 00:1f.6 NOT HANDED OVER — its MSI-X could not be armed`, netd found no endowment and exited, and the bench's one cable stayed dark. `bring_up` now arms MSI-X and falls back to MSI, and `Bound` holds whichever it got. **The driver above the boundary cannot tell which one it is and does not have to**: both deliver the same vector into the same `Interrupt`, and the claim answers the same handle either way. What differs is where the message lives, and therefore what a hand-over back has to write to silence it — `Armed::silence` masks an MSI-X table entry or clears MSI Enable, and `Armed::undo` puts the capability itself back off for a hand-over that armed a vector and was then refused. **MSI is not the weaker mechanism here, and the security argument is the same one.** MSI-X's table is kept out of what the holder maps because a holder that could rewrite it could point the device's message at any address the LAPIC decodes. An MSI function's message is in its own config space, which `pcidev` keeps: `config_read` is read-only and there is no writing counterpart. So MSI needs no BAR withheld — the same rule reaching a different register file. `Refusal::NoMsix` becomes `NoInterrupt` and says both mechanisms, because that is now what it means. `PciDevice::disable_msi` is new and is `disable_msix`'s counterpart: it sets the per-vector mask where the capability implements one and clears MSI Enable, which every function has. `toyos_pci::msi` grows `disabled` and the `MASKED`/`UNMASKED` mask values, host-tested — `disabled` deliberately does not restore the Multiple Message Enable field an arming zeroed, or a function would come back armed for as many vectors as it can raise. The hand-over record now names the mechanism (`vector 0x28 on MSI-X`): it is the first thing a machine that never heard from its device is asked, and it is not something the driver above the boundary can see. The two checks. - **Negative control.** Run 28 on the T14 is this change reverted whole, on the base the granted claim will be measured against: the same `tests/lancase` image on this machine's own I219 with `bring_up` arming MSI-X alone. It refused the claim by name at 1.349 s, netd exited `code=0` at 2.268 s, and nothing answered on the cable for the twenty seconds the boot stayed up. - **Independent oracles, two.** Linux's own reading of the same function, above — a driver nobody here wrote, saying that function is an MSI part. And the capability's register layout, which is the PCI spec's and which `toyos-pci/src/msi.rs`'s tests encode: the offsets of the address, data and mask registers all move with the 64-bit address bit, and writing a vector at the wrong one of them lands in whatever capability comes next in the list. Beside them, this kernel already produces the shape MSI must reproduce — `PCI 00:1f.3: msi address=0xfee00098 data=0x00000000` for the T14's HDA. Green: `cargo test -p toyos-pci` (41), `cargo test --lib` (296), `cargo run -- --clippy` (all five invocations), and the four guest arms that read this module — `virtio_net_no_msix`, `iommu_virtio_platform`, `pci_function_is_exclusive` and `userdev_dma_fault`. The MSI arm itself is exercised on the T14 alone: no device QEMU models that a process may claim publishes MSI without MSI-X, so there is no guest that can take that branch. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
Japabu
enabled auto-merge
September 8, 2026 15:32
Japabu
disabled auto-merge
September 8, 2026 15:38
Japabu
added a commit
that referenced
this pull request
Sep 8, 2026
The green arm's claim stops at the 32-bit window, and the branch that says what the machine has left below 4 GiB is stacked on #443. Merged here so the image the T14 runs carries the survey; when both land, merging main is the same commits again.
…t does The fallback this branch added chose by what an arming answered, so a function that publishes MSI-X and whose table this kernel could not decode fell through to MSI and was handed over with that table and its PBA inside a BAR `place_bars` did not withhold: `msix_bar` answers `None` on a decode failure, so nothing is kept back, while `enable_msix` answers `None` on the same input. On the base that function was refused and never reached a holder. The choice is now what the function's capability list publishes and never what an arming answered. `toyos_pci::mechanism` is that rule, pure and host-tested: a function publishing MSI-X is armed on MSI-X or refused `MsixUnusable`, MSI is armed only where there is no table in a BAR at all, and neither is `NoInterrupt`. `enable_msix` succeeding implies `Msix::decode` succeeded implies `msix_bar` named the BAR, so the table's BAR is withheld on every path that arms MSI-X. `disable_msi` is the enable bit alone. Its per-vector mask write had no specification behind its order and was the opposite of the one independent implementation this branch cites — Linux's `pci_msi_shutdown` clears MSI Enable and then *unmasks* — and leaving the Mask bit set owes a message on the set-to-clear transition a later arming makes of it with the Pending bit set (PCIe 7.7.1.7). What is left is the one decision `Msi::disabled` makes, which `disabling_clears_the_enable_bit_and_nothing_else` gates on the host; its fixture now carries Multiple Message Enable set, so the partial implementation that cleared that field too is red where it used to pass. `netd`'s `config_space_is_bounded` now attempts a configuration write and refuses a claim that answers one. That refusal — `RegTarget::PciConfig(_) => Err(NotSupported)` — is the whole of why an MSI function's message may stay in configuration space with no BAR withheld for it, and nothing asserted it. Deleted: `Armed`'s three one-caller methods and the `arm` free function, whose bodies are one `match` each at their sites; `msi::MASKED`/`UNMASKED` and the test that restated their declarations; `iommu.rs`'s `MSI_ARMED` `must_not_say`, which no implementation of that module could red — 00:03.0 publishes MSI-X, so that arm never reaches the MSI branch. `issues/kernel/a-claimed-function-must-have-msi-x-and-the-i219-may-not.md` is renamed and cut to the half that still stands: `toyos-i219` refuses a part outside MSI-X mode at `IVAR`, and the T14's `00:1f.6` is measured to be one. The kernel half the slug claimed is refuted by this branch. No citation to either the slug or the path exists anywhere else in the tree (`git grep`). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
…re tracked
`toyos_pci::mechanism` was a new pure-crate rule with one caller, a four-row
truth table its two tests transcribed row for row, and a doc that told the
kernel's hand-over story inside a crate that knows nothing of hand-overs. It is
deleted whole: `toyos-pci/src/lib.rs` is byte-identical to origin/main again,
and `bring_up` asks the capability list directly.
The rule that MSI is not a fall-back is a rule about hand-over and is stated
once, in the module whose subject is a function driven by a process
(`kernel/src/pcidev/mod.rs`). The kernel's own xHCI and HDA drivers arm MSI-X
or fall back to MSI, and that is not the same choice: nothing is handed over
there, so no BAR carrying an MSI-X table reaches a holder and there is no rule
to contradict.
Also deleted, because nothing consumed them: the `on {armed}` discriminant on
the hand-over line, which restates what `report_message` printed off the
device's own registers one line earlier; netd's configuration-space write
probe, which ran on the one claim that is armed on MSI-X and never on the one
armed on MSI, and which had to reach past `PciDev` — a typed handle with no
write method at all — into `toyos_abi::syscall` to make the call; and the second
assertion in `disabling_clears_the_enable_bit_and_nothing_else`, which the first
already implies.
Two weaknesses this branch leaves standing are now recorded rather than carried
in a pull request body:
issues/kernel/nothing-reaches-the-msi-arm-of-a-claimed-function.md
issues/kernel/nothing-asserts-that-a-claim-answers-no-configuration-write.md
`grep -rn 'disable_msi\b\|enable_msi\b' kernel/` gives five sites: hda.rs:666
and xhci/wait/boot.rs:104 arm and never disarm, and pcidev/mod.rs:495, :520 and
:756 are this branch's, reached by no tier. Each file carries its owner and the
exit condition that closes it.
Prose deleted at the sites the review named, including two pieces of
pre-existing prose in files this branch edits: `pcidev`'s "What is read back,
and what is not" register of tests, which no gate held and which went stale
every time a test moved, and five of the six lines on `BAR_MOVED`/`MSIX_ARMED`.
TWO SENTENCES OF 8dec3ec ARE RETRACTED. History is not rewritten here, so they
are withdrawn by name instead:
"nothing answered on the cable for the twenty seconds the boot stayed up" is
false. /Users/jan/.claude/jobs/2280e09e/tmp/t14-run28/lancase.log:12 reads
"100.92.92.12 answered a ping 64 s into the window, after 5 s of silence — so
something on this cable was up while Ubuntu was not".
"Run 28 on the T14 is this change reverted whole, on the base the granted
claim will be measured against" is false. Run 28 is tip=220305b4
(t14-run28/lancase.log:1) and run 29 is tip=24625c6b
(t14-run29/lancase.log:1), whose parent 938957a run 28 does not carry, so the
pair reverts two changes and is not a negative control.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
…iving it
`enable_msix` collapsed four outcomes into one `None`, so `bring_up` had to ask
the capability list again to tell "publishes no table" from "publishes one this
kernel could not arm" — and the refusal it raised then asserted a reason that was
false on three of the paths it fired on. `Refusal::MsixUnusable` said the table
"is in a BAR nothing here can name to withhold", which holds only where
`Msix::decode` failed: after a successful decode `msix_bar` answers `Some(bir)`
and `place_bars` does withhold that BAR. On the `message()` path it was worse
than false — `enable_msi` calls the same `message()` and fails identically, so
the honest refusal there is that neither mechanism could be armed, and the
console had already printed `not armed — {why}` one line above the contradiction.
`enable_msix` now answers `Result<Mmio, Unarmed>` (`drivers/pci.rs:33-44`):
`Absent` is a function publishing no MSI-X, `Unusable` a table this kernel could
not reach, `Blocked` a message the unit refuses — which is the same message MSI
would carry. `bring_up` is one match over it (`pcidev/mod.rs:489-496`) with no
capability walk of its own: `Unusable` refuses `MsixUnusable`, `Blocked` refuses
`NoInterrupt`, `Absent` tries MSI. The `else if publishes(msi::CAP_ID)` arm is
gone with the closure: `enable_msi` already opens by looking the capability up
and answering false without one, so the arm decided nothing and no log line on
any machine moved with it. `virtio_net_no_msix` is the test that reaches the
`Absent` arm and reads that false back.
`MsixUnusable` no longer claims what withholding happened; it says the function
publishes MSI-X, this kernel could not arm it, and MSI is not a fallback for a
function that has a table.
`PciDevice::capability(id)` (`drivers/pci.rs:363-366`) is the one spelling of
"find this function's capability by id". It replaces seven copies of
`capabilities().find(|c| c.id() == …)` — the four in `drivers/pci.rs`, `msix_bar`
and `reset` in `pcidev/mod.rs`, and `power_up` in `drivers/hda.rs`.
Three callers move from `Option` to `Result` and decide nothing new:
`hda::arm_interrupt`, `virtio_sound::arm_interrupt` and `xhci::wait::boot::
arm_interrupt` read `.is_ok()`/`.is_err()` where they read `.is_some()`/
`.is_none()`.
Two numbers in 76fb456's message and body are corrected here, since history is
not rewritten. Its message attributed "five sites" to
`grep -rn 'disable_msi\b\|enable_msi\b' kernel/`; that command prints seven
lines — the two definitions plus five call sites — and the enumeration that
followed it was of the call sites only. Its body called
`tests/common/iommu.rs` byte-identical to `origin/main`, which
`git diff origin/main HEAD --shortstat -- tests/common/iommu.rs` refutes at
`1 insertion(+), 6 deletions(-)`; `toyos-pci/src/lib.rs` and
`userland/netd/src/virtio_net.rs` are byte-identical and `tests/common/iommu.rs`
is not. The body also cited the choice at `mod.rs:487-496`, which was the comment
above it and one line short of the block.
Prose deleted rather than rewritten: `Armed::Msi`'s doc, which restated the
module header's own MSI clause; the unbacked "no device QEMU models…" sentence
and the session-local "run 29" locator in
`issues/kernel/nothing-reaches-the-msi-arm-of-a-claimed-function.md`; the
rebuttal of the dropped `open` probe in
`issues/kernel/nothing-asserts-that-a-claim-answers-no-configuration-write.md`;
and, pre-existing in files this branch edits, the "The refusal moved with the
driver" chronology in `tests/common/faults.rs` and `enable_msix`'s two-meaning
`None` clause. That tracker's own claim moved with the code: `enable_msi` from
`bring_up` is now reached by `virtio_net_no_msix`, and what nothing reaches is a
successful arming and everything past it.
Green in this worktree: `cargo test -p toyos-pci` 40 passed exit 0;
`cargo test --lib` 295 passed 1 ignored exit 0;
`cargo test --workspace --exclude toyos-build` 138 suites 1347 passed exit 0;
all five `src/clippy.rs` shapes exit 0, no warning. Every
`cargo test --test toyos-build` is still refused at `src/toolchain.rs:1382`
(exit 101) while `/Users/jan/Dev/jan/toyos-aperture` holds the sysroot;
`--claim-sysroot` was not passed and `main` was not merged in.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
… walk reached `bring_up` armed MSI on `Unarmed::Absent`, and `Absent` meant only "the walk yielded no MSI-X capability". The walk is `caps::CapWalk`, which ends at a misaligned pointer, one below the standard header, or one already visited (`toyos-pci/src/caps.rs`). So a function whose MSI capability precedes such a link and whose MSI-X capability follows it read as `Absent`, was armed on MSI, and `msix_bar` — the same blind walk, one line above — named no BAR, so `place_bars` withheld none and the MSI-X table's BAR went to the holder with everything else. A holder that can write that table points the device's message at any address the LAPIC decodes. On origin/main that function was refused `NoMsix` and reached no holder, so the hole is this branch's. An early end is now a distinct answer, and the refusal is by name. - `CapWalk::truncated()` says whether the walk ended at the list's terminator or at a link the spec forbids. The decision stays in the pure crate; the kernel reads it. - `PciDevice::capability(id)` answers `Result<Capability, NoCapability>`: `Absent` is a walk that reached the terminator and found nothing under the id, `Truncated` a walk that stopped early, so what lies past that link was never read. - `enable_msix` carries it out as `Unarmed::NoTable(NoCapability)`, and `bring_up` refuses `Refusal::CapsTruncated` — "its capability list ends at a link the PCI spec forbids, so whether it holds an MSI-X table in a BAR was never read, and MSI is not armed on a guess". Only `NoTable(Absent)` reaches the MSI arm. The five remaining readers of `capability` — `disable_msix`, `enable_msi`, `disable_msi`, `hda::power_up`, `pcidev::reset` and `msix_bar` — take the same answer and decide nothing new; a truncated walk leaves each of them where a missing capability did. `msix_bar` is the one that matters, and what makes it safe is that `bring_up` refuses the function before `place_bars` ever reads what it answered. The host tests that see a partial implementation are `toyos-pci`'s four walk tests, which now assert the flag as well as the step: an implementation that treats a misaligned pointer, a below-header pointer or a cycle as a clean end is red at `a_pointer_that_is_not_dword_aligned_is_refused`, `a_pointer_below_the_standard_header_is_refused` and `a_pointer_to_a_visited_link_ends_the_walk`, and one that reports the terminator as an early end is red at `the_terminator_ends_the_walk` and `a_forward_chain_is_followed_to_its_end`. The module header at `kernel/src/pcidev/mod.rs` stated the bound as an absolute — "a function that publishes MSI-X is armed on MSI-X or refused" — which held only over what the walk reached. It now states it over the walk. Deleted, because nothing reads them: `#[derive(Debug, Clone, Copy, PartialEq, Eq)]` on `Unarmed`, whose five traits nothing in the tree formats, clones, copies or compares. Prose deleted rather than rewritten, at the sites the review named: `Unarmed`'s "Named rather than collapsed into one `None`", which is the argument `Refusal`'s own doc already makes, by reference to a `None` that no longer exists; `capability`'s first sentence, which restated its signature; `bring_up`'s clause naming which test reads which refusal, which the same commit deleted ten lines of elsewhere; and, pre-existing in files this branch edits, the three-implementations investigation story above `tests/common/faults.rs`'s `virtio_net_no_msix` and the reason under `userland/netd/src/i219.rs`'s BAR search, which this branch falsifies — the T14's `00:1f.6` publishes no MSI-X, so nothing is withheld from that claim. Green in this worktree: `cargo test -p toyos-pci` 40 passed exit 0; `cargo test --lib` 295 passed 1 ignored exit 0; `cargo test --workspace --exclude toyos-build` 138 suites 1347 passed 0 failed exit 0; all five `src/clippy.rs` shapes exit 0 with no warning. Every `cargo test --test toyos-build` is still refused at `src/toolchain.rs:1382` (exit 101) while `/Users/jan/Dev/jan/toyos-aperture` holds the sysroot; `--claim-sysroot` was not passed and `main` was not merged in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
…reaches `Refusal::CapsTruncated` and `NoCapability::Truncated` are reached by no test in any tier, for the same reason the MSI arm is: the guest has no function that publishes one. The walk's half of the decision is host-tested in `toyos-pci/src/caps.rs` and a partial implementation of it is red there; the kernel's refusal arm is not, and the file now says so rather than describing a tree one commit older. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
`main` moved four times under this branch (#449, #451, #454, #455). One conflict, in `kernel/src/pcidev/mod.rs`'s module header. #449 appended a sentence to the header's "What is read back, and what is not" register of tests; `76fb456d` on this branch deleted that register whole, because no gate held it and it went stale every time a test moved, and recorded the holes it had been carrying as `issues/kernel/nothing-reaches-the-msi-arm-of-a-claimed-function.md` and `issues/kernel/nothing-asserts-that-a-claim-answers-no-configuration-write.md`. The deletion stands. The register names `NoMsix`, the refusal this branch replaces with `NoInterrupt`, `MsixUnusable` and `CapsTruncated`, so keeping it would leave the header naming a variant no longer in the file. #449's sentence is accounted for and not dropped with it. Two of the three things it said stand elsewhere in #449's own commit: that `account_for` records on every boot and refuses nothing on it is the header paragraph #449 added above, and that the record is the whole of what the kernel does about an un-forwarded window is `issues/kernel/a-bar-is-placed-in-a-window-firmware-names-no-part-of.md`. The third — that nothing here reads those records back, that the judge is a boot of the machine, and that `toyos_pci::aperture` is where the decision behind them is exercised — had no other home, and is moved to `account_for`'s own doc, which is the contract for what those records are. `kernel/src/drivers/pci.rs` merged without conflict and carries both sides: #449's `PciDevice::bar_slots` and its use in `assigned_bars`, and this branch's `NoCapability`, `Unarmed`, `PciDevice::capability` and `PciDevice::disable_msi`. `publish` and `place_bars` bound their BAR walks by `bar_slots()` as #449 left them; `bring_up` walks no capability list of its own, and a list that ends at a link the spec forbids still reaches `Refusal::CapsTruncated` and never the MSI arm. The pull request body's negative control was anchored to `$(git rev-parse HEAD^2)`, an expression this merge moves. It is re-anchored by name to `ad61ed08`, the `main` this merge brings in; the merge changes two of the paths that control reverts, so the body carries a fresh run of it against that base. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
The branch declared its new MSI path unexercised and filed it as one tracked weakness. It was two, and only one of them needs silicon. **The truncation classification needs no claimable function at all.** `PciDevice::capability`'s `Truncated`/`Absent` split is what decides whether a malformed capability list falls through to the MSI arm, and `kernel/src/drivers/virtio.rs`'s `cap_selftest` already drove the real walk over a cyclic list, a misaligned link, a below-header link and a forbidden head through `PciDevice::over_config`. Each of those five walk cases now also reads back what the walk's *end* made of a capability none of them publishes: a walk that reached the terminator answers `Absent`, one that stopped early answers `Truncated`. The verdict is its own line, `pci cap split 5/5`, and `pci_capability_walk` — `Tier::Fast`, so the per-pull-request gate runs it — refuses a boot that does not print it. No actuator, no boot config, no tier row. **The mutation it is for, run.** `capability`'s `None if walk.walk.truncated()` guard replaced by `None if false`, so every miss answers `Absent` — a kernel reading a list that ended early as one that named nothing. The gate went red at four named cases with `virtio: pci cap split 1/5`, exit 1, while `virtio: pci cap selftest 14/14` stayed green beside it: the case count that existed before could not see this defect, and the split is what sees it. **MSI-X first is now asserted on the gate that runs.** The only arm requiring a claimed function to be armed on MSI-X was `iommu_virtio_platform`, which is `Tier::Nightly` and which `.github/workflows/ci.yml` selects only on a schedule or a dispatch, so the owner's ordering was unguarded per pull request. `pci_function_is_exclusive` (`Tier::Fast`) now requires the hand-over to spend `MSIX_ARMED` and refuses `MSI_ARMED` on the same function, and `xhci_second_controller` (`Tier::Fast`) requires both of its controllers — neither of them the `msix=off` one — to report `xHCI: MSI-X enabled`. The second is the one a producible mutation reds: `nec-usb-xhci` publishes both mechanisms, so an `arm_interrupt` taking MSI first prints the other line. The claimed-function arm cannot be mutated that way, because no function this harness hands to a claim publishes both, and the pull request body says so rather than implying otherwise. **The arming stays owed, and its tracker now prices only that.** `issues/kernel/nothing-reaches-the-msi-arm-of-a-claimed-function.md` bundled the classification into the cost of the arming. It now names what remains — the `bring_up` refusal arm, `disable_msi` from either hand-back site, `Refusal::MsixUnusable` and `Unarmed::Blocked` — keeps the bench as its exit condition, and prices the guest alternative honestly: it needs a claimable function publishing MSI and no MSI-X, which nothing this harness hands to a claim is, so hiding a capability is not enough by itself. **The refusals the deleted register carried are recorded again.** `76fb456d` deleted `pcidev`'s "What is read back, and what is not" and the two issue files this branch filed recorded only the MSI arm and the configuration write. `issues/kernel/a-claims-own-refusals-are-read-by-nothing.md` records the rest: `ClaimError::Ambiguous`, `KernelDriven` and `Exhausted`, every window refusal, and every bound `SYS_DEVICE_BAR_MAP` and `SYS_DEVICE_DMA_ALLOC` check. **Two false counts, withdrawn by name.** History is not rewritten here. - `6d59a093`'s message and the pull request body say `PciDevice::capability` replaced "seven copies of `capabilities().find(|c| c.id() == …)` — the four in `drivers/pci.rs`". Both halves are false. `git grep -n 'capabilities()\.find' ad61ed0 -- kernel toyos-pci userland` prints **six** lines, **three** of them in `kernel/src/drivers/pci.rs` (`enable_msix`, `disable_msix`, `enable_msi`); the other three are `hda::power_up`, `pcidev::reset` and `pcidev::msix_bar`. The seventh caller, `disable_msi`, is new code on this branch and replaced no copy. - `a2be5f84`'s message says "The five remaining readers of `capability`" and then names six of them. With this commit's self-test reader, `grep -rn '\.capability(' kernel/src` counts eight callers. `issues/hardware/toyos-i219-refuses-a-part-outside-msi-x-mode-at-ivar.md` was `kind: defect` over a body saying no hand-over has reached the driver and nothing has run the write. `issues/README.md` gives `defect` as "real, reproducible", so it is a `finding`. Prose deleted rather than rewritten, at the sites the review named: the `pcidev` header sentence restating `Refusal::CapsTruncated`'s own Display string, and `disable_msi`'s "the counterpart of `Self::disable_msix`", which restates the item's name. The `pci-cap-selftest` actuator's doc carried a case count already one behind the code and that this commit moves again; the count is gone rather than corrected. One clause each at `hda::arm_interrupt` and `xhci::wait::boot::arm_interrupt`, which this branch left taking MSI on whatever a truncated walk reached: both functions are this kernel's own and hand no BAR to a holder, so an MSI-X table past the forbidden link is one nobody but this kernel could reach. Green in this worktree, each the command's own exit status: `cargo run -- --build-only` exit 0; `cargo test --test toyos-build -- pci_capability_walk` `PASS` exit 0; `cargo test --test toyos-build -- pci_function_is_exclusive` `PASS` exit 0; `cargo test --test toyos-build -- xhci_second_controller` `PASS` exit 0; `cargo test --test toyos-build -- virtio_net_no_msix` `PASS` exit 0; `cargo test --lib` 307 passed, 1 ignored, exit 0; `cargo test --workspace --exclude toyos-build` 1367 passed, 0 failed, exit 0; `cargo run -- --clippy` `clippy: 5 invocations clean` exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Round 2 closed "MSI-X first is unguarded" with an assertion that guards nothing, and justified the gap with a sentence about this harness that is false. **The vacuous assertion is deleted, for the second time and the same reason.** `tests/toyos.rs`'s `pci_function_is_exclusive` asserted `must_not_say(MSI_ARMED)` on `00:03.0`. That function is QEMU's `virtio-net-pci-non-transitional`, whose capability list is MSI-X at 0x98 and five vendor capabilities — no id 0x05 anywhere — so `enable_msi` returns at its lookup and no mutation of this kernel can put `PCI 00:03.0: msi address=` on that console. `94341ce1` deleted the identical assertion from `tests/common/iommu.rs` on this branch for exactly that reason; it came back one file over without an answer, and goes again. Its `must_say(MSIX_ARMED)` neighbour goes with it: on a function whose only armable mechanism is MSI-X, a hand-over *is* the msix line, and the `handovers != 1` refusal four lines above already requires one. `MSI_ARMED` is deleted and `MSIX_ARMED` is private again, its one reader being the module it lives in. **The real assertion has a home, and it is on the fast tier.** `tests/e1000case/system.toml` hands netd `pci:8086:10d3` — QEMU's `e1000e`, which publishes MSI at 0xd0 *and* MSI-X at 0xa0 — and `https_tls13_e1000e` is `Tier::Fast`, so every pull request already boots a claimed function that publishes both. `iommu::armed_on_msix` takes the `vendor:device` the boot config declares, finds the BDF that function was handed over on, and requires `msix address=` for it and refuses `msi address=`. The id comes from the new `Bench::claims` field rather than from whichever function the guest reports, so the assertion is about the function the harness declared. **The mutation that reds it, run.** `bring_up`'s match reordered to try `enable_msi` first, nothing else touched: ``` [kernel 0.324 cpu0] PCI 00:03.0: msi address=0xfee00098 data=0x00000000 [kernel 0.329 cpu0] pcidev: PCI 00:03.0 [8086:10d3] handed over on slot 0, vector 0x28 FAIL https_tls13_e1000e: "PCI 00:03.0: msix address=" never reached the boot console ALONE https_tls13_e1000e: red again, the same failure both times — the defect is real. test result: FAILED. 0 passed, 1 failed, 1 total (6.5s) ``` exit **1**. Every fetch, refusal and differential arm below it still passed: the card works on MSI, which is why nothing but this assertion sees the order. **The arming's own answer is read back, not just `capability`'s.** `bring_up` matches on `enable_msix`, so that is what the self-test now asserts: each walk case reads `device.enable_msix(0)` as well as `device.capability(msix::CAP_ID)`. No layout there publishes MSI-X, so the call returns at its lookup and touches no MMIO. Mutation, run: `enable_msix`'s `map_err(Unarmed::NoTable)` replaced by one reporting every miss as `Absent` — ``` virtio: pci cap selftest FAILED on a list that cycles on itself: the arming reads absent, want truncated (and the same on the misaligned link, the below-header link, the forbidden head and the capability reached before a forbidden link) virtio: pci cap split 8/13 virtio: pci cap selftest 15/15 test result: FAILED. 0 passed, 1 failed, 1 total (4.5s) ``` exit **1**, with `15/15` green beside it. **A case that both finds and truncates.** Every layout published only `PCI_CAP_ID_VENDOR`, so `Ok(_) => "found"` was unreachable and the split only ever separated absent from truncated. One row adds the shape this branch exists to refuse — a capability the walk reaches, then a link the spec forbids: `(0x40, msi::CAP_ID, 0x43)`, where `capability(msi::CAP_ID)` must answer found and `capability(msix::CAP_ID)` truncated. `CASES` is 15 and `SPLITS` 13. **The hole that remains is measured now, not asserted.** `bring_up`'s two `NoTable` arms replaced by one falling through to `enable_msi` — the whole privilege fix reverted — leaves `pci_capability_walk`, `virtio_net_no_msix`, `https_tls13_e1000e` and `pci_function_is_exclusive` all **green**, exit 0 each. Reaching it needs a *claimed* function whose capability list ends early, which nothing this harness hands to a claim has; `issues/kernel/nothing-reaches-the-msi-arm-of-a-claimed-function.md` says so in those words. One thing does stand against it without a test: `-D dead-code` refuses a kernel in which `Refusal::CapsTruncated` is never constructed, so that mutation does not build until the lint is suppressed. Prose deleted rather than rewritten, at the sites the review named: `pcidev`'s `account_for` coverage narration, which is both a claim about what reads it back and one another landing moves; `pci_cap_selftest`'s "Fourteen crafted PCI capability layouts … the five walks among them", two counts this commit moves; the four lines narrating the two deleted assertions; the three narrating `xhci_second_controller`'s MSI-X count, which the refusal below them states; `MSI_ARMED`'s doc, which stated a discrimination the constant could not carry; and `cap_selftest`'s `SPLITS` doc, positional narration of the rows above. **Withdrawn by name. History is not rewritten here.** - The pull request body, `68ba8df6`'s message and the round-2 handoff all say `pci_function_is_exclusive`'s assertion "cannot be shown by a mutation: no function this harness hands to a claim publishes both mechanisms". False. `tests/e1000case` hands one to a claim on the fast tier, and the mutation above is run against it. - `a2be5f84`'s message justified deleting `userland/netd/src/i219.rs`'s BAR clause with "which this branch falsifies — the T14's `00:1f.6` publishes no MSI-X, so nothing is withheld from that claim". False: the clause is about code that runs on `tests/e1000case` too, where the claimed `8086:10d3` does publish MSI-X with its table in BAR 3, so the kernel does withhold that BAR and does report 0 bytes for it. The invariant returns as one clause at the site. - The body's "Retracted by name" section says `git diff --name-status 835cf8e HEAD | wc -l` is **50** and names "eleven `src/*.rs`". At `68ba8df6` that command printed **53** and `git diff --name-only 835cf8e HEAD -- 'src/*.rs' | wc -l` printed **14**; 50 is the previous head `88aedad9`'s number. The body carries this head's. Green in this worktree, each the command's own exit status: `cargo run -- --build-only` exit 0; `cargo test --test toyos-build -- pci_capability_walk` `PASS` exit 0; `cargo test --test toyos-build -- https_tls13_e1000e` `PASS` exit 0; `cargo test --test toyos-build -- pci_function_is_exclusive` `PASS` exit 0; `cargo test --test toyos-build -- xhci_second_controller` `PASS` exit 0; `cargo test --test toyos-build -- virtio_net_no_msix` `PASS` exit 0; `cargo test --test toyos-build -- --nightly iommu_virtio_platform` `PASS` exit 0; `cargo test --lib` 307 passed, 1 ignored, exit 0; `cargo test --workspace --exclude toyos-build` 1367 passed, 0 failed, exit 0; `cargo run -- --clippy` `clippy: 5 invocations clean` exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
Round 3 left the privilege half of this branch unwitnessed and said so: reverting
`bring_up`'s two `NoTable` arms left every tier green, and the tracker priced the
alternative at "a boot config carrying such a function and a test binary to hold
it". That price is refuted by the tree, and a branch that adds a privilege path
does not land with the mutation that would red it missing.
**The shape is staged on a function an existing boot config already claims.**
`pcidev-caps-truncated` is one `actuators!` row; `StagedCaps` in
`kernel/src/drivers/pci.rs` holds one requester id across the hand-over's own
walks, and `CapabilityIter::next` ends that function's list one byte off dword
alignment after its MSI capability. Every other walk in the machine reads the
list the device published — the static is `NO_FUNCTION` until a claim arms it and
again when the guard drops. `tests/e1000case`'s `8086:10d3` publishes MSI at 0xc8
→ 0xd0 and MSI-X at 0xa0, so the staged walk yields MSI, never reaches the MSI-X
capability, and `bring_up` refuses `CapsTruncated`. No holder is needed: the arm
under test is a refusal, and `pci_claim_caps_truncated` reads it off the console
of a boot where netd's claim was refused.
**What the judge asserts is the privilege decision and not the log line.** The
refusal by its own reason; no `msi address=` for that function, which is the
arming on a list this kernel had no right to trust; no hand-over of
`[8086:10d3]`; no BAR moved, so the BAR the MSI-X table lives in is still where
firmware put it; init's own refusal line; netd's exit; and the machine otherwise
whole.
**The vacuous assertion is deleted a third time, and by ruling.**
`iommu::armed_on_msix` was called from `tls13_judge` for both benches, so
`must_not_say("PCI 00:03.0: msi address=")` ran on every `https_tls13`. QEMU's
`virtio-net-pci-non-transitional` publishes MSI-X at 0x98 and five vendor
capabilities and no id 0x05, so `enable_msi` returns at its lookup and no
implementation of this kernel can print that line. `94341ce1` deleted the
identical arm from `tests/common/iommu.rs` and `eea8c7f7` deleted it from
`pci_function_is_exclusive`; it came back a third time one call site further out.
The orchestrator's round-4 ruling is that it is deleted and stays deleted. It is
not in `tests/common/https.rs` at all now: `tls13_judge` answers the boot console
and the `https_tls13_e1000e` registration — the bench whose claimed function
publishes both mechanisms — makes the assertion.
**`Bench::claims` is read against the file it names.** It restated
`tests/e1000case/system.toml`'s `devices` row in Rust, which is the drift
`tests/common/devices.rs`'s `the_config_runs_exactly_these_jobs` exists to
prevent. `every_bench_claims_what_its_config_declares` follows that pattern:
it reads each bench's `system.toml`, takes `[programs.netd]`'s own row, and
asserts the constant against it. `tests/netcase` declares the same function
twice — once for netd and once for the test binary that asks for a second claim —
so the section matters.
**The crafted layout is the case its name claims.** `(0x40, msi::CAP_ID, 0x43)`
alone put no MSI-X capability anywhere in that config space, so
`capability(msix::CAP_ID)` answered `Truncated` over a list that had nothing to
find: the case could not tell a walk stopped at the forbidden link from one that
reached the end of a list with no table. `(0x44, msix::CAP_ID, 0)` is the other
half of the shape the body describes — a capability the walk reaches, a link the
spec forbids, and a table past it — so `truncated` now means "there is one and it
was not read". `CASES` stays 15 and `SPLITS` 13: the row joins a case rather than
adding one.
**The `-D dead-code` claim is withdrawn.** Round 3's body and `eea8c7f7`'s message
offered "`-D dead-code` refuses a kernel in which `Refusal::CapsTruncated` is
never constructed" as what stood against the hole without a test. It is not a
guard: the lint fires on the mutation that keeps the variant, never on a
regression that reached `main`, and a mutation that deletes the variant with the
arms — which is the whole change reverted, and the mutation run below — builds
clean.
Prose deleted rather than rewritten, at the sites the review named:
`tests/toyos.rs`'s "fourteen crafted layouts" and the six-item list after it, a
count this branch moved; `tests/common/https.rs`'s "QEMU's `e1000e` publishes MSI
at 0xd0 and MSI-X at 0xa0", a measurement's provenance and two offsets a
`.github/qemu-version` bump moves; `Bench::claims`'s restatement of
`armed_on_msix`'s own doc; `cap_selftest`'s "The shape the claim path exists to
refuse", which restated the case name on the line below it; and the narrating
halves of the two comments at the `reached` and `enable_msix` reads, the
load-bearing clause of each kept.
**Mutation 1 — the privilege decision, and it reds now.** `bring_up`'s two
`NoTable` arms replaced by one falling through to `enable_msi`, with
`Refusal::CapsTruncated` and its `Display` arm deleted: the whole change
reverted, which is also why it builds. `cargo build --target x86_64-unknown-none
--features boot-actuators,test-actuators` in `kernel/` exit **0**, then
`cargo test --test toyos-build -- pci_claim_caps_truncated` exit **1**:
```
FAIL pci_claim_caps_truncated: "NOT HANDED OVER" never reached the boot console:
[kernel 0.345 cpu0] PCI 00:03.0: msi address=0xfee00098 data=0x00000000
[kernel 0.354 cpu0] pcidev: PCI 00:03.0 BAR 3 (0x4000 bytes) moved to 0xc0600000
[kernel 0.354 cpu0] pcidev: PCI 00:03.0 [8086:10d3] handed over on slot 0, vector 0x28
ALONE pci_claim_caps_truncated: red again, the same failure both times — the defect is real.
test result: FAILED. 0 passed, 1 failed, 0 stale or expired expected-failure entries, 0 invalidated, 1 total (7.9s)
```
BAR 3 is the BAR that function's MSI-X table register names, and the mutated
kernel moved it and gave it to netd with everything else.
**Mutation 2 — the ordering, re-run at this head.** `bring_up` tries
`enable_msi` first and falls back to `enable_msix`, nothing else touched. Build
exit **0**, `cargo test --test toyos-build -- https_tls13_e1000e` exit **1**:
```
[kernel 0.354 cpu0] PCI 00:03.0: msi address=0xfee00098 data=0x00000000
FAIL https_tls13_e1000e: "PCI 00:03.0: msix address=" never reached the boot console
ALONE https_tls13_e1000e: red again, the same failure both times — the defect is real.
test result: FAILED. 0 passed, 1 failed, 0 stale or expired expected-failure entries, 0 invalidated, 1 total (12.8s)
```
**Mutation 3 — the arming's own answer, re-run at this head.** `enable_msix`'s
`map_err(Unarmed::NoTable)` replaced by one reporting every miss as `Absent`.
Build exit **0**, `cargo test --test toyos-build -- pci_capability_walk` exit
**1**:
```
virtio: pci cap selftest FAILED on a list that cycles on itself: the arming reads absent, want truncated
(and the same on the misaligned link, the below-header link, the forbidden head
and the capability reached before a forbidden link)
virtio: pci cap split 8/13
virtio: pci cap selftest 15/15
```
Green in this worktree, each the command's own exit status:
`cargo test --test toyos-build -- pci_claim_caps_truncated` `PASS` exit 0;
`cargo test --test toyos-build -- pci_capability_walk` exit 0;
`cargo test --test toyos-build -- https_tls13` exit 0;
`cargo test --test toyos-build -- virtio_net_no_msix` exit 0;
`cargo test --test toyos-build -- pci_function_is_exclusive` exit 0;
`cargo test --test toyos-build -- https_tls13_e1000e` exit 0 (`PASS` in 4 s; its
first run in this session hit the 300 s fetch budget while three other checkouts
held all twelve guest slots, and the harness's own alone re-run was green);
`cargo test --lib` 308 passed, 0 failed, 1 ignored, exit 0;
`cargo test --workspace --exclude toyos-build` 139 `test result: ok` lines,
1367 passed, 0 failed, exit 0;
the five `cargo clippy` shapes `src/clippy.rs` declares, run as the `host` job
runs them, exit 0 each.
`pci_claim_caps_truncated` enters `tests/test-durations` as an `UNMEASURED`
marker with `shards=none`, which is the one red this commit knowingly carries:
`--merge-durations` refuses a committed marker, so the next commit takes the
price CI measures and assigns the final tier.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
…reads
Round 4 found the branch had added logic beside logic that already did the
job, and prose beside prose that already said it. Both are deleted rather
than rewritten.
**One refused-claim judge.** `faults::claim_caps_truncated` was a third copy
of the shape `virtio_net_no_msix` and `iommu::no_unit_is_no_claim` already
had: refusal line, reason, no hand-over, no BAR, init's line, netd's exit.
`faults::refused_claim(log, claims, why)` is that judge, and the three arms
call it. What is left at each caller is what is that arm's own — the argv
check and the audio function for the crippled NIC, the actuator's boot
parameter for the truncated list, and, for the machine with no unit, that
*nothing at all* was handed over, which is more than the claim's own refusal
says.
**The address is the harness's, never the guest's.** The judge read the
refused function out of the console and then asserted about *that*, which is
an assertion about whichever function the kernel happened to name. It now
knows the profile's slot (`CLAIMED_AT`), refuses a console that refused any
other function, and anchors every line to it: `pcidev: PCI 00:03.0 NOT HANDED
OVER — <reason>` is one match rather than two unanchored ones. `msi address=`
and `msix address=` are both required absent now, where each arm had asked for
one of them.
**One spelling of each thing.** `NO_FUNCTION` was declared in
`drivers/pci.rs` and again in `iommu/vtd/fault.rs`; it is declared once, where
a function's address is a triple, and the fault handler reads it through the
import it already had. `NETD_EXITS` was declared twice and is now declared
once, beside the wait that uses it. `1af4:1041` was written in three places
and is now read from `https::VIRTIO.claims`, the constant
`every_bench_claims_what_its_config_declares` holds against the committed
`devices` row. The two lines a hand-over spends are built by `bar_moved` and
`msix_armed`, so the arm that requires them and the arm that requires their
absence cannot drift apart.
**The bench's row is read with the parser the harness has.**
`every_bench_claims_what_its_config_declares` hand-rolled a TOML section and
list scan, copied from `devices.rs`. It reads `toml::from_str` into a
`toml::Value` and indexes `programs.netd.devices`, as `load_audio_baseline`
does; a device row that is not a string panics by name rather than being
dropped.
**Prose deleted, not moved.** The escalation story — read the early end as a
terminator, MSI is armed on the guess, `msix_bar` withholds no BAR — was told
at `pcidev/mod.rs`'s header, at `drivers/pci.rs`'s `StagedCaps`, and again in
the judge's doc. The header keeps it; the other two are gone. The three-line
reason at `hda::arm_interrupt` and `xhci::wait::boot::arm_interrupt` is one
paragraph on `PciDevice::enable_msi`, the call both of them make.
**A compromise on the ordinary path is recorded.**
`place_bars`'s `Some(index) == table_bar` mutated to `false` hands the MSI-X
table's own BAR to the holder of every function that publishes a table, and
every tier stays green on base and branch alike. It is pre-existing and is not
fixed here; it is a bullet in
`issues/kernel/a-claims-own-refusals-are-read-by-nothing.md`, which this branch
created for exactly that list.
**The marker is replaced by what CI measured.** Run 35100393637's twelve
hosted shards priced `pci_claim_caps_truncated` at 2583 ms and its
`test-durations-merged` artifact carries the row; the `durations` job reds on
the committed marker and says so by name. 2583 ms is under `FAST_COMMIT_MS`
(8000), so `Tier::Fast` stands and no registration moves. That one row is
taken and no other: the profile's other names are this run's shard luck, which
`src/durations.rs` measures at 1.28x p10-p90.
Measured in /Users/jan/Dev/jan/toyos-msi, each the command's own exit:
`pci_claim_caps_truncated` 0, `pci_capability_walk` 0, `virtio_net_no_msix` 0,
`pci_function_is_exclusive` 0, `https_tls13` + `https_tls13_e1000e` 0,
`iommu_virtio_platform` (--nightly) 0; `cargo test --lib` 0;
`cargo test --workspace --exclude toyos-build` 0; the five `src/clippy.rs`
shapes 0 each. M1 re-run over the consolidated judge — both `NoTable` arms
falling through to `enable_msi`, `Refusal::CapsTruncated` and its `Display`
arm deleted, `grep -c CapsTruncated` 0 — builds exit 0 and reds exit 1, now on
the refusal itself ("this console refused []") with `msi address=`,
`BAR 3 … moved` and `[8086:10d3] handed over` in the evidence.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
… refuses Round 4's ruling — the address a judge asserts about is the harness's own and never the guest's — was applied to `refused_claim` and not one file over. `iommu::armed_on_msix` still read the BDF out of the guest's `handed over on slot` line and then asserted `msix address=` and `msi address=` for *that*, so a kernel that armed MSI on the claimed function and named a different one in its hand-over line passed: the judge found the other function's msix line and called an MSI-armed `00:03.0` MSI-X-first. It now reads `faults::CLAIMED_AT`, asserts the printed address equal to it, and spends the spellings `faults::msix_armed()` and `faults::msi_armed()` — the `msi address=` line gets the constructor `msix address=` already had, so neither is written twice. `refused_claim`'s walk over `NOT HANDED OVER` lines was two `filter_map`s, so a line carrying the marker without the `pcidev: PCI ` prefix was dropped rather than red — a text scan closes only the spellings it matches, and a kernel that renamed the prefix would have handed the judge an empty list. `functions_named` is that walk for both judges and such a line is an `Err`. Prose, by correction where it is evidence: the issue's opening no longer counts the refusals that are read back, because this branch's own judge moved that count; its `place_bars` bullet spells the mutation in the form that builds, `(Some(index) == table_bar && false)` — a bare `false` is `unused variable: table_bar`, kernel build exit 101 — and names the four tests measured green on it rather than claiming every tier; and `CLAIMED_AT`'s doc says what is true of the constant instead of "every profile in this suite", no profile placing that function anywhere. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
`functions_named`'s doc said a renamed prefix would hand its caller an empty list, which `refused_claim` already reds on. The case that passed is the partial one: a console carrying one refusal this walk can parse and a second it cannot, where the judge of "and no other function" is answered about the subset. Comment only; no code moved, so the round's measurements stand. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A PCI function handed to a userland driver was armed on exactly one interrupt
mechanism:
pcidev::bring_upcalledenable_msix(...).ok_or(Refusal::NoMsix)?,so a function publishing no MSI-X capability was refused by name and its holder
never ran. Every function this project had handed to a process so far was a
virtio one and every one of those has MSI-X, so the refusal had only ever been
reached by
virtio_net_no_msix's deliberatevectors=0.The ThinkPad T14's onboard NIC is not one of those. Booted on the bench (run 28,
tip=220305b4), this kernel wrote, 1.349 s in,pcidev: PCI 00:1f.6 NOT HANDED OVER — its MSI-X could not be armed, and a claim with no interrupt is a driver that would never be told anything; netd found no endowment and exited, and thebench's one cable carried no ToyOS.
The owner's direction of 2026-09-08 is the rule this implements: the LAN
uses the most modern interrupt mechanism the device offers and never INTx.
MSI-X first wherever a function has it; MSI only where it has none — the T14's
I219 publishes no MSI-X capability, so there MSI is the most modern there is.
INTx is never armed, and nothing in this branch adds a path that could arm one.
What the kernel does now
bring_upis onematchover what the arming answered, and it walks nocapability list of its own:
enable_msixanswersResult<Mmio, Unarmed>and splits the three ways it canfail where each is known, so no caller re-derives it and no refusal asserts a
reason false on the path that raised it:
Unusable— a table this kernel could not reach:Msix::decodefailed, theBIR is not a memory BAR, or
table_addressfailed.Refusal::MsixUnusablesays the function publishes MSI-X, this kernel could not arm it, and MSI is
not a fallback for a function that has a table.
Blocked— the unit refuses this function's message (iommu::remap_msi).enable_msicalls the same privatemessage()with the same arguments andfails identically, so
Refusal::NoInterruptis exactly what happened.NoTable(Absent)— a walk that reached the capability list's terminator andfound no MSI-X. This is the only case that reaches the MSI arm.
NoTable(Truncated)— a walk that stopped at a link the PCI spec forbids.Truncatedis the security case, and it was the branch's own hole. The walkis
caps::CapWalk, which ends at a misaligned pointer, one below the standardheader, or one already visited. Until
cad60ec6a function whose MSI capabilitypreceded such a link and whose MSI-X capability followed it read as absent,
was armed on MSI, and
msix_bar— the same blind walk — named no BAR, soplace_barswithheld none and the MSI-X table's BAR went to the holder witheverything else. A holder that can write that table points the device's message
at any address the LAPIC decodes. On the base that same function is refused
NoMsixand reaches no holder, so the regression was this branch's and isclosed in it.
PciDevice::capability(id)is the one spelling of "find this function'scapability by id". It replaced six copies of
capabilities().find(|c| c.id() == …), three of them indrivers/pci.rs;grep -rn '\.capability(' kernel/srccounts 8 callers today.What the reviews changed
1. The truncation refusal is classified where the walk is already driven.
The branch had priced two holes as one. Arming a claimed function on MSI needs
silicon or a boot config; the
Truncated/Absentsplit needs neither.kernel/src/drivers/virtio.rs'scap_selftestalready drove the real walk overa cyclic list, a misaligned link, a below-header link and a forbidden head
through
PciDevice::over_config, so each case now also reads back what thewalk's end made of a capability, and prints its own verdict line,
pci cap split.pci_capability_walkisTier::Fast, so that half is on theper-pull-request gate and cost no new registration at all.
2. The arming's own answer is read back, not only
capability's.bring_upmatches on
enable_msix, so each walk case now assertsdevice.enable_msix(0)as well as
device.capability(msix::CAP_ID). No layout there publishes an MSI-Xcapability the walk reaches, so the call returns at its lookup and touches no
MMIO.
3. A case that both finds a capability and truncates, and holds a real table
past the forbidden link. Every layout published only
PCI_CAP_ID_VENDOR, soOk(_) => "found"was unreachable and the split only ever separated absent fromtruncated. The row is now
&[(0x40, msi::CAP_ID, 0x43), (0x44, msix::CAP_ID, 0)]— a capability the walkreaches, a link the spec forbids, and an MSI-X capability past it. With only the
first tuple,
capability(msix::CAP_ID)answeredTruncatedover a config spaceholding no MSI-X capability anywhere, so the case could not tell a walk stopped
at the forbidden link from one that reached the end of a list with no table;
with the second,
truncatedmeans "there is one and it was not read", which isthe discrimination the refusal exists for.
CASESstays 15 andSPLITS13: therow joins a case rather than adding one.
4. MSI-X first is asserted where a function actually publishes both.
tests/e1000case/system.tomlhands netdpci:8086:10d3— QEMU'se1000e,which publishes MSI at 0xd0 and MSI-X at 0xa0 (read off the device model over
0xcf8/0xcfc at
.github/qemu-version's 11.1.0) — andhttps_tls13_e1000eisTier::Fast.iommu::armed_on_msixtakes thevendor:devicethe boot configdeclares (
Bench::claims) and requiresmsix address=for the slot that claimis on while refusing
msi address=there. Point 17 is where that slot stoppedbeing whichever one the guest printed.
5. A vacuous assertion is gone, for the second time.
pci_function_is_exclusiveassertedmust_not_say(MSI_ARMED)on00:03.0,whose capability list is MSI-X at 0x98 and five vendor capabilities — no id 0x05
anywhere — so no mutation of this kernel can print that line.
94341ce1haddeleted the identical assertion from
tests/common/iommu.rsfor that reason andit returned one file over. Its
must_say(MSIX_ARMED)neighbour goes too: on afunction whose only armable mechanism is MSI-X a hand-over is the msix line,
and the
handovers != 1refusal above already requires one.MSI_ARMEDisdeleted, and the
msix address=line has one spelling —faults::msix_armed(),read by the arm that requires it and by every judge that requires its absence
(point 17, which is where the second spelling of it was finally closed).
6. The refusals the deleted register carried are recorded again.
76fb456ddeleted
pcidev's "What is read back, and what is not", and the two issue filesthis branch filed recorded only the MSI arm and the configuration write.
issues/kernel/a-claims-own-refusals-are-read-by-nothing.mdrecords the rest:ClaimError::Ambiguous,KernelDrivenandExhausted, every window refusal,and every bound
SYS_DEVICE_BAR_MAPandSYS_DEVICE_DMA_ALLOCcheck.7.
kind: defectover a body saying nothing has ever run the write.issues/hardware/toyos-i219-refuses-a-part-outside-msi-x-mode-at-ivar.mdis afinding;issues/README.mdgivesdefectas "real, reproducible".8. The kernel-driven fallback says once why it is safe.
hda::arm_interruptandxhci::wait::boot::arm_interruptstill take MSI onwhatever a truncated walk reached.
PciDevice::enable_msi's own doc is wherethat is said, because it is the call both of them make: a driver in this kernel
hands no BAR of its function to a holder, so an MSI-X table past a forbidden
link is one nobody but this kernel could reach. Neither site restates it.
9. The truncation refusal has a judge, and the branch no longer carries a
privilege path a one-field mutation cannot see. Round 3 reported that
reverting
bring_up's twoNoTablearms left every tier green, and the trackerpriced the alternative at "a boot config carrying such a function and a test
binary to hold it, plus that boot's tier row and CI price". That price is wrong
twice: the arm under test is a refusal, so no holder is needed, and the
kernel's own actuator machinery reaches inside this arming path already.
pcidev-caps-truncatedis oneactuators!row;StagedCapsinkernel/src/drivers/pci.rsholds one requester id across the hand-over's ownwalks and
CapabilityIter::nextends that function's list one byte off dwordalignment after its MSI capability, leaving every other walk in the machine
reading the list the device published.
pci_claim_caps_truncated(
Tier::Fast,tests/common/faults.rs) bootstests/e1000caseunder it andreads
faults::refused_claim— the refusal on the known slot by its own reason,neither
msi address=normsix address=for that function, no hand-over of[8086:10d3], no BAR moved, init's refusal line — then netd's exit,Boot: completeand a clean console. Mutation 1 below is the negative controlit was added with.
10. The vacuous assertion is deleted a third time, by ruling.
iommu::armed_on_msixwas called fromtls13_judgefor both benches, somust_not_say("PCI 00:03.0: msi address=")ran on everyhttps_tls13—1af4:1041publishes no id 0x05, so that arm is green on every implementationof this kernel. It is the identical arm
94341ce1deleted andeea8c7f7deleted again, reinstated one call site further out. The orchestrator's round-4
ruling is that it is deleted and stays deleted. There is no
must_not_sayof anmsi address=intests/common/https.rsat all now:tls13_judgeanswers theboot console, and the
https_tls13_e1000eregistration — the one bench whoseclaimed function publishes both mechanisms — makes the assertion.
11.
Bench::claimsis read against the file it names. It restatedtests/e1000case/system.toml'sdevicesrow in Rust, which is the drifttests/common/devices.rs'sthe_config_runs_exactly_these_jobsexists toprevent.
every_bench_claims_what_its_config_declaresfollows that pattern: itreads each bench's
system.tomlwithtoml::from_str, the parserload_audio_baselinealready readstests/audio-baseline.tomlwith, indexesprograms.netd.devices—netcasedeclares the same function twice, once fornetd and once for the test binary that asks for a second claim — and asserts the
constant against that row.
What round 4 changed
12. One refused-claim judge, where there were three copies.
faults::claim_caps_truncatedhad been written beside two arms that already didthe job:
virtio_net_no_msixandiommu::no_unit_is_no_claimeach asserted therefusal line, the reason, no hand-over, no BAR, init's line.
refused_claim(log, claims, why)is that judge and all three call it, so a kernel that answered arefusal by logging it and handing the function over anyway is red wherever the
refusal is reached. What stays at a caller is that arm's own: the argv check and
the audio function for the crippled NIC, the actuator's parameter for the
truncated list, and — on the machine with no unit — that nothing at all was
handed over, which is more than the claim's own refusal says.
13. The refused function's address is the harness's, never the guest's.
The judge read the BDF out of the console and then asserted about that, which
is an assertion about whichever function the kernel happened to name. It knows
the profile's slot (
00:03.0), refuses a console that refused any otherfunction, and anchors each line to it:
pcidev: PCI 00:03.0 NOT HANDED OVER — <reason>is one anchored match rather than two unanchored ones. The controlbelow shows it working — the base kernel refuses the same function with a
different reason and the anchored line reds on it.
14. One spelling of each thing the judge reads.
NO_FUNCTIONwas declaredin
kernel/src/drivers/pci.rsand again inkernel/src/iommu/vtd/fault.rs; itis declared once now, where a function's address is a triple, and the fault
handler reads it through the import it already had.
NETD_EXITSwas declaredtwice and is declared once.
1af4:1041was written in three places and is readfrom
https::VIRTIO.claims, the constant point 11 holds against the committeddevicesrow. The two lines a hand-over spends are built bybar_movedandmsix_armed, so the arm requiring them and the arm requiring their absencecannot drift apart. What this round missed is that
iommu::armed_on_msixspelledmsix address=a third time, which is point 17.15. Prose deleted, not moved. The escalation story — read the early end as a
terminator, MSI armed on the guess,
msix_barwithholding no BAR — was told atpcidev/mod.rs's header, atdrivers/pci.rs'sStagedCapsand again in thejudge's doc. The header keeps it and the other two are gone.
16. A compromise on the ordinary path is recorded.
place_bars'sSome(index) == table_barmutated to(Some(index) == table_bar && false)handsthe MSI-X table's own BAR to the holder of every function that publishes a table,
and
https_tls13,https_tls13_e1000e,pci_function_is_exclusiveanduserdev_dma_faultare each green on it — mutation 5 below, with the spellingthat builds and the bare
falsethat does not. It is pre-existing:place_bars's line isdc38a054's own, byte for byte, and this branch neitherwrote nor moved it. It is not fixed here — it is a bullet in
issues/kernel/a-claims-own-refusals-are-read-by-nothing.md, which this branchcreated for exactly that list. A refused claim is not the arm that would cover
it; the refusal spends no BAR at all, so what is unread is the hand-over that
succeeds.
What round 5 changed
17. The MSI-X judge asserts the harness's address too. Point 13 applied
round 4's ruling to
refused_claimand stopped one file over.iommu::armed_on_msixstill read the BDF out of the guest's own[{claims}] handed over on slotline and then assertedmsix address=andmsi address=for that, which is an assertion about whichever function thekernel named — and it is the same third spelling of
msix address=point 14said there was one of. It reads
faults::CLAIMED_ATnow, asserts the printedaddress equal to it, and spends
faults::msix_armed()and the newfaults::msi_armed(); the older mechanism's line gets the constructor the newerone already had, so neither is written in two places. Mutation 4 below is what
that buys: a kernel that arms MSI on the claimed function and names another
one in its hand-over line passed the old judge and reds on this one.
18. A text scan that cannot parse a line refuses instead of dropping it.
refused_claim's walk overNOT HANDED OVERlines was twofilter_maps, so aline carrying the marker without the
pcidev: PCIprefix left the listsilently. The empty list already reds; what did not was a partial miss — one
refusal the scan can read on
CLAIMED_ATand a second it cannot read at all,which is exactly the console "refused any other function" exists to catch. A
text scan closes only the spellings it matches, so the unmatched one is now the
finding:
faults::functions_namedis that walk for both judges and answers anErrnaming the line and the marker.19. Prose corrected where it is evidence. The issue file no longer counts
the refusals that are read back — this branch's own judge moved that count, so
it lists them instead. Its
place_barsbullet spells the mutation in the formthat builds and names the four tests measured green on it rather than claiming
every tier.
CLAIMED_AT's doc said "the slot every profile in this suite putsthe function netd claims on"; no profile puts it anywhere — the slot is QEMU's
assignment by
-deviceorder,git grep 'addr=' -- tests/common/qemu.rsprintsnothing, and
Profile::Metalcarries no such function at all — so it says whatis true of the constant: a wrong one reds and never passes. And the control
below cited
toyos.rs:18383, whichdc38a054's merge had moved onto a doccomment; the refusal is
assert_fast_profile_labelattests/toyos.rs:18399-18405.Retracted by name
History is not rewritten here, so these are withdrawn rather than edited.
6d59a093's message and this body saidPciDevice::capabilityreplaced"seven copies of
capabilities().find(|c| c.id() == …)— the four indrivers/pci.rs". Both halves are false.git grep -n 'capabilities()\.find' 8261079e -- kernel toyos-pci userlandprints 6 lines, 3 of them in
kernel/src/drivers/pci.rs; the otherthree are
hda::power_up,pcidev::resetandpcidev::msix_bar. The seventhcaller,
disable_msi, is new code on this branch and replaced no copy.a2be5f84's message says "The five remaining readers ofcapability" andthen names six.
a2be5f84's message justified deletinguserland/netd/src/i219.rs's BARclause with "which this branch falsifies — the T14's
00:1f.6publishes noMSI-X, so nothing is withheld from that claim". False. That clause is
about code which runs on
tests/e1000casetoo, where the claimed8086:10d3does publish MSI-X with its table in BAR 3 — so the kernel does withhold that
BAR and does report 0 bytes for it. The invariant returns as one clause at the
site.
68ba8df6's message and the round-2 handoff all saidpci_function_is_exclusive's MSI-X-first assertion "cannot be shown by amutation: no function this harness hands to a claim publishes both
mechanisms". False.
tests/e1000casehands one to a claim on the fasttier, and mutation 2 below is run against it.
eea8c7f7's message and this body offered "-D dead-coderefuses a kernel inwhich
Refusal::CapsTruncatedis never constructed" as what stood against theunwitnessed privilege arm. It is not a guard. The lint fires only on a
mutation that keeps the variant while deleting its constructor; it fires on
the mutation, never on a regression that reached
main; and an#[allow]or any later arm that constructs the variant removes it silently. The whole
change reverted — the arms collapsed and the variant deleted, which is the
form CLAUDE.md's mutation rule asks for — builds clean, exit 0, and is
mutation 1 below.
issues/kernel/nothing-reaches-the-msi-arm-of-a-claimed-function.mdpriced aguest arm at "a boot config carrying such a function and a test binary to hold
it". Refuted by this tree, and the file is corrected: the shape is staged
on a function an existing boot config already hands to a claim, and a refusal
needs no holder. What the file still tracks is the MSI arm that succeeds,
which nothing in any tier reaches.
ad61ed08and then8261079e. Each measurement below names the head it was taken at, becausethis branch has had two since: every green row, mutations 1, 4 and 5 and the
size numbers were run at
348ac77f, which this head (f0073d33) is one doccomment and no code away from; the negative control and mutations 2 and 3 are
d82dff33's, the head before the merge of9f91b581, and nothing that movedbetween the two is on a path any of them touches.
The two checks
Negative control — anchored by name to
dc38a054, never to a relativeexpression a merge moves. For every path the control reverts,
dc38a054, theearlier anchors
8261079eandad61ed08, andmain's tip as merged in thishead (
9f91b581) all hold the same bytes:git diff --name-only ad61ed08 dc38a054 -- <those paths>prints nothing, andgit diff --name-only dc38a054 9f91b581prints.claude/agents/reviewer.mdandsrc/durations.rs— neither a reverted path nor a judge — so re-anchoring movesno byte of what is reverted. It reverts the 16 non-judge paths this branch's
own commits touch and keeps the four judges —
tests/common/faults.rs,tests/common/https.rs,tests/common/iommu.rs,tests/toyos.rs— plustests/test-durations, which is not a judge but is theprice row
tests/toyos.rs's registration requires (reverting it too makes theharness refuse the run by name in
assert_fast_profile_label,tests/toyos.rs:18399-18405, instead of running either arm).kernel/src/iommu/vtd/fault.rsjoins the list this round: it readsdrivers/pci.rs's oneNO_FUNCTIONnow, so a control that reverted thedeclaration without it would not compile.
printed exactly
Run at
d82dff33, the control kernel builds — exit 0 — and two judges gored, each the command's own exit status:
exit 1 — and its
ALONEline reads "red again on a DIFFERENT failure",which is the harness comparing two strings that carry the kernel timestamp
(
0.128and0.105): one assertion, twice, under two clocks. Andexit 1. That is the anchored match earning its place: the base refuses the
same function on the same slot, and the judge reds on the reason rather than
passing on the words
NOT HANDED OVERappearing somewhere. Restore:git reset --hard HEAD,git status --porcelainempty,git rev-parse HEADunchanged at
d82dff33.What the control does not discriminate, stated rather than implied.
pci_claim_caps_truncatedcannot run on it at all, and no kernel is whatrefuses it: the actuator and the staging it needs are part of the reverted
change, so the harness refuses the parameter before a guest is started —
tests/common/qemu.rs:2648,"pcidev-caps-truncated" is a kernel_params and the kernel declares no such actuator or parameter, exit 1 with nothing booted. Its negative control is mutation 1, which is thesame revert of the same decision with the instrument left in place.
https_tls13_e1000estays green on the reverted base, exit 0: the e1000epublishes MSI-X either way, so the base arms MSI-X too. That arm is a guard on
the owner's direction, shown by mutation 2, not a judge of this diff.
Refusal::MsixUnusable,Unarmed::Blocked,Armed::Msiand bothdisable_msisites likewise revert with every arm green, because nothing in any tier arms a
claimed function on MSI successfully. That is what
issues/kernel/nothing-reaches-the-msi-arm-of-a-claimed-function.mdstilltracks, still a weakness, with the bench as its exit condition.
A mutation is a measurement only once the mutated tree is shown to build, so
each below quotes its build's exit status before its judge's — and mutation 5
is there because one spelling of it does not build at all. The build
is
cargo build --target x86_64-unknown-none --features boot-actuators,test-actuatorsinkernel/, withtarget/debugonPATHfortoyos-ld— the same target and featuressrc/clippy.rs's third shape and theharness's own kernel build use.
Mutation 1 — the privilege decision, and it reds (re-run at this head).
bring_up's twoNoTablearms replaced by one falling through toenable_msi,with
Refusal::CapsTruncatedand itsDisplayarm deleted —git grep -c CapsTruncated -- kernelmatches no file — so the whole change is reverted,which is also why it builds. Build exit 0, then
cargo test --test toyos-build -- pci_claim_caps_truncatedexit 1:The judge names what it judges and what the console did instead —
refused []is a boot in which no claim was refused at all — and the three lines above are
the hand-over that happened in its place.
BAR 3 is the BAR that function's MSI-X table register names (
0xa4 = 0x00000003, BIR 3, offset 0, read off the device model), and the mutated kernelmoved it and handed it to netd with everything else. That is the escalation the
two arms stand between.
Mutation 2 — the ordering (at
d82dff33).bring_uptriesenable_msifirst and falls back to
enable_msix, nothing else touched. Build exit 0,then
cargo test --test toyos-build -- https_tls13_e1000eexit 1:Every fetch, refusal and differential arm below it still passed — the card works
on MSI, which is why nothing but this assertion sees the order.
Mutation 3 — the arming's own answer (at
d82dff33).enable_msix'smap_err(Unarmed::NoTable)replaced by one reporting every miss asAbsent.Build exit 0, then
cargo test --test toyos-build -- pci_capability_walkexit 1:
with
15/15green beside it: two counts, and only the one that read thedecision moves.
Mutation 4 — the judge's own address, and the partial fix it used to pass.
bring_uparms MSI first (mutation 2's defect) and the hand-over line printspci.dev + 1, so the kernel takes the older mechanism on the claimed functionand names a different one in the line the old judge read its address out of.
Against the judge as point 4 shipped it this was green: it found
00:04.0'smsix address=and called an MSI-armed00:03.0MSI-X-first. Build exit 0,then
cargo test --test toyos-build -- https_tls13_e1000eexit 1:The capture is the whole argument: three
msix address=lines are on thatconsole and one of them belongs to the claim. A judge that takes its address
from the guest picks whichever the guest offers it; this one names
00:03.0before reading anything, and the
msi address=on that slot is what it wouldhave gone on to refuse.
Mutation 5 — the recorded compromise, and it stays green (point 16).
place_bars'sSome(index) == table_barmutated to(Some(index) == table_bar && false): build exit 0, thenhttps_tls13andhttps_tls13_e1000eexit 0,pci_function_is_exclusiveexit 0,userdev_dma_faultexit 0. The barefalsethe tracker used to spell itwith does not compile —
error: unused variable: table_bar,-D unused-variables implied by -D warnings, build exit 101 — which is whythe issue file now carries the form that builds. This is the one mutation here
run to show that nothing reds.
Independent oracles, two, neither of them another agent.
/proc/interruptson the T14names its NIC's interrupt
IR-PCI-MSI-0000:00:1f.6 … enp0s31f6and/sys/bus/pci/devices/0000:00:1f.6/msi_irqs/162readsmode=msi. A drivernobody here wrote, on the same silicon, saying that function is an MSI part.
toyos-pci's tests encode it. PCI §6.7 fixesa capability pointer as dword-aligned and above the 64-byte standard header,
which is what makes an early-ending walk a fact about the list and not
about the function. An implementation that reads a misaligned pointer, a
below-header pointer or a cycle as a clean end is red at
a_pointer_that_is_not_dword_aligned_is_refused,a_pointer_below_the_standard_header_is_refusedanda_pointer_to_a_visited_link_ends_the_walk; one that calls the terminator anearly end is red at
the_terminator_ends_the_walkanda_forward_chain_is_followed_to_its_end.Green
Every row is the line the command printed in
/Users/jan/Dev/jan/toyos-msi, withthe exit status of the command itself and never a pipeline's, measured at this
head.
cargo test --test toyos-build -- pci_claim_caps_truncatedPASS pci_claim_caps_truncated (2s)/test result: ok. 1 passed, 1 total (4.9s)cargo test --test toyos-build -- pci_capability_walkPASS pci_capability_walk (2s)/test result: ok. 1 passed, 1 total (3.3s)cargo test --test toyos-build -- https_tls13(the filter is a prefix, so it selects both bench names)PASS https_tls13 (4s)/PASS https_tls13_e1000e (4s)/test result: ok. 2 passed, 2 total (6.0s)cargo test --test toyos-build -- virtio_net_no_msixPASS virtio_net_no_msix (2s)/test result: ok. 1 passed, 1 total (2.2s)cargo test --test toyos-build -- pci_function_is_exclusivePASS pci_function_is_exclusive (2s)/test result: ok. 1 passed, 1 total (3.4s)cargo test --test toyos-build -- --nightly iommu_virtio_platform(the arm whose no-unit judge round 4 moved)PASS iommu_virtio_platform (6s)/test result: ok. 1 passed, 1 total (7.6s)cargo test --libtest result: ok. 308 passed; 0 failed; 1 ignored; 0 measured; 0 filtered outcargo test --workspace --exclude toyos-buildtest result: oklines, 1367 passed, 0 failed, noFAILEDlinecargo clippyshapessrc/clippy.rsdeclares, run one by one as thehostjob runs themd82dff33)FAIL pci_capability_walkandFAIL virtio_net_no_msixd82dff33)The price row is no longer a marker.
pci_claim_caps_truncatedenteredtests/test-durationsas anUNMEASUREDmarker withshards=none, which isthe documented two-cycle cost of a new registration: the marker buys the name
one measured CI run and the next commit carries that price. Run
35100393637,twelve hosted shards at
a75b3828, priced it at 2583 ms, and itstest-durations-mergedartifact carries the row; that run'sdurationsjobreds by name on the committed marker — "committed UNMEASURED profile marker(s)
are provisional and may not land: pci_claim_caps_truncated" — and says to
replace it with the measured value.
pci_claim_caps_truncated 2583 shards=12is now the row. 2583 ms is under
FAST_COMMIT_MS(8000), soTier::Fastis thetier its price gives it and no registration moves. That one row is taken and no
other: every other name in the merged artifact is this run's shard luck, which
src/durations.rsmeasures at 1.28x p10-p90.Two reds in an earlier battery were a host going down. At
23ef7817virtio_net_no_msixandpci_function_is_exclusiveeach failed withBoot timed out waiting for ===READY===; the console carried: nothing at all— no guest byteat all, twice, in the minutes before the development host rebooted into a new OS
build and wiped
/tmp. Both are exit 0 in the table above, which is measuredafter that reboot, as is every other row in it.
Size
git diff --shortstat origin/main HEADis21 files changed, 712 insertions(+), 198 deletions(-); acrosskernel toyos-pci tests userlandthe--numstatsumsto
+575 / −155. Nothing outsidekernel/,toyos-pci/,tests/,userland/netd/andissues/is touched by this branch's own commits: no Cargomanifest, no
NOTICE, nosourcegaterow, nosrc/tiers.rsrelegation row, noCLAUDE.md, and no syscall added, changed or retired. What it does add to theharness is one registered name, one
actuators!row and that name's measuredprice row.
🤖 Generated with Claude Code
https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK