acpi: discovery is handed its node like every other driver

The last claimant. The kernel seeds the acpi-tables node, so it sits in the
same boot snapshot the manager already scans to find the PCI host bridge —
there was never a bootstrap problem, only a lookup nobody had written. The
manager claims it and names it in the spawn; the service stops claiming.

Every driver in the system now receives its hardware rather than taking it.

Two failures on the way, both mine. addDriver puts the device id in argv[1],
and the acpi service read argv[1] as a self-verify device-count floor — so
handed device 7 it decided it was in test mode, printed "acpi-parse: ok",
and never reported a device. The test argument is now floor:N, which a bare
id cannot be mistaken for.

And acpi-parse spawns the service directly rather than through the manager,
so nothing handed it the node. That test now claims and transfers it exactly
as the manager does, which is the right shape: the test plays the manager's
role instead of the service reaching for hardware.

device_claim now has two callers left: the manager, which is the acquirer
and should have it, and the display service's GOP path. That is recorded as
question 10 — the framebuffer is not a device, so the answer is likely that
it leaves the device table rather than being exempted from its rules.

Suite 118/118.
This commit is contained in:
Daniel Samson
2026-08-08 21:54:45 +01:00
parent 6b3a381626
commit b7d97ebb5d
4 changed files with 67 additions and 39 deletions
+25 -28
View File
@@ -43,10 +43,10 @@ that cannot safely run in user space.**
| D2 | Adversarial case: a process handed nothing is refused, on a held device and a free one | **done** — `device-authority-test`; the claim half joins it at D6 |
| D3 | The manager claims the seeded devices at boot, before any driver is spawned | **merged into D4** — see below |
| D4 | The manager claims + delegates on `hello`; `usb-xhci-bus` is the first driver converted | **done** — caught an IOMMU regression I introduced; see below |
| D5 | The other four claimants converted: `pci-bus`, `ps2-bus`, `virtio-gpu`, `acpi` | **partial** — `pci-bus` + `virtio-gpu` done; `ps2-bus` and discovery need question 9 |
| D5 | The other four claimants converted: `pci-bus`, `ps2-bus`, `virtio-gpu`, `acpi` | **done** — every driver now receives its hardware; question 9 answered |
| D0 | The grant rides `system_spawn` — atomic, so no driver need change to receive one | **done** — and caught a test-marker bug that made the D2 fixture unfailable |
| D10 | Every driver hellos, on its own merits (liveness, one class of driver) | not started — optional, independent |
| D6 | `device_claim` refuses a device the caller was not handed; the hole is closed | not started |
| D6 | `device_claim` refuses a device the caller was not handed; the hole is closed | **blocked on question 10** — only the display service's GOP path still claims |
| D7 | Zero-resource devices stop being kernel objects — inventory moves to the manager | **blocked** — nothing else mints their ids; see question 8 |
| D8 | **`maximum_children_per_parent` deleted** | **done** — it was unblocked from the moment D9 landed; I kept reading my own stale label |
| D9 | The device table becomes dynamic; **`maximum_devices` deleted**; per-holder quota declared | **done** — one of the two invented numbers is gone |
@@ -91,38 +91,35 @@ They land together, with the manager claiming only for drivers in an explicit
anything in D4 — recorded rather than dismissed, because D4 moved the `hello` earlier
and so did shift boot timing. Watch it across the remaining steps.
### Open question 9 — danos has two device-acquisition patterns; D6 fits only one
### Question 9 — answered: a singleton gets every device that matched it
Earlier versions of this question listed symptoms — "`ps2-bus` ignores its `argv[1]`",
"discovery has no assignment" — which hid that they are the same fact.
The 8042 is one controller described by two ACPI nodes, so it cannot be split across
processes. The manager now hands the single `ps2-bus` instance **every** matching node:
the first rides the spawn, the rest are transferred to the running instance. Late
arrival is safe because the ordering is natural rather than lucky — the controller node
carries the ports and is needed at once, the mouse node not until after identify
(measured: handed over at 0.336, first touched at 0.456). The count is whatever matched,
so a machine with no PS/2 ports or one port needs no special case.
| Pattern | Who | How it gets its device |
|---|---|---|
| Per-device driver | `pci-bus`, `usb-xhci-bus`, `virtio-gpu`, `usb-hid`, `usb-storage` | assigned one id, one instance per device — **all converted** |
| Singleton that finds its own | `ps2-bus`, discovery | spawned once with `no_device`, walks the table itself |
Discovery turned out not to be special either. The kernel seeds the `acpi-tables` node,
so it is in the same boot snapshot the manager already scans for the PCI host bridge —
it is handed over at spawn like everything else.
The second is deliberate, not an oversight. `onChildAdded` says so:
### Open question 10 — the framebuffer is the last thing anyone claims
> An hid-matched driver (ps2-bus) is a singleton that finds its own devices once
> spawned — spawn it once, no device assignment.
`device_claim` now has exactly two callers: the device manager, which is the acquirer
and should have it, and `system/services/display/backend.zig`, whose GOP path claims the
kernel-seeded display node.
`device_claim` is the mechanism that makes that pattern work. **D6 removes it and puts
nothing in its place**, which is the whole of the blockage.
Closing `device_claim` breaks the compositor's boot floor. Exempting it puts a hole in
the middle of the authority model, in the one place an exemption is most expensive.
The manager is not ignorant: it matched *both* `PNP0303` and `PNP0F13` to `ps2-bus` and
chose not to assign either, so it already knows which devices a singleton wants. An
answer is therefore in reach — hand a singleton each matching device as it matches. The
cost: only the first can ride the spawn, so later ones arrive while the driver is
running, and `ps2-bus` enumerates once at startup and would have to tolerate that.
**The decision: do singletons stop being singletons — one instance per device, like
everything else — or does the system keep a second acquisition path for them?** The
first is uniform and costs a rewrite of `ps2-bus`'s startup. The second keeps a
mechanism whose only remaining users are two drivers, and every exemption in an
authority model is somewhere the model does not hold.
Nothing else blocks D6. Both invented ceilings are already gone, so this is about
closing the claiming hole, not about a number.
The likely answer is neither. **The framebuffer is not a device** — it is where pixels
go, handed over by the loader, and the kernel wraps it in a `DeviceClass.display`
descriptor only so `mmio_map` can hand it over write-combining. If that is right, it
should leave the device table rather than be exempted from its rules, and the compositor
should receive the pixels some other way. That is a change to the display path, which is
out of scope for this run.
### Settled 2026-08-08: the grant rides `system_spawn` (D0)