Roadmap
Development plan from bare-metal boot to self-hosting OS.
Table of contents
- Sprint Overview
- Sprint 1 — Boot & Serial Output ✅
- Sprint 2 — Memory Management ✅
- Sprint 3 — Interrupts & Exceptions ✅
- Sprint 4 — Processes & Scheduler
- Sprint 5 — Capabilities & IPC
- Sprint 6 — Syscall Interface & Userspace
- Sprint 7 — Init Process & First Program
- Sprint 9.5 — Reaper & Resource Teardown ✅
- Sprint 10 — Wasm Hypervisor ✅
- Sprint 11 — PCI & Device Discovery 🔧
- Future Milestones
- Contributing
Sprint Overview #
| Sprint | Focus | Status | Description |
|---|---|---|---|
| 1 | Boot & Serial | ✅ Complete | Toolchain, bootloader, serial UART, framebuffer console |
| 2 | Memory | ✅ Complete | PMM bitmap allocator, VMM page tables, kernel heap |
| 3 | Interrupts | ✅ Complete | GDT/TSS, IDT, ACPI/MADT, LAPIC, I/O APIC, W^X remap |
| 4 | Scheduler | ✅ Complete | Processes, threads, preemptive scheduler, SMP (4 cores) |
| 5 | Capabilities | ✅ Complete | CNode, capability types, IPC endpoints, synchronous IPC |
| 6 | Syscalls | ✅ Complete | SYSCALL/SYSRET, 12 syscalls, ELF loader, Ring 3 entry |
| 7–9 | Userspace | ✅ Complete | Init (PID 1), libmnos, TarFS, delegation, memory management |
| 9.5 | Reaper | ✅ Complete | DEAD_QUEUE, kernel stack reclamation, VMM walker, process teardown |
| 10 | Wasm Hypervisor | ✅ Complete | Ring 3 heap (4 MiB), wasmi interpreter, SFI hardware bridge (Wasm→COM1) |
| 11 | PCI & Devices | 🔧 In Progress | PCI bus enumeration, BAR parsing, virtio-blk driver, capability-gated MMIO |
Sprint 1 — Boot & Serial Output ✅ #
Get the kernel running, prove it with visible output.
- Rust nightly toolchain configuration (
rust-toolchain.toml) - Cargo workspace with kernel crate, dev/release profiles
.cargo/config.toml— bare-metal target, kernel code-model, no SSE/AVX, build-std- Linker script — higher-half kernel, page-aligned sections
- Limine bootloader configuration
- IRQ-safe ticket spinlock
PhysAddr/VirtAddrnewtypes with HHDM translation- COM1 serial UART driver — 16550, 115200 baud 8N1
- CPU primitives — halt, CR2/CR3, INVLPG, RDTSC, MSRs
- Limine boot protocol interface
kprint!/kprintln!logging macros- Kernel panic handler
- Framebuffer text console — 8×16 bitmap font, scrolling
- Kernel entry point — 5-phase boot
- Makefile build system
- Boots in QEMU with UEFI
Sprint 2 — Memory Management ✅ #
Teach the kernel to manage physical and virtual memory.
- Physical Memory Manager — bitmap allocator (alloc, free, zeroed, contiguous)
- VMM page table infrastructure (map, unmap, translate)
- Kernel Heap — linked-list allocator with coalescing, enables
alloccrate - Linker script fix —
.gotsection handling - Kernel higher-half remap (completed in Sprint 3)
- W^X enforcement via remap (completed in Sprint 3)
Sprint 3 — Interrupts & Exceptions ✅ #
Handle CPU exceptions and hardware interrupts safely.
- GDT — kernel/user segments, TSS with IST1 guard page, SYSRET layout
- IDT — 15 exception handlers + 16 IRQ stubs + spurious @255 (swapgs + SysV ABI)
- ACPI — XSDT-first MADT parser, Limine rev3 HHDM gap fix
- LAPIC — CPUID 0x15 + PIT calibration, one-shot mode, spurious handler
- I/O APIC — MADT parsing, IRQ routing, legacy PIC disable
- W^X remap — in-place page table update (.text=R+X, .rodata=R, .data/.bss=R+W+NX)
Sprint 4 — Processes & Scheduler ✅ #
Run multiple threads of execution, share the CPU fairly.
- Process / Thread structures — Process owns PML4 + CNode, Thread is schedulable unit (states: Ready/Running/Blocked/Dead)
- Context switching — register save/restore trampoline, RSP swap, lazy FPU state
- Preemptive scheduler — LAPIC timer 10ms quantum, per-core run queues, idle threads with HLT
- SMP initialization — INIT/SIPI, per-core GDT/IDT/TSS/LAPIC, 4-core parallel boot
- Per-CPU data — CpuLocal via GS segment, per-core current_thread tracking
Sprint 5 — Capabilities & IPC ✅ #
The security model — unforgeable tokens and message passing.
- CNode (Capability Node) — per-process table with 64 slots, typed capabilities with CapRights bitmask
- Capability types — PmmAllocator, MemoryFrame, IoPort, Process, IpcEndpoint, IrqLine, Empty
- Synchronous IPC — SYS_SEND/SYS_RECV on capability-protected endpoints, 3-word payload
- Interrupt routing — SYS_WAIT_IRQ blocks on IRQ capability, I/O APIC EOI
- Rights enforcement — all syscalls validate capability rights before operation
Sprint 6 — Syscall Interface & Userspace ✅ #
Cross the Ring 0/Ring 3 boundary.
- SYSCALL/SYSRET — MSR configuration (STAR/LSTAR/SFMASK), naked entry point with swapgs + kernel stack swap
- Syscall dispatch — 12 implemented syscalls: SYS_EXIT, SEND, RECV, PORT_OUT, PORT_IN, WAIT_IRQ, SPAWN_PROCESS, ALLOC_MEMORY, MAP_MEMORY, DELEGATE, SPAWN_THREAD, DROP_CAP
- ELF loader — parse ELF64, map PT_LOAD segments with W^X permissions, BSS zeroing
- Ring 3 entry — IRETQ transition from kernel thread to user code at 0x400000
Sprint 7–9 — Init Process & The God Process ✅ #
Life outside the kernel — the Init process holds absolute power.
- Init process (PID 1) — isolated PML4, CNode with PmmAllocator + IoPort + Process(self) capabilities
- Userspace library (
libmnos) — syscall wrappers (IPC, I/O, IRQ, process/memory management), Ring 3 heap bootstrap - Serial driver (
serial_drv) — userspace ELF loaded from initrd TarFS, COM1 via IoPort capability - Initrd TarFS — USTAR tar archive loaded by Limine, mapped into Init’s address space at 0x1000_0000
- Delegation syscalls — SYS_SPAWN_PROCESS, SYS_DELEGATE, SYS_SPAWN_THREAD (Sprint 8)
- Memory management from Ring 3 — SYS_ALLOC_MEMORY + SYS_MAP_MEMORY proven with write+readback (Sprint 9)
Sprint 9.5 — Reaper & Resource Teardown ✅ #
What is created must be destroyed — the kernel recycles its own entropy.
- DEAD_QUEUE — lock-free queue for dead threads, schedule() pushes dead Box<Thread> to reaper
- Reaper daemon — kernel thread that drains DEAD_QUEUE on each scheduler tick
- Kernel stack reclamation — HHDM → phys conversion, free_frame() per page (+4 frames proven)
- VMM PML4 walker — destroy_user_address_space() walks PML4[0..256] bottom-up, frees all user pages + table pages
- Process teardown — unregister_process() removes from PROCESS_TABLE, drops Process Box + CNode
- SYS_DROP_CAP (syscall 11) — removes capability from CNode slot, enabling slot reuse
Sprint 10 — Wasm Hypervisor ✅ #
Turn Init into the WebAssembly hypervisor — SFI Hardware Bridge proven.
- Ring 3 global allocator — linked_list_allocator in libmnos, fed by capability-gated page allocation
- init_heap() bootstrap — 1000 pages (4 MiB) at 0x4000_0000 via SYS_ALLOC_MEMORY + SYS_MAP_MEMORY + SYS_DROP_CAP loop
- Vec in Ring 3 — Vec<u64> constructed, grown (reallocation), and dropped in pure userspace
- wasmi integration — wasmi v0.31.2 WebAssembly interpreter running in Ring 3 (no_std + alloc)
- Wasm module loading — hello_wasm.wasm (549 bytes) extracted from initrd TarFS, parsed by wasmi Module::new()
- Wasm execution proof — Wasm
add(10, 32)returned42via wasmi in Ring 3 (Phase 2) - User stack expansion — 64 pages (256 KiB) for wasmi's recursive parser, stack-overflow-free
- Host function bridge —
host_print(ptr, len)registered viaLinker::func_wrap(), reads Wasm linear memory (Phase 3) - SFI hardware bridge — Wasm
run_guest()→host_print→Memory::read→SYS_PORT_OUT→ COM1 hardware (Phase 3) - “Hello from the Wasm Sandbox!” — printed from inside Wasm through the full capability chain (Phase 3)
Sprint 11 — PCI & Device Discovery 🔧 #
The Hardware Census — teach the kernel to see every device on the PCI bus.
- PCI Configuration Space driver — legacy Port I/O (0xCF8/0xCFC),
read_config_32(bus, device, func, offset) - Bus enumeration — brute-force scan 256 buses × 32 devices, multi-function detection via Header Type bit 7
- Device logging — BDF address, Vendor/Device ID, Class/Subclass/ProgIF with human-readable names
- Virtio-blk detection — Vendor 0x1AF4, Device 0x1001 confirmed on QEMU with
-drive if=virtio - Full QEMU topology proven — 7 devices: Host Bridge, ISA Bridge, IDE, ACPI Bridge, VGA, Ethernet, Virtio Block
- BAR parsing —
write_config_32+read_bar: decode MMIO vs I/O, 32-bit vs 64-bit, size probing via all-ones write - Virtio BAR 0 — I/O port 0xC000, 128 bytes (legacy virtio control registers)
- Virtio BAR 1 — MMIO at 0x81060000, 4096 bytes (device-specific configuration)
- Virtio BAR 4 — MMIO at 0xC000000000, 16384 bytes prefetchable (modern virtio / MSI-X)
- Width-extended PORT_IN/PORT_OUT — R10 width parameter (0/1=byte, 4=dword), backward compatible with all existing 8-bit callers
- Dynamic IoPort capability minting — kernel discovers Virtio BAR 0 via PCI, mints IoPort(0xC000, 128) into Init’s CNode Slot 4 at boot
- Ring 3 Virtio-Blk interrogation — Init reads device features (0x79007E54) and disk capacity (2048 sectors / 1 MB) via 32-bit port I/O
- libmnos 32-bit I/O —
sys_port_in_32()/sys_port_out_32()wrappers passing R10=4 for dword width - PCI capability list walking — MSI/MSI-X detection for interrupt-driven I/O
- Capability-gated MMIO — new CapType::MmioRegion for userspace device drivers
- Virtio-blk driver — block read/write through virtqueues, Ring 3 driver process
Future Milestones #
These features are planned for after Sprint 7 completes the core OS:
| Milestone | Description |
|---|---|
| VFS Service | Virtual filesystem abstraction in userspace |
| Initramfs | In-memory tar filesystem for boot-time binaries |
| Disk Driver | AHCI/NVMe driver in userspace |
| Filesystem | ext2 or FAT32 implementation as userspace service |
| Networking | TCP/IP stack as a userspace service |
| Shell | Basic interactive command-line shell |
| USB HID | Keyboard and mouse drivers |
| GPU Driver | Intel HD 405 framebuffer driver |
| Compositor | Window manager / display server |
| Rust std Port | Port Rust's standard library to MinimalOS |
| Self-hosting | Compile MinimalOS on MinimalOS |
Contributing #
Contributions are welcome! The project is structured around sprints — each sprint focuses on a self-contained subsystem.
How to Contribute
- Check the current sprint's open items above
- Read the relevant subsystem documentation
- Fork the repository and create a feature branch
- Implement your changes with tests where applicable
- Submit a pull request
Development Guidelines
- Rust edition 2024 with
no_std— no standard library - No unsafe without justification — document why each
unsafeblock is sound - Comments explain WHY, not what — assume the reader knows Rust
- One commit per logical change — granular, descriptive commit messages
- Test in QEMU —
make runbefore submitting