From 450d74d07f00023ad133a24834fbd3fffd7c0795 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sun, 18 Oct 2026 02:09:56 +0200 Subject: [PATCH] docs: add ADAPTERS.md with adapter structure, rules, and scaffolding guide --- docs/ADAPTERS.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 docs/ADAPTERS.md diff --git a/docs/ADAPTERS.md b/docs/ADAPTERS.md new file mode 100644 index 0000000..efdae0b --- /dev/null +++ b/docs/ADAPTERS.md @@ -0,0 +1,79 @@ +# Writing Adapters + +An adapter implements the `Platform` trait for a specific architecture. It is the only crate with `unsafe` code. + +## Scaffolding + +```bash +scripts/new-adapter.sh +``` + +This generates `crates/adapter-/` with the standard structure. Then: + +1. Add `"crates/adapter-"` to workspace `members` in `Cargo.toml` +2. Fill in `board.rs` with device addresses for the target board +3. Add boot assembly (`global_asm!` in `main.rs` or a `.S` file) +4. Update `linker.ld` for the target's entry address and memory layout +5. Implement the TODOs in `hw/`, `mmu/`, `trap/`, and `platform.rs` + +## Structure + +Every adapter follows this layout: + +``` +crates/adapter-/ +├── Cargo.toml +├── linker.ld +└── src/ + ├── main.rs — boot entry, kmain + ├── board.rs — all board/SoC constants in one place + ├── platform.rs — impl Platform (the contract with the kernel) + ├── hw/ — one file per hardware device + │ ├── uart.rs — serial output + │ ├── irq.rs — interrupt controller (PLIC, GIC, APIC, ...) + │ └── timer.rs — timer/clock + ├── mmu/ — memory management + │ ├── page_table.rs — architecture-specific page table format + │ └── allocator.rs — boot-time page allocator + └── trap/ — trap/exception handling + └── mod.rs — trap vector + Rust handler +``` + +## Rules + +- **`unsafe` is the absolute bare minimum.** Each `unsafe` block does exactly one hardware operation and is wrapped immediately in a safe function. You should be able to count every `unsafe` block on your fingers. +- **`board.rs` is the single source of truth for addresses.** UART base, interrupt controller base, RAM start — all in one file. If someone ports to a different board with the same architecture, they change one file. +- **The kernel never changes.** `Kernel` is generic. Adding a new adapter means zero changes to `domain/`, `kernel/`, `types/`, or `platform/`. + +## Existing Adapters + +| Adapter | Architecture | Target Board | Status | +|---------|-------------|-------------|--------| +| `adapter-riscv` | RISC-V 64-bit | QEMU virt | Phase 2 complete — boots, MMU, traps, timer, IPC demo | + +## Platform Trait + +The adapter implements all methods of the `Platform` trait defined in `crates/platform/src/lib.rs`: + +```rust +pub trait Platform { + fn configure_protection(&mut self, process: ProcessId, regions: &[MemoryRegion]); + fn context_switch(&mut self, from: &mut SavedContext, to: &SavedContext); + fn enable_user_mode(&mut self, entry: EntryPoint, stack: StackPointer) -> !; + fn set_timer(&mut self, duration: TimerDuration); + fn current_ticks(&self) -> Ticks; + fn mask_irq(&mut self, irq: IrqId); + fn unmask_irq(&mut self, irq: IrqId); + fn send_ipi(&mut self, target: CoreId); + fn core_id(&self) -> CoreId; + fn num_cores(&self) -> u8; + fn map_shared(&mut self, process: ProcessId, base: PhysicalAddress, size: PageCount, permissions: PermissionSet); +} +``` + +## Boot Flow + +1. Assembly entry (`_start`): set stack pointer, call `kmain` +2. `kmain`: zero BSS, init UART, init MMU, init traps, init timer +3. Create `Kernel`, call `kernel.boot()` +4. Start scheduling