Post-reorg cleanup: POSIX layer, and naming fixes

Follow-up to the monorepo re-org. Suite 35/35 plus host tests green.

POSIX compatibility is now its own library, library/posix/ (unistd, stdio),
layered strictly over the runtime — it calls the runtime's IPC/heap, never
system calls directly. The runtime is now POSIX-free (the danos-native
application ABI). The VFS wire protocol is danos-native throughout
(Stat -> FileStatus, .stat -> .status, O_CREAT -> create); the POSIX layer
maps the POSIX spellings at the boundary. The coding standard's ABI-name
exception is scoped to one place: a file is allowed POSIX spellings only if it
lives under library/posix/ — everywhere else, danos naming with no exception.

Naming fixes, all mechanical:
- initrd -> initial-ramdisk: the source file, the module, the tool
  (make-initial-ramdisk.py), the artifact (initial-ramdisk.img, including the
  bootloader's load path), and the identifiers.
- system/kernel/device-service.zig -> devices-broker.zig: it is ring-0 kernel
  code (the trusted device table + claim capability), not a ring-3 service. The
  future user-space device *manager* (policy) will live in system/services/.
- Dropped the daemon `d` suffix: hpetd -> hpet, busd -> bus. A driver lives in
  system/drivers/, so the folder already says what it is; encoding the role in
  the name too is redundant. The coding standard drops that exception.
- system/devices/aml/interp.zig -> interpreter.zig (the type was already
  Interpreter).
This commit is contained in:
Daniel Samson
2026-07-10 13:33:06 +01:00
parent 8754d4e46a
commit ceacc6b514
27 changed files with 308 additions and 254 deletions
+8 -8
View File
@@ -32,19 +32,19 @@ plain bus driver with no controller — a USB hub — is also a real thing.
## The device table is the spine
danos already has the right central structure. `system/kernel/device-service.zig` holds a table of
danos already has the right central structure. `system/kernel/devices-broker.zig` holds a table of
`DeviceDesc`, each with a parent, a class, and a set of resources. Firmware discovery
seeds it ([discovery.md](discovery.md)); `device_register` grows it.
Three invariants make it a capability system rather than a directory:
1. **A claim is exclusive.** `device_claim(id)` succeeds once. Everything downstream —
`mmio_map`, `irq_bind`, `device_register` — checks `device_service.ownerOf(id) == me`.
`mmio_map`, `irq_bind`, `device_register` — checks `devices_broker.ownerOf(id) == me`.
2. **A descriptor is a licence to map physical memory.** Whoever claims a device may
map its `.memory` resources and bind its `.irq` resources. This is why
`device_register` cannot be a free-for-all.
3. **Therefore: containment.** Every resource of a registered child must lie inside a
resource of the same kind on its parent (`device_service.contains`). A bus driver can only
resource of the same kind on its parent (`devices_broker.contains`). A bus driver can only
ever *subdivide* what it already holds. Without this, `device_register` would be a
syscall named "map any physical page you like."
@@ -57,7 +57,7 @@ is not an address window. Discovery is trusted; user space is not.
### What a bus driver looks like
`system/drivers/busd/busd.zig` is the smallest honest one. Its "bus" is the HPET's register block and
`system/drivers/bus/bus.zig` is the smallest honest one. Its "bus" is the HPET's register block and
its "devices" are the block's comparators:
```zig
@@ -78,7 +78,7 @@ for (0..n) |i| { // 3. publish each child
Each child is left **unclaimed**, which is the handoff: a comparator driver can now
`device_claim` one and `mmio_map` it, and will see only its own 0x20-byte window. A child
whose window escapes the bus is refused — `busd` asserts that, and the `bus` test
whose window escapes the bus is refused — `bus` asserts that, and the `bus` test
asserts the kernel's table upholds it.
A USB device has *no* resources at all: `resource_count = 0`, because it's addressed
@@ -247,7 +247,7 @@ barrier, or per-arch inline asm — which is what `library/mmio.zig` should hide
**The blocker, and it's a hard one.** No PCI device can take an interrupt today.
[`addBars`](system/devices/acpi.zig) records `.memory` and `.io_port` BARs and never an
`.irq`; there is no `_PRT` parsing anywhere in the tree. `hpetd` only works because the
`.irq`; there is no `_PRT` parsing anywhere in the tree. `hpet` only works because the
HPET advertises its own routing options in its own registers — a privilege no ordinary
device has.
@@ -271,7 +271,7 @@ which means **discovery should give each `pci_device` a `.memory` resource for i
4 KiB ECAM slot**. That's a small change to `parseMcfg` and it unblocks the whole
capability walk (MSI, MSI-X, PCIe extended caps) without any new syscall.
Note QEMU's HPET reports `Tn_FSB_INT_DEL_CAP = 0` — no MSI — so `hpetd` can never
Note QEMU's HPET reports `Tn_FSB_INT_DEL_CAP = 0` — no MSI — so `hpet` can never
exercise this path. The first MSI driver will be the first PCI driver.
## M16 — the IOMMU, and the honest caveat
@@ -291,7 +291,7 @@ gap should be named rather than implied.
`M13` (capability passing) is independent of `M14`/`M15` and is the cheapest. It
unlocks class drivers, which are the shape with no hardware requirements at all — you
could write a real one against `busd`'s comparators tomorrow.
could write a real one against `bus`'s comparators tomorrow.
`M14` and `M15` together unlock the first HCD. `M14`'s barrier layer is worth landing
on its own regardless: it's small, obviously correct, and stops every future driver