re-org docs
This commit is contained in:
+63
-63
@@ -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)).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user