Repository navigation
Conversation
Stage 2 of issues/a-device-function-is-driven-from-its-arrival-to-its-end.md. - The device set (toyos_abi::devset, SYS_DEVICE_SET/SYS_DEVICE_SET_READ): a level-triggered snapshot of every PCI function the kernel hands out, minted from DEVICE with READ and WAIT only, so the supervisor alone holds it. Its header carries the time by which a slot may change with no interrupt (PCIe 6.0 §6.6.1's wait, a command's §6.7.3.2 timeout). - pcidev keeps one record per requester, published one at a time, each carrying its live arrival: a returning device is a new arrival on the same record, so its domain id is reused. A claim of an older arrival answers Gone on every call; a departed function's release asks the device nothing, and its windows, firmware BARs, parked grants and residue are retired. - Native PCIe hot-plug on a port below a host bridge whose _OSC granted native hot-plug and capability structure control. The port is the kernel's, its MSI-X entry armed through the claim path's remapped message; the handler reads and clears Slot Status, takes a lost or button-removed slot's functions out of the set, issues at most one Slot Control write and posts the set's watch. Powering a slot, the 100 ms wait and enumeration run on the set's reader. The last release behind a removed slot powers it off. - An unassigned BAR behind a bridge is placed by placement::behind_bridges and accepted when the register reads the written address back with its flag bits intact. - toyos-supervisor: a departed arrival is never started again and is forgotten once nothing runs on it; the restart budget is the address's. - The supervisor reads the set, says what joined and left, and waits on its watch and its settle time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
…to nothing is no BAR A slot's handler posts the device set's watch, which the scheduler must exist for: the boot-time call is made after scheduler::init (a real declaration arrives from acpiserver later still). An unassigned register behind a bridge is placed only where its size probe answers a size: QEMU's edu's BAR 1 reads 0 and sizes to nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
…clared bus-mastering site Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
…ords 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
Japabu
added a commit
that referenced
this pull request
Oct 15, 2026
…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
Japabu
added a commit
that referenced
this pull request
Oct 15, 2026
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
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.
Stage 2 of
issues/a-device-function-is-driven-from-its-arrival-to-its-end.md, "Functions arrive and leave". Lands after the apertures track's stage B (#935), whose per-root declaration carries each host bridge's_OSCgrant: until it is merged here,pcidev::arm_hot_plugis called with no bridge, so no slot is armed, anda_function_arrives_and_leavesreds.The architecture was ruled by the orchestrator on this branch's design round (the ruling on points 1–7 is this PR's record): the kernel owns the slot's interrupt; arrival work runs on the device set's reader; the button means remove; one record per requester; the
_OSCgrant rides stage B's declaration; an unassigned BAR behind a bridge is placed bybehind_bridgesand proven by the register; the retired-grants exit is restated.What changes
toyos_abi::devset,SYS_DEVICE_SET,SYS_DEVICE_SET_READ,toyos::devset). It is a level-triggered snapshot of every PCI function the kernel hands out: a header (generation, settle time), then inventoryPcirecords in rising arrival order. It is minted from aSysCapcarryingDEVICE, withREADandWAITonly (noDUP, noTRANSFER), so the supervisor alone holds it.devset::decodeis the reader's boundary: no header, a wrong count, a non-PCI record, arrival 0, or a duplicate or out-of-order arrival is refused by name.SYS_DEVICE_INVENTORYstaysinspect's.kernel/src/pcidev). The published-once table becomes up to 512 records, one per requester id, each written once and read lock-free, and each carrying its live arrival. A device that returns is a new arrival on the same record, so it gets a new number and a new handle while reusing its domain, which the last release emptied: domain ids stay bounded by requesters, not plug cycles. Every call a claim of an older arrival makes answersGone(with_bound, the interrupt read,has_irqso a poll wakes). A departed function's release asks the device nothing: it drops the message and unmaps the grants before their pages go (tear_down_departed). It is then retired: its windows, firmware BARs, reset entry, parked grants and residue go.kernel/src/pcidev/slot.rs,toyos_pci::hotplug). A root or downstream port with a hot-plug-capable slot is armed only below a declared host bridge whose_OSCgranted native hot-plug and capability structure control (bits 0 and 4, PCI Firmware 3.3 §4.5.1). Otherwise each port says why by name, andpcidev: N host bridge(s) declared …prints the grant per bridge.device_delwaits for.placement::behind_bridgesand accepted when the register reads the written address back with its flag bits intact. This is the one case where pcidev: a BAR behind a bridge is placed only where every bridge on its path forwards #928's "the function answers its own firmware value" proof cannot apply, and the site says so (place_unassigned).bar::kindsplits a BAR's kind from its address, so an unassigned 32-bit BAR can be placed. A register that sizes to nothing is no BAR.unclaimablerefuses a function the IORT routes were not read for. A fault from a function the fault table does not know is handed to pcidev, which clears its bus mastering and names a claim or a departed function as the owner, so it does not halt the machine.PCI … joined the device set as arrival Nand… (arrival N) left the device set, and reads PCI records for starts from the set (DEVICE), no longer from the inventory.WouldBlock, then says what four calls answered and ends with 0.issues/a-released-function-never-claimed-again-keeps-its-retired-grants.md: retired grants are freed at departure; the exit for a function that stays and is never claimed again now depends on the deadline callback inissues/hotplug-blocks-a-scheduler-pass.md.Deleted:
pcidev::FUNCTIONSandarrival_of(an arrival is no longer an index),Machine::functions, VT-dbind's "every function was enumerated" assertion, and the supervisor's PCI reading from the inventory.The guest row and why it needs QEMU
a_function_arrives_and_leavesruns onProfile::HeadlessHotplugPort: q35, an emptypcie-root-port,acpi-pci-hotplug-with-bridge-support=off. It plugs aneduover QMP, which starts apciholder. Thendevice_delpresses the button. The claim answersGoneon its interrupt read, config read, BAR map and DMA grant; the holder ends with 0; the supervisor says the arrival left; QEMU reportsDEVICE_DELETEDonce the slot is off. A second plug is a new, larger arrival with a holder of its own. No bench has a hot-plug port the owner lets a driver claim behind, so physical arrival is QEMU-only; only QEMU arrives on demand. The slot's and the supervisor's decisions are host-tested.q35's own
_OSCgrants what the row needs only with that flag off. The DSDT QEMU builds differs in one byte,And(CDW3, 0x1F)off versus0x1Eon, and it answers a revision other than 1 as unrecognized (evidenceq35-osc/). Stage B's "q35 keeps native hot-plug" is the default machine.Checks and evidence (ToyOSOrg/evidence
pr-934, https://github.com/ToyOSOrg/evidence/tree/adcef6565dcd615b7fd2cf0d4209d0ec8439e0da/lifecycle-2)cargo run -- --ci hostat 927635e: exit 0, 86 steps green. An earlier run at a6ab756 found two reds this branch fixed: the new config's coverage row and the port's bus-mastering site.cargo run -- --build-onlyat 927635e: x86_64 exit 0, aarch64 exit 0.toyos-supervisor(arrive, depart and return as a new arrival; a departure while a start is pending; the address's budget on a returning device),toyos_abi::devset(round trip; every malformed snapshot refused),toyos_pci::hotplug(QEMU's port read whole; the Slot Control word; what a slot is owed; what a press removes),toyos_pci::bar(an unassigned BAR placed).a_function_arrives_and_leavesat a6ab756 withstand-in-grant.patch, standing in for stage B's declaration: exit 0 (hotplug-row/control-green.log). Arrival 12 was held, answeredGonefour times, and was retired; the second plug was arrival 13. This must be rerun on stage B's real grant after the merge.hotplug-row/controls.shand restored:mutation-gone-unansweredreds, with noDEVICE_DELETEDwithin 240 s.mutation-arrival-reusedreds, with "arrived as 12, not after 12".usbd_drives_the_spare,bar_map_again,bar_map_behind_a_bridge,a_drives_row_holds_one_process_per_functionat a6ab756: exit 0, 4 passed (claim-rows/). Later commits are a build-gate registry, issues and The ring comparator: toyos-crypto beside ring in a guest, on metal rows (crypto stage 2) #932's merge, none in pcidev's claim path.slot-qemu/): MSI-X only, entry 0; Slot Capabilities0x001a007b; OVMF leaves the slot off;device_delwaits for the OS to power it off.usbd_drives_the_type_c_controller(T14) andamdvi_translates_the_stick_controller(AMD). Nothing arrives on either bench. Together they establish that the boot set is unchanged and print each bridge's grant. Before stage B merges they read "0 host bridge(s) declared".Risks and open points
🤖 Generated with Claude Code
https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1