Repository navigation
PCI root bridges are acpiserver's declaration: each root's _CRS windows and _OSC offer, held by the kernel; the loader's window reads go (PCI apertures stage B) - #935
Conversation
…clare, pcidev state) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
# Conflicts: # kernel/src/pcidev/mod.rs # lib/acpi/tests/resource.rs
…vers map at identity Work in progress before review; the PR body states the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
…the _OSC grant Ruled for lifecycle stage 2, which arms hot-plug ports under a granting root: acpiserver negotiates each root's _OSC under the PCI host bridge UUID (PCI Firmware Specification 3.3 section 4.5) in the pass that reads its _CRS, and the kernel keeps the records and says each grant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
# Conflicts: # kernel/src/arch/aarch64/smmu/domain.rs # kernel/src/arch/x86_64/amdvi/domain.rs # kernel/src/arch/x86_64/amdvi/mod.rs # kernel/src/pcidev/mod.rs # tests/toyos.rs
|
Metal at
|
…eclaration fails every metal boot The AMD bench's root has more memory windows than the per-root bound of 8, so at 4f5142f its declaration was refused, every claim on it would have been, and no row saw it: its boot claims nothing and its row judges kernel-driven domains. The windows are now one list of 64 across every root; acpiserver says each root's count and its _CRS bytes under OWN, so the bench's next boot records them. Every metal boot now fails on the kernel's refused-declaration record, and the AMD row requires the declaration. The host bridge _OSC tests gain QEMU q35's masked shape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
Review of #935 at
|
…ried only, the no-acpi-row loss recorded - A declaration whose records the ABI does not name (a count or run past its array, an unnamed _OSC word, a reversed bus range) or whose roots share a bus on one segment is refused through Held like any other refusal: logged, posted, and the answer (toyos_pci::aperture::records). - The root _OSC is a query alone and its offer is recorded; the hot-plug service that acts on native hot-plug control (#934) commits it, so the osc module's condition holds. - issues/an-x86-machine-with-no-acpi-row-hands-over-no-pci-claim.md. - window.rs: Addresses::map's contract stated per arm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
Owner ruling: the kernel stops driving PCI functions (step 10) before this lands, so no kernel driver needs a domain before the declaration. The window rule is the one rule again, for every domain: above the CPU where the unit has room, and otherwise clear of the declared windows, with no domain where nothing is declared. A claim passes its declaration; a kernel driver, which comes up before any declaration, passes none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
|
Round 1 at
Also in this round:
|
So #934 commits through this ABI unchanged: a root's record holds what its query offered and what a commit (Query clear) was granted, none in stage B. A commit beside no offer, or of bits not offered, is a record the ABI does not name, refused by name with the declaration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
|
Host tests: an offer with no commit decodes; a commit decodes beside an offer covering it; a commit beside no offer, beyond the offer, or under an unnamed word is none; |
Conflicts resolved against main's changes since 3b77b9b: - #947 deleted kernel/pci/src/placement.rs and issues/no-boot-reaches-the-retry-that-undoes-a-placement-nothing-answered.md; the branch's hunks there (a doc comment and an import, and the issue's exit) were about the placement that no longer exists, so both stay deleted. issues/an-aarch64-cargo-run-boot-hands-over-no-pci-claim.md stays deleted: main's one-line edit restated how its windows are read, which this branch replaces. - K1's IOVA allocator (6cb27ce): a domain's allowed addresses are still the unit's range less every reserved range, but the root bridges' windows now come per domain from the declaration (`Domains::prepare`), beside the backend's own reserved ranges (RMRRs, IVMDs, the interrupt range, AMD-Vi's special range, the ITS doorbell), which `avoid` keeps. No declaration, no domain. `OwnSpace::create` takes the declared windows; the IOMMU selftests, which run before any declaration on QEMU's root bus, pass none. - pcidev: main's `publish` without the loader's list, and the declaration, its wait and its refusals as on the branch. - KernelArgs: main's `slot_volume_guid` follows `microcode_len` at 456; 472 bytes. - The supervisor (27b75c3): the `acpi` claim's holder starts before the disk drivers, whose claims wait for its declaration. - acpicase: main's nvme and usbd rows claim PCI functions on a boot whose only `acpi` holder is a job, so it keeps no storage rows; the probe's held-function arm takes the console function the kernel drives, the only function a kernel driver still holds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
Main's benchcase and hostedclangcase came with nvme and usbd rows and no `acpi` claim holder, so on this branch their first claim would wait out its deadline and every claim of the boot would be refused. Both start acpiserver now, and a build host test holds the rule for every config: one whose rows claim a PCI function starts a row holding the `acpi` claim, undeclaredcase alone excepted, since it is booted to judge that refusal. Issues directly affected by the loader's window reads going: - the GCD map's held MMIO descriptors: deleted, since the loader reads no GCD map any more; - the hypervisor and ACPI tracks and the BarUnrouted tooling issue name `_CRS` where they named the loader's reads; - the x86 no-acpi-row issue names the disk drivers, which main's block service split made the claimants; - new: the ACPI server's death has no readback on the T14, since its boot's first `acpi` holder is a job and no row declares before usbd's claim. Issues that named closed drafts as owners: the four scheduler findings #872's S2 and S3 were to settle are the placement track's, which owns the push, the victim choice and wake placement; the speed track's line naming #865 as the CPU cap's owner goes, since #976 sized every per-CPU table for the CPUs firmware names; the ACPI track's `_CST` line keeps its issue and drops #870. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
The merge of main left the kernel's virtio console with no domain before the declaration: main's IOVA allocator builds every domain clear of the root bridges' windows, and the console comes up before acpiserver declares them. On VT-d the console keeps the identity domain and works; on virt's SMMUv3 its stream aborts, so `cargo run -- --arch aarch64` panics in `wait_used` before userland. The issue this branch had closed stays open with that cause, owned by this track, since how a kernel driver gets a domain before any declaration is the owner's to decide. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
benchcase: main's osbench round 2 beside the ACPI server this branch starts there. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
…2d60) into wt/toyos-lifecycle-2 Lifecycle stage 2 rebuilt on main and stage B. - pcidev: stage B's module is the base. The per-requester records, the device set's generation and snapshot, `Gone` on an older arrival's claim, the departed release and retirement, and the slot's interrupt are this branch's, over main's BAR records (`Decoded`); `Machine::windows` and the placement state are gone with #947. - An arrived function's BARs: `place_unassigned` and `behind_bridges` are gone. Each BAR the device leaves unassigned is given, before the function is listed, the lowest address inside its port's windows that no other function decodes in and that the declared root bridges' memory holds (`toyos_pci::hotplug::{Windows, assign}`, host-tested), written once and kept where the register reads it back, with no probe through it. Its BARs enter `Machine::decoded` and leave it on retirement. `bar::placement` stays for that one write, refusing only an I/O BAR and asserting the caller's own choice. - The slots are armed by stage B's declaration, from `pcidev::declare`, below a root whose `_OSC` commit was granted native hot-plug and the capability structure. acpiserver commits both where its query offered both (`osc::negotiate_root`); the declaration carries the grant. The boot-time arm with no bridges is gone. - A slot's port reads its own bus numbers and windows: main deleted `toyos_pci::bridge` and `PciDevice::bridge`. `PciDevice::header_type` tells a bridge below a slot. - Two readers of the set never enumerate one arrival twice (`REFRESHING`). - ABI: the device set's object kind is 15 and its syscalls 135 and 136, past main's; the static `IrqWatch` poll returns for its watch. - supervisor: main's `drive_where` reads the device set, says what joined and left, and decides over the rows asked for. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
Its job must make the boot's first acpi claim, so no row declares the root bridges' memory, and usbd's stick claim, which carries the log, waits out the deadline. The T14 boot at 4e32df6 ran the job and stopped cleanly, and its kernel.log came back empty. A row that cannot produce a readback is a defective registration, so it goes with its judge and the helper only it used. No QEMU row takes its place: QEMU's firmware hands over in ACPI mode, so the release has no legacy mode to return to. `acpi_release` stays, run by nothing. The issue's exit is the row registered again on a boot that has a log, and the issues and the ACPI track that read the row point there. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
- KernelArgs: main's boot images (#994) without the loader's root bridge windows; 504 bytes, root_image at 184. - loader: main's payload module, no rootbridge. - supervisor: start_service takes main's spawn (the image's source, the boot images) and skips SYSTEM, which starts before the manifest. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
Review of #935, round 2: pushed
|
- iommu::DeviceSpace::create's doc and the virtio console's comment say what the code does today: a driver in this kernel comes up before the declaration and keeps the machine's addresses. The owner's decision on that changes the code later. - acpi_release goes with its row and judge. Nothing ran it, and the issue's exit restores all three. - The aarch64 issue says the console loses the domain main gives it. - The two new issues are owned by the ACPI track. The PR they were named after closes on landing. - Docs: MAX_WINDOWS states the AMD bench's measured 16, `Osc::Offered` names no stage, and the config test says which claims it does not see. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
#935's review round 2. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
…r it is listed Since #994, SYSTEM is the first service in the list, started before the manifest was read. The holder count taken from the list's front therefore found none, the disk drivers' claims were made before acpiserver ran, and they waited out the declaration's deadline. `the_log_lands_on_the_boot_stick` went red on it after the merge of main. The declaring rows are now partitioned out of the whole list and started first, and the session home step makes every declarer's home. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q
|
Round 2 at
Suggestions:
The rows were checked against logs kept locally. Evidence publication waits on the owner. |
Review of #935, round 3, at
|
Status: draft. Merged with
maind7f269dbcatf9e44e0fb. It waits on the owner's item 53 (below): until it is decided,cargo run -- --arch aarch64panics before userland. Review round 2's four items are answered (round-2 comment). Host CI, both image builds and the five QEMU rows the review asked for are green at the head. Metal at4e32df68c: AMD passed, T14testcasespassed, T14acpicasehad no log, as predicted; its row is now unregistered (below).Problem
cargo run -- --arch aarch64handed over none of its four PCI claims. The loader's window list (each root bridge'sConfiguration()plus every unowned GCD MMIO range) counted ECAM and flash among the declared windows (#916). The owner's ruling: aperture discovery leaves the loader, AML stays in acpiserver, and a refused or missing declaration fails closed.Owner item 53: a kernel driver's domain before the declaration
Main's IOVA allocator (K1,
kernel::iova, #974) builds every domain clear of the root bridges' declared windows, and drops the old rule that placed a domain above the CPU's addresses where the unit translates wider. Option 1, an identity-placed domain for a kernel driver, was withdrawn on this PR on the premise that after step 10 no kernel driver needs a domain before the declaration. The kernel's virtio console still does: it comes up before acpiserver declares, so it gets no domain (iommu: no domain of its own for a device: no declaration of the root bridges' windows is held) and keeps the machine's addresses.maingives it.virt's SMMUv3 a stream with no domain aborts, so the console's first queue completes nothing and the kernel panics inwait_used(UART log, lines 204 to 213). Thevirtguest rows pass because their console bypasses the unit.Options:
cargo run's terminal shows nothing after the loader.issues/an-aarch64-cargo-run-boot-hands-over-no-pci-claim.mdstays open with this cause. This branch had closed it at4f5142fea, where the boot handed over all four claims.What this changes
system/acpiserver/src/apertures.rs):_SEG, the bus range and the memory windows of_CRS(toyos_acpi::root_bridge), including Word, DWord, QWord and Extended descriptors, and steps over I/O._OSCunder the PCI host bridge UUID: revision 1, Support = extended config space and MSI, Control asked = native hot-plug and the PCIe capability structure. It records the offer and makes no commit; Functions arrive and leave: the device set, native PCIe hot-plug, Gone (lifecycle stage 2) #934, which services hot-plug, commits._TRA, a consumed range, an unknown descriptor, a second or out-of-range bus range, a root with no bus range, more than 16 roots, more than 64 windows across all roots.toyos_abi::acpi::Apertures): segment, buses, the_OSCoffer, a commit's grant, and a run of one shared window list. It travels throughop::DECLAREon the acpi claim. Functions arrive and leave: the device set, native PCIe hot-plug, Gone (lifecycle stage 2) #934 consumes this shape.kernel/src/pcidev): only from the acpi claim's holder and only fromUnknown; every record checked against the ABI, then every window together (whole, disjoint, none over RAM). Any failure refuses by name, wakes the waiters and stands as the answer. The holder's claim ending first withholds it (Ended).Unanswered).Readback::declaration_not_refused), and the AMD row requires the declared-windows record.Domains::avoid, and less the declared windows, which each claim passes (OwnSpace::create(room, windows)). No declaration, no domain. The AMD-Vi and SMMU selftests, which run before any declaration with the test device on QEMU's root bus, pass none.the_log_lands_on_the_boot_stickwait out the deadline, a defect the merge brought andf9e44e0fbfixes.benchcaseandhostedclangcasenow too, and a build host test holds it (every_config_that_claims_a_pci_function_starts_its_declarer;undeclaredcaseis the one exception, booted to judge the refusal).acpicasehas no storage. Its first acpi holder is a job, so no row declares before the supervisor's own claims; main's nvme and usbd rows there would wait out the deadline and refuse every claim. The probe's held-function arm moves to the console function the kernel drives.acpi_server_deathis unregistered, with its judge and its jobacpi_release: its job must hold the boot's first acpi claim, so nothing declares before usbd's stick claim and the T14 boot has no log (measured at4e32df68c). No QEMU row can take its place, since QEMU's firmware hands over in ACPI mode.issues/the-acpi-servers-death-has-no-readback-on-the-t14.md, owned by the ACPI track, has re-registering all three as its exit.loader/src/gcd.rs,loader/src/rootbridge.rs,PciRootBridgeIo,KernelArgs::root_bridge_windowsand its count (KernelArgs1504 → 472 bytes), the OVMFConfiguration()fixture and its tests.an-x86-machine-with-no-acpi-row-hands-over-no-pci-claim.md, andthe-acpi-servers-death-has-no-readback-on-the-t14.md(below);the-gcd-maps-held-mmio-descriptors-are-logged-nowhere.md(the loader reads no GCD map);BarUnroutedtooling issue;_CSTline drops Design: idle CPUs enter the deep idle states the firmware declares #870.What each judge establishes
virt_claim_lpirequirespci: root 0000:00 _OSC: native hot-plug offered; VirtIts has a second root at bus 8.a_drives_row_holds_one_process_per_functionrequires q35'snot offered.a_claim_waits_out_an_undeclared_machine(q35, no acpiserver): the first claim waits 30 s, and both are refused by name.acpi_mediated_accessjudges theEndedtransition, and the console function'sHeldFunction.domains_map_clear_of_the_host_bridges(T14) reads every mapping against the acpi claim's declared windows.amdvi_translates_the_stick_controlleralso requires the declaration.Checks
Evidence:
pr-935at415052dc7. That commit was published through the GitHub API after the clone was refused, which the owner is deciding on.cargo run -- --ci hostf9e44e0fb--build-only, x86-64 and aarch64f9e44e0fba_drives_row_holds_one_process_per_function,a_claim_waits_out_an_undeclared_machine,acpi_mediated_access,virt_claim_lpi,the_log_lands_on_the_boot_stickf9e44e0fbe6dd4addf, before the supervisor fixe6dd4addfthe_log_lands_on_the_boot_stickstalled waiting for usbd, the defect fixed above1ffbdbaafcargo runx86-64 / aarch641ffbdbaaf4e32df68ctestcases: 3 passed. T14testcases: passed (3 windows declared, a claim waited 67 ms,_OSC: native hot-plug offered, buses 0x00..=0x79, no commit). T14acpicase: no log, the predicted outcome.Logs after
1ffbdbaafare kept locally and not published, pending the owner's word on evidence publication.Risks and open points
acpi_server_deathis unregistered until its T14 boot has a log (its issue, owned by the ACPI track)._CRSis still unmeasured byte for byte; its next boot logs the bytes and the window count.4f5142fea); Functions arrive and leave: the device set, native PCIe hot-plug, Gone (lifecycle stage 2) #934 commits it.🤖 Generated with Claude Code
https://claude.ai/code/session_01PXEk8BBMDT8tXu4AnENB9Q