re-org docs

This commit is contained in:
Daniel Samson
2026-07-23 00:25:34 +01:00
parent 52d6e372fd
commit 757c6f14c3
52 changed files with 156 additions and 156 deletions
+63 -63
View File
@@ -3,102 +3,102 @@
Notes on how danos boots and draws, written to explain the *why* behind the code
rather than restate it. Roughly in the order things happen at runtime:
1. **[efi.md](os-development-guide/efi.md) — EFI / the boot process.** How UEFI firmware finds and
1. **[efi.md](os-development/efi.md) — EFI / the boot process.** How UEFI firmware finds and
runs the bootloader, what the loader gathers before `ExitBootServices`, how it
loads the kernel ELF, and the ABI contract for the jump into the kernel. Start
here.
2. **[system-image.md](os-development-guide/system-image.md) — system.img, the boot capsule.** The
2. **[system-image.md](os-development/system-image.md) — system.img, the boot capsule.** The
bundled user binaries packed into one file in the initial-ramdisk wire
format, because one open + one sequential read is the only file I/O shape
firmware is fast at. The trivial container format, the three artifacts one
build list derives (tree, manifest, capsule), the loader's three-strategy
fallback chain, and the capsule's kernel-side life as both the spawn table
and the read-only `/system` mount.
3. **[gop.md](os-development-guide/gop.md) — the Graphics Output Protocol.** How UEFI exposes graphics
3. **[gop.md](os-development/gop.md) — the Graphics Output Protocol.** How UEFI exposes graphics
modes (unlike fixed VGA modes), how we detect the monitor's native resolution
from EDID and switch to it, and the pixel formats we accept or reject.
4. **[framebuffer.md](os-development-guide/framebuffer.md) — the framebuffer.** What the linear
4. **[framebuffer.md](os-development/framebuffer.md) — the framebuffer.** What the linear
framebuffer the loader hands over actually is, and what **pitch** (stride)
means versus width — the detail you have to get right to avoid a skewed image.
5. **[memory-map.md](os-development-guide/memory-map.md) — the memory map.** How the loader learns what
5. **[memory-map.md](os-development/memory-map.md) — the memory map.** How the loader learns what
physical RAM exists and hands it to the kernel in danos's own neutral format,
rather than leaking UEFI's memory descriptors across the boundary.
6. **[frame-allocator.md](os-development-guide/frame-allocator.md) — the physical frame allocator.** The
6. **[frame-allocator.md](os-development/frame-allocator.md) — the physical frame allocator.** The
bitmap allocator that hands out and reclaims 4 KiB physical frames from that
map — the primitive page tables and the heap are built on.
7. **[interrupts.md](os-development-guide/interrupts.md) — interrupts and exceptions.** The GDT, IDT and
7. **[interrupts.md](os-development/interrupts.md) — interrupts and exceptions.** The GDT, IDT and
TSS, the exception stubs, and the handler that reports a CPU fault in red instead
of letting it triple-fault into a silent reset.
8. **[paging.md](os-development-guide/paging.md) — the kernel's page tables.** Building our own 4-level
8. **[paging.md](os-development/paging.md) — the kernel's page tables.** Building our own 4-level
page tables, identity-mapping the low 4 GiB, and switching CR3 off the firmware's
tables onto ours.
9. **[device-interrupts.md](device-driver-development-guide/device-interrupts.md) — device interrupts.** The Local
9. **[device-interrupts.md](device-driver-development/device-interrupts.md) — device interrupts.** The Local
APIC and its timer — the kernel's first interrupt that is *handled and returned
from*, giving it a heartbeat.
10. **[heap.md](os-development-guide/heap.md) — the kernel heap.** A growable free-list allocator built on
10. **[heap.md](os-development/heap.md) — the kernel heap.** A growable free-list allocator built on
the VMM, exposed as a `std.mem.Allocator` so std containers work — dynamic
allocation for the kernel.
11. **[scheduling.md](os-development-guide/scheduling.md) — the scheduler.** Fixed-priority preemptive
11. **[scheduling.md](os-development/scheduling.md) — the scheduler.** Fixed-priority preemptive
multitasking: kernel threads, the context switch, O(1) priority selection, and
blocking (sleep, wait queues) — the leap to a running system.
12. **[ipc.md](device-driver-development-guide/ipc.md) — inter-process communication.** Bounded blocking
12. **[ipc.md](device-driver-development/ipc.md) — inter-process communication.** Bounded blocking
message-passing channels, then synchronous call/reply between *processes* over
endpoints — the backbone the microkernel's isolated servers talk over.
13. **[syscall.md](os-development-guide/syscall.md) — system calls.** How ring 3 asks the kernel for
13. **[syscall.md](os-development/syscall.md) — system calls.** How ring 3 asks the kernel for
something: the `syscall`/`sysret` fast path, the trap frame, and why the table is
deliberately tiny. The numbers are a **private** ABI — [vdso.md](os-development-guide/vdso.md) designs
deliberately tiny. The numbers are a **private** ABI — [vdso.md](os-development/vdso.md) designs
the public boundary that will hide them.
14. **[vfs-protocol.md](file-system-development/vfs-protocol.md) — the VFS wire protocol.** The language-neutral
byte-level spec of the file protocol spoken over IPC: request/reply headers,
the operation table, mount routing, and the append-only evolution rules — the
first IPC protocol documented as public ABI.
15. **[drivers.md](device-driver-development-guide/drivers.md) — writing a driver.** The payoff: a driver is an
15. **[drivers.md](device-driver-development/drivers.md) — writing a driver.** The payoff: a driver is an
ordinary ring-3 process that claims a device, maps its registers, and **sleeps
until its hardware interrupts it**. The claim is the capability; `irq_ack` is the
unmask.
16. **[driver-model.md](device-driver-development-guide/driver-model.md) — buses, classes and host controllers.** How
16. **[driver-model.md](device-driver-development/driver-model.md) — buses, classes and host controllers.** How
real driver stacks factor into three shapes and how families share code. The
three primitives it proposed are long since built (M13 capability passing,
M14 DMA + barriers, M15 MSI), and the driver *contract* on top of them —
hello, supervision, restart — is built too (device-manager.md, M18).
17. **[usb-hub.md](device-driver-development-guide/usb-hub.md) — USB hubs.** Built (M22): why hub topology is handled
17. **[usb-hub.md](device-driver-development/usb-hub.md) — USB hubs.** Built (M22): why hub topology is handled
*inside* the `usb-xhci-bus` driver rather than a separate hub class driver — a
device behind a hub is reached by the **controller**, programmed with a route
string in its slot context — plus the compound-hub reality (a USB 3.0 hub is
physically two hubs) and detection via the hub's status-change interrupt endpoint.
18. **[process-management.md](os-development-guide/process-management.md) — process management.** The
18. **[process-management.md](os-development/process-management.md) — process management.** The
microkernel's `ps`/`kill`/SIGCHLD: enumerate as a table snapshot, the
supervision link as the kill authority, and child-exit notifications over the
same endpoints IRQs arrive on.
19. **[process-lifecycle.md](os-development-guide/process-lifecycle.md) — the process lifecycle.** Built
19. **[process-lifecycle.md](os-development/process-lifecycle.md) — the process lifecycle.** Built
(M17): signals over IPC as the one lifecycle vocabulary every process speaks — the
POSIX.1-1990 words with message delivery instead of stack hijack, the stable
`process` module interface, exit reasons, published exit events any stateful
service can subscribe to (the VFS releasing dead clients' handles), and the two
iron rules (cleanup is the kernel's job; kill is not a signal).
20. **[device-manager.md](device-driver-development-guide/device-manager.md) — the device manager.** Built (M18,
20. **[device-manager.md](device-driver-development/device-manager.md) — the device manager.** Built (M18,
through the app surface): the
tree, the matcher, and the supervisor. Tree structure lives in the manager,
authority stays in the kernel; bus drivers report what they see; drivers are
restarted through the lifecycle vocabulary — the plan that turns
[resilience.md](os-development-guide/resilience.md)'s restart goal into increments.
21. **[input.md](device-driver-development-guide/input.md) — the input module.** Broadcasting input events (keyboard,
[resilience.md](os-development/resilience.md)'s restart goal into increments.
21. **[input.md](device-driver-development/input.md) — the input module.** Broadcasting input events (keyboard,
mouse, joystick): why a synchronous rendezvous can't fan out to many listeners, the
asynchronous `ipc_send` primitive built to fix it, and the per-device subscribe/publish
service layered on top.
22. **[display.md](device-driver-development-guide/display.md) — the display service.** The display half of the GUI
22. **[display.md](device-driver-development/display.md) — the display service.** The display half of the GUI
track: a user-space compositor that owns the framebuffer, composes a layer stack into
a double buffer, and presents it. Why GOP and the PCI display device are two views of
one controller, the device-node + write-combining handoff, and what flicker-free buys
that tear-free doesn't. Plan: [display-plan.md](device-driver-development-guide/display-plan.md). **v2** (complete) makes
that tear-free doesn't. Plan: [display-plan.md](device-driver-development/display-plan.md). **v2** (complete) makes
scanout a pluggable backend — GOP floor + a native virtio-gpu driver, hot-attached, with
runtime mode-set, EDID, fenced vsync presents, and restart re-attach:
[display-v2.md](device-driver-development-guide/display-v2.md), plan [display-v2-plan.md](device-driver-development-guide/display-v2-plan.md). Looking
[display-v2.md](device-driver-development/display-v2.md), plan [display-v2-plan.md](device-driver-development/display-v2-plan.md). Looking
further out, three research snapshots survey what a *native* driver for real GPU silicon
would take as another `.scanout` backend: [nvidia-gpus.md](device-driver-development-guide/nvidia-gpus.md) (RTX 3060 /
Ampere), [amd-gpus.md](device-driver-development-guide/amd-gpus.md) (RX 6600 / RDNA2), and [intel-igpu.md](device-driver-development-guide/intel-igpu.md)
would take as another `.scanout` backend: [nvidia-gpus.md](device-driver-development/nvidia-gpus.md) (RTX 3060 /
Ampere), [amd-gpus.md](device-driver-development/amd-gpus.md) (RX 6600 / RDNA2), and [intel-igpu.md](device-driver-development/intel-igpu.md)
(Intel iGPU).
23. **[halting.md](os-development-guide/halting.md) — halting.** Why a kernel can't just "exit", and
23. **[halting.md](os-development/halting.md) — halting.** Why a kernel can't just "exit", and
how `while (true) hlt` parks the CPU safely once there's nothing left to do.
Start with the north star:
@@ -108,7 +108,7 @@ Start with the north star:
**resilience** (restartable components). Win condition: runs on the author's PC and
both Raspberry Pis, ideally with a GUI. Real-time is an option to explore, not a
requirement. The *why* that shapes everything below.
- **[resilience.md](os-development-guide/resilience.md) — resilience.** A design note (not built yet) on
- **[resilience.md](os-development/resilience.md) — resilience.** A design note (not built yet) on
fault isolation + live restart — the reincarnation-server + capability model that
makes "if I break it, I can restart it" real. danos's core motivation.
- **[zig-self-hosting.md](zig-self-hosting.md) — running Zig on danos.** A design note
@@ -117,14 +117,14 @@ Start with the north star:
port to **one seam** (`std.os.danos`), so we build an `os` seam module (→ that seam) plus
the thin `file-system` module, retire the `posix` shim, and follow a phased path to
`zig build-exe hello.zig` running on danos — **not** Linux-ABI emulation.
- **[threading.md](os-development-guide/threading.md) — threads, the std-shaped way.** **Built** (M1–M6):
- **[threading.md](os-development/threading.md) — threads, the std-shaped way.** **Built** (M1–M6):
the `thread` module's `Thread` mirrors `std.Thread`'s API (spawn/join/detach, Mutex/Condition/
Semaphore) over a **private** thread ABI — several tasks sharing one address space via
a `thread_spawn` syscall, futex-backed blocking, address-space refcounting. Why it's the
native type and not literal `std.Thread` (the [private ABI](os-development-guide/syscall.md)), and why
threads stay a narrow opt-in against the [resilience](os-development-guide/resilience.md) default. Build
plan + gates: [threading-plan.md](os-development-guide/threading-plan.md).
- **[vdso.md](os-development-guide/vdso.md) — the vDSO, the public system-call boundary.** A design note
native type and not literal `std.Thread` (the [private ABI](os-development/syscall.md)), and why
threads stay a narrow opt-in against the [resilience](os-development/resilience.md) default. Build
plan + gates: [threading-plan.md](os-development/threading-plan.md).
- **[vdso.md](os-development/vdso.md) — the vDSO, the public system-call boundary.** A design note
(not built yet) on keeping `abi.zig` genuinely private: a kernel-supplied, C-ABI
entry blob mapped into every process as the *only* way into the kernel — so the
syscall numbers can be renumbered or randomised at will, and Rust/C binaries get a
@@ -137,69 +137,69 @@ Cutting across all of these:
hardware needed to run danos: minimum specs (UEFI x86-64, ACPI, PCIe ECAM,
xHCI, ~128 MiB RAM) grounded in what the boot path actually assumes, plus a
plain-language guide matching Intel/AMD CPU generations by name.
- **[release-iso.md](os-development-guide/release-iso.md) — the release ISO.** The flashable boot
- **[release-iso.md](os-development/release-iso.md) — the release ISO.** The flashable boot
media: `zig build release-x86-64` wraps the FAT32 boot volume in a hybrid ISO
(MBR ESP partition + El Torito EFI entry, one embedded image) that Etcher/dd
flash to USB or a burner writes to disc — built by an in-repo pure-Python
tool, like the FAT image itself.
- **[architecture.md](os-development-guide/architecture.md) — the architecture split.** How CPU-specific code is kept
- **[architecture.md](os-development/architecture.md) — the architecture split.** How CPU-specific code is kept
behind a build-time `arch` module so the generic kernel never names x86_64,
leaving room for other systems (e.g. an AArch64 Raspberry Pi) later.
- **[arm.md](os-development-guide/arm.md) — ARM targets.** The Raspberry Pi landscape the arch split is
- **[arm.md](os-development/arm.md) — ARM targets.** The Raspberry Pi landscape the arch split is
aiming at: `arm` (32-bit, Pi Zero W) vs `aarch64` (64-bit, Pi 3-5), UEFI vs
device-tree boot, and what each layer needs.
- **[discovery.md](os-development-guide/discovery.md) — device discovery.** A design note on learning what
- **[discovery.md](os-development/discovery.md) — device discovery.** A design note on learning what
hardware exists via ACPI (x86) or device tree (ARM) behind one neutral device model —
when to build it, and how to keep it architecture-agnostic.
- **[acpi.md](os-development-guide/acpi.md) — finding the ACPI tables.** The concrete x86 locator chain:
- **[acpi.md](os-development/acpi.md) — finding the ACPI tables.** The concrete x86 locator chain:
how the loader captures the **RSDP**, hands its physical address across in `BootInformation`,
and how the platform derives the **RSDT/XSDT** from it and walks the SDTs — plus the
live event side (the SCI, the power button, GPE/Notify) the ring-3 acpi service runs.
- **[power.md](os-development-guide/power.md) — the power service.** System power as a domain-named
- **[power.md](os-development/power.md) — the power service.** System power as a domain-named
service: button/lid/battery events published to subscribers, and init's orderly
shutdown composing the [lifecycle](os-development-guide/process-lifecycle.md) stop sequence with an ACPI
shutdown composing the [lifecycle](os-development/process-lifecycle.md) stop sequence with an ACPI
S5 write. Firmware-neutral — a PSCI backend drops in on ARM.
- **[timers.md](os-development-guide/timers.md) — timers and time.** The ring-3 surface for reading the
- **[timers.md](os-development/timers.md) — timers and time.** The ring-3 surface for reading the
clock and waiting: why `now()` is a syscall rather than a service, and the one-shot
timer notification (`timer_bind`) that gives supervisors a timed wait — built on the
LAPIC heartbeat and calibrated TSC of [device-interrupts.md](device-driver-development-guide/device-interrupts.md).
- **[smp.md](os-development-guide/smp.md) — multiple cores.** A design/research note on how microkernels
LAPIC heartbeat and calibrated TSC of [device-interrupts.md](device-driver-development/device-interrupts.md).
- **[smp.md](os-development/smp.md) — multiple cores.** A design/research note on how microkernels
(L4, seL4) handle SMP — big kernel lock vs per-CPU vs multikernel — and how the
right choice depends on whether danos is chasing real-time or resilience.
- **[coding-standards.md](coding-standards.md) — coding standards.** The naming rule the
tree follows: non-acronyms are spelled out in full (`message`, not `msg`), files are
`kebab-case`, code follows Zig's case conventions, and the handful of exceptions
(POSIX/C ABI names, `init`/`len`/`ptr`, acronyms).
- **[sysv.md](os-development-guide/sysv.md) — the calling convention.** What "the kernel is SysV" means,
- **[sysv.md](os-development/sysv.md) — the calling convention.** What "the kernel is SysV" means,
and why the loader→kernel boundary has to pin it (the RDI-vs-RCX handoff).
- **[testing.md](testing.md) — testing.** How the kernel is tested by booting it in
QEMU and asserting on its serial output — reproducibly, and structured so the
same tests run across architectures.
- **[logging.md](os-development-guide/logging.md) — logging.** The multi-sink diagnostic log (serial,
- **[logging.md](os-development/logging.md) — logging.** The multi-sink diagnostic log (serial,
0xE9 debugcon, file later) kept separate from the framebuffer display, plus the
robustness path: optional framebuffer, POST-code checkpoints, and a persistent
panic breadcrumb so the kernel survives — and can be diagnosed — with no output.
## How the pieces relate
The boot flow ties them together: UEFI runs the loader ([efi.md](os-development-guide/efi.md)), which
queries the **GOP** to pick a graphics mode ([gop.md](os-development-guide/gop.md)), hands the kernel a
**framebuffer** to draw into ([framebuffer.md](os-development-guide/framebuffer.md)) and a **memory
map** of physical RAM ([memory-map.md](os-development-guide/memory-map.md)); the kernel turns that map
into a **frame allocator** ([frame-allocator.md](os-development-guide/frame-allocator.md)), installs
its **descriptor tables** so CPU faults are caught ([interrupts.md](os-development-guide/interrupts.md)),
builds its own **page tables** and switches onto them ([paging.md](os-development-guide/paging.md)),
brings up the **heap** for dynamic allocation ([heap.md](os-development-guide/heap.md)), starts the
**scheduler** ([scheduling.md](os-development-guide/scheduling.md)) and the **timer** that preempts it
([device-interrupts.md](device-driver-development-guide/device-interrupts.md)) — with tasks blocking, sleeping and
passing messages over **[IPC](device-driver-development-guide/ipc.md)** channels — runs, its CPU-specific bits
behind the [architecture](os-development-guide/architecture.md) boundary, and when idle, or on a panic, it **halts**
([halting.md](os-development-guide/halting.md)).
The boot flow ties them together: UEFI runs the loader ([efi.md](os-development/efi.md)), which
queries the **GOP** to pick a graphics mode ([gop.md](os-development/gop.md)), hands the kernel a
**framebuffer** to draw into ([framebuffer.md](os-development/framebuffer.md)) and a **memory
map** of physical RAM ([memory-map.md](os-development/memory-map.md)); the kernel turns that map
into a **frame allocator** ([frame-allocator.md](os-development/frame-allocator.md)), installs
its **descriptor tables** so CPU faults are caught ([interrupts.md](os-development/interrupts.md)),
builds its own **page tables** and switches onto them ([paging.md](os-development/paging.md)),
brings up the **heap** for dynamic allocation ([heap.md](os-development/heap.md)), starts the
**scheduler** ([scheduling.md](os-development/scheduling.md)) and the **timer** that preempts it
([device-interrupts.md](device-driver-development/device-interrupts.md)) — with tasks blocking, sleeping and
passing messages over **[IPC](device-driver-development/ipc.md)** channels — runs, its CPU-specific bits
behind the [architecture](os-development/architecture.md) boundary, and when idle, or on a panic, it **halts**
([halting.md](os-development/halting.md)).
Above that line the microkernel proper begins: **discovery** ([discovery.md](os-development-guide/discovery.md),
[acpi.md](os-development-guide/acpi.md)) learns what hardware exists, ring-3 processes ask the kernel for
things through the small **[syscall](os-development-guide/syscall.md)** table, isolated servers reach each
other over IPC **endpoints** ([ipc.md](device-driver-development-guide/ipc.md)), and a **[driver](device-driver-development-guide/drivers.md)** claims
Above that line the microkernel proper begins: **discovery** ([discovery.md](os-development/discovery.md),
[acpi.md](os-development/acpi.md)) learns what hardware exists, ring-3 processes ask the kernel for
things through the small **[syscall](os-development/syscall.md)** table, isolated servers reach each
other over IPC **endpoints** ([ipc.md](device-driver-development/ipc.md)), and a **[driver](device-driver-development/drivers.md)** claims
a device, maps its registers, and sleeps until the hardware interrupts it — which is
the whole reason for the arrangement ([vision.md](vision.md)).