Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ members = [
"lib/blackbox",
"lib/blockhold",
"lib/blockring",
"lib/blockserve",
"lib/bootmap",
"lib/crypto",
"lib/device-memory",
Expand All @@ -63,6 +64,7 @@ members = [
"lib/quiesce",
"lib/random",
"lib/rootimage",
"lib/scsi",
"lib/sha2",
"lib/sha2-hw",
"lib/swap",
Expand Down Expand Up @@ -115,6 +117,7 @@ members = [
"system/netstack/shard/testnet",
"system/netstack/udp",
"system/netstack/wire",
"system/nvme",
"system/pkg",
"system/ps2server",
"system/ps2server/ps2",
Expand Down
16 changes: 11 additions & 5 deletions images/console.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,20 @@ syscap = ["roster"]
"bin/shutdown" = "/system/bin/toybox"
"bin/stats" = "/system/bin/toybox"

# The block service: the NVMe controller this machine's DATA is on, driven
# from userland through its claim. Started again when it ends; the claim goes
# back with the process and is minted again for the next.
# The block service: every disk a driver offers on `disk`, listed and opened
# for the clients `block` grants, each session handed to its disk's driver.
# Started again when it ends; its drivers connect again and offer again.
[programs.diskserver]
service = true
restart = true
serves = ["block"]
devices = ["pci:01:08:02/1b36:0010"]
serves = ["block", "disk"]

# The NVMe driver: one process per such controller, reading its own table and
# offering its disk to the block service. QEMU's controller alone, so a metal
# boot leaves the bench's own NVMe disk to its firmware.
[programs.nvme]
drives = ["pci:01:08:02/1b36:0010"]
receives = ["disk"]

# The file servers: DATA, the log and the boot volume, one process
# each, serving every program the directories of its role. Started again when
Expand Down
16 changes: 11 additions & 5 deletions images/system.toml
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,20 @@ starts = ["toybox", "shell", "terminal", "doom", "snake", "calc", "editor", "pai
"bin/stats" = "/system/bin/toybox"
"bin/tone" = "/system/bin/toybox"

# The block service: the NVMe controller this machine's DATA is on, driven
# from userland through its claim. Started again when it ends; the claim goes
# back with the process and is minted again for the next.
# The block service: every disk a driver offers on `disk`, listed and opened
# for the clients `block` grants, each session handed to its disk's driver.
# Started again when it ends; its drivers connect again and offer again.
[programs.diskserver]
service = true
restart = true
serves = ["block"]
devices = ["pci:01:08:02/1b36:0010"]
serves = ["block", "disk"]

# The NVMe driver: one process per such controller, reading its own table and
# offering its disk to the block service. QEMU's controller alone, so a metal
# boot leaves the bench's own NVMe disk to its firmware.
[programs.nvme]
drives = ["pci:01:08:02/1b36:0010"]
receives = ["disk"]

# The file servers: DATA, the log and the boot volume, one process
# each, serving every program the directories of its role. Started again when
Expand Down
25 changes: 23 additions & 2 deletions issues/a-device-function-is-driven-from-its-arrival-to-its-end.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,22 @@ started. Nothing reaches userland when a device arrives or leaves.
pull request before stage 1's guest smoke
(`issues/a-cargo-run-boot-claims-every-pcidev-slot.md`).

**Ruled** (orchestrator, 2026-10-20, on the step-10 brief; it replaces #901's
`block@<location>` ports, `each`, `pci@` and several block services):

- One shared block service, diskserver, serves `block` to its clients
(unchanged: grants are supervisor-minted badges) and `disk` to disk drivers.
A disk driver is a `drives` row receiving `disk`: it reads its own GPT,
offers each disk's partitions, and says when a disk is gone.
- On an open the service checks the grant and hands the client's connection
and region to the offering driver, which answers `MSG_OPENED` on the
client's connection and serves the session itself; data never passes the
service (`toyos_blockring::disk`, `lib/blockserve`).
- The supervisor starts the `drives` processes before the storage rows and
tells the block service how many disk drivers it started. An open of a
partition no disk offers, and a listing, wait until every boot-started disk
driver has settled, each wait bounded and naming the driver that did not.

**Measured**:

- **Releases versus the end**, before stage 1a (`usbd_drives_the_spare` on
Expand Down Expand Up @@ -117,15 +133,20 @@ started. Nothing reaches userland when a device arrives or leaves.
then, and refuses every later offer. A driver gone after soundserver
began playing to it ends soundserver. QEMU's two-controller row is
`hda_plays_to_the_controller_that_reaches_an_output`.
- **Done for NVMe.** `nvme` is a `drives` row, one process per
controller, offering its disk to diskserver, which is the block service
alone (the ruling above).
- Next: virtio-sound is still driven inside soundserver
(`system/soundserver/src/virtio.rs`); it becomes a driver on the same
port. Then the output set: a second output offered while one plays, a
driver's `gone`, and a stream moved to another output, none of which
soundserver serves yet; and netstack and diskserver.
soundserver serves yet; and netstack.
4. **usbd drives every xHCI**, one per controller, started by stage 1's `drives` rows.
This is step 10 of
`issues/the-kernel-is-small-interrupts-post-and-threads-wait.md`, whose
`input` port is this track's per-device source and `gone`.
`input` port is this track's per-device source and `gone` (`toyos-input`
carries both), and whose sticks are disks offered on `disk` (the ruling
above).

## Folded here

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ opened: 2026-08-10
# A disk plugged in after boot is bound inside a scheduling pass

The BOT round trip and the SCSI bring-up above it are pure machines,
`toyos_xhci::bot::RoundTrip` and `toyos_xhci::scsi::BringUp`, and the kernel
`toyos_xhci::bot::RoundTrip` and `toyos_scsi::BringUp`, and the kernel
drives both blocking, in place. For the read/write entry points that is the
caller's own time. For the bind it is not: `msc::bind` is the one call site
where a scheduling pass can still spend its transfer budget inside xHCI — for a
Expand Down
67 changes: 40 additions & 27 deletions issues/diskserver-claims-qemus-nvme-by-its-pci-id.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@ kind: defect
opened: 2026-10-12
---

# diskserver claims QEMU's NVMe by its PCI id and no other controller

Both shipped boot configs give diskserver one device, `pci:01:08:02/1b36:0010`
(`images/system.toml`, `images/console.toml`): the NVMe class with the vendor and device id of
QEMU's own `nvme` model, under Red Hat's vendor id. The supervisor matches the id exactly
(`toyos_manifest::device::PciMatch`, `toyos_supervisor::claims`), so on any other NVMe controller it
endows diskserver nothing, diskserver says `no NVMe controller this row names is on
this machine; serving no partition`, and DATA, LOG and BOOT are absent unless
the image is on a USB stick the kernel drives. The driver is not QEMU's:
`Controller::open` (`system/diskserver/src/nvme.rs`) takes any function whose
class code is `01:08:02`.
# The NVMe driver drives QEMU's NVMe by its PCI id and no other controller

Both shipped boot configs give the `nvme` driver's `drives` row one matcher,
`pci:01:08:02/1b36:0010` (`images/system.toml`, `images/console.toml`): the NVMe class with the
vendor and device id of QEMU's own `nvme` model, under Red Hat's vendor id. The supervisor matches
the id exactly (`toyos_manifest::device::PciMatch`, `toyos_supervisor::drives`), so on any other
NVMe controller no driver starts, and DATA, LOG and BOOT are absent unless the image is on a USB
stick the kernel drives. The driver is not QEMU's: `Controller::open` (`system/nvme/src/nvme.rs`)
takes any function whose class code is `01:08:02`.

Read, not booted:

Expand All @@ -34,19 +32,34 @@ and bhyve each set. `issues/the-lan-is-not-yet-production-grade.md` plans the
same for NICs ("init binds drivers to hardware from a declared match table by
vendor, device and class").

Two constraints a class row meets that an id row does not: a machine with two
NVMe controllers matches twice, which refuses diskserver's start, naming both
(`toyos_supervisor::claims`); and a machine whose NVMe holds another operating system, as the T14's
holds Ubuntu, is handed to diskserver, which then serves only the partitions
its table and grants name (`system/diskserver/src/main.rs`).

**Owner**: whoever holds `issues/toyos-runs-in-any-open-source-hypervisor.md`.

**Exit**: a `devices` row names a PCI function by class code, which
`toyos_manifest::device::PciMatch::parse` takes and refuses malformed (#926); both
shipped configs name NVMe that way; and a guest boot whose controller is
QEMU's `nvme` with `use-intel-id=on` serves DATA through diskserver, which a
row naming `1b36:0010` instead reds. The configs the T14 boots keep their id
row, outside this exit, until the T14's NVMe holds no Ubuntu: a class row there
would hand diskserver the disk the metal workflow reboots through (the
orchestrator's ruling, #896, issuecomment-6131213771, ruling 4).
**A compromise #962 keeps**, accepted by the orchestrator there: the `nvme`
row names QEMU's id in every image, shipped and test alike, so that no metal
boot drives a bench's own NVMe disk — the T14's holds the Ubuntu the metal
loop reboots through after every boot (`tests/metal/src/lib.rs`). That is a
machine with an NVMe disk and no ToyOS driver for it.

**What a shipped image should drive**: every NVMe controller, by class code,
whatever machine it boots on — QEMU, another hypervisor, metal.

**What keeps another system's disk unwritten under a class row**, by reading
and not measured: the driver reads its table and resets and enables the
controller, and writes nothing outside a session. A session opens only what a
grant admits (`system/diskserver/src/main.rs`), and the supervisor mints
grants for the loader's LOG and BOOT GUIDs, for the `TOYOS-DATA` type, and for
`update` on the slots of the running ROOT's disk (`storage_endowment`,
`Supervisor::slot_grant`, `system/supervisor/src/main.rs`), none of which an
Ubuntu partition carries. Whether Ubuntu boots off a controller ToyOS drove
and reset is not measured.

**Owner**: the orchestrator, which dispatches it; the hypervisor track
(`issues/toyos-runs-in-any-open-source-hypervisor.md`) waits on it.

**Exit**: every image's `nvme` row names NVMe by class code, which
`toyos_manifest::device::PciMatch::parse` takes (#926); a guest boot whose
controller is QEMU's `nvme` with `use-intel-id=on` serves DATA through the block
service, which a row naming `1b36:0010` instead reds; a supervisor host test
holds that every block grant it mints names a loader-named GUID, a ToyOS
partition type, or the running ROOT disk's slots, red on a grant by any other
type; and a T14 row whose readback shows the nvme driver offering the T14's
disk with no session opened on any of its partitions, read after the metal
loop's own reboot into Ubuntu off that disk.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ kind: defect
opened: 2026-10-10
---

# diskserver's NVMe bring-up open-codes what `toyos-pci-claim` holds
# The NVMe driver's bring-up open-codes what `toyos-pci-claim` holds

`Controller::open` (`system/diskserver/src/nvme.rs`) maps BAR 0 with
`Controller::open` (`system/nvme/src/nvme.rs`) maps BAR 0 with
`PciDev::map_bar` and an `unsafe Window::new` over it, allocates its grant with
`PciDev::dma_alloc` and another `unsafe Window::new`, and names each kernel
refusal as `Refusal::Kernel(call, e)`. That is `Bar::map`, `Grant::alloc` and
`KernelRefused` of `lib/pci-claim/src/lib.rs`, which netstack's two
drivers and soundserver's virtio-sound driver use: two more `unsafe` sites
whose argument is the one the crate already makes.

Exit: diskserver reaches its BAR and grant through `toyos-pci-claim`, or the
Exit: the NVMe driver reaches its BAR and grant through `toyos-pci-claim`, or the
reason it cannot is at the crate's module header.
27 changes: 0 additions & 27 deletions issues/scsi-is-decoded-inside-the-xhci-crate.md

This file was deleted.

This file was deleted.

12 changes: 8 additions & 4 deletions issues/the-kernel-is-small-interrupts-post-and-threads-wait.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ Beside that order, each waiting on something outside it:
session reopened over the page a killed server left, by fileserver's
`a_directory_rename_is_whole_under_one_name_wherever_the_server_is_killed`
for DATA, and for LOG by the FAT test step 10 owes. **Partly done**
(#525, #536): diskserver drives NVMe, and the kernel's NVMe driver is
gone. **Left**: on the T14, `/log` and `/home` are on the
(#525, #536): NVMe is driven from userland, and the kernel's NVMe
driver is gone; the `nvme` driver offers its disk to diskserver, the block
service. **Left**: on the T14, `/log` and `/home` are on the
stick, which the kernel drives until step 10; the kernel's USB storage,
block layer, page cache and refusal chain go at step 9.
4. **Where the data filesystem lives** — owner ruling, 2026-09-26, from the
Expand Down Expand Up @@ -181,8 +182,11 @@ Beside that order, each waiting on something outside it:
`issues/a-device-function-is-driven-from-its-arrival-to-its-end.md`:
usbd is a `drives` row, one process per xHCI controller the kernel
leaves. The whole xHCI moves, HID delivered
to the owner of input over the `input` port and mass storage over
`toyos-blockring`. A USB keyboard's transitions never reach the
to the owner of input over the `input` port, each device its own
`source` with its own `gone`, and each stick a disk offered to the block
service on `disk`, whose sessions usbd serves over `toyos-blockring`
(`issues/a-device-function-is-driven-from-its-arrival-to-its-end.md`'s
block ruling, which replaces #901's `block@` ports). A USB keyboard's transitions never reach the
kernel, whose keyboard and mouse streams go when their last kernel
source leaves (the ruling on #899, applied to usbd on #901). It
depends on stage 7 step 2 landing first, because at step 10 usbd's
Expand Down
Loading