No whitepaper hand-waving. The Rust port is a real capability-secure microkernel that
brings up a genuine userland on QEMU for both aarch64 and x86_64 — with
zero third-party crates anywhere in the kernel. It now runs preemptive per-hart SMP, kernel threads,
a C standard library, Rust std, and a ported OpenZFS filesystem on a real
disk. Here is the honest state of it.
The canonical spec is language-neutral; the project's eventual reference language is a purpose-built systems language. Rust is the spec's named fallback — and the closest off-the-shelf match for what VectraOS demands. This port proves the architecture in a language that exists today, that you can hire for, and that you can debug.
Capability classes become newtypes; move semantics give use-after-revoke a fighting chance at compile time. The kernel boundary still enforces type and rights — the language just makes the mistakes louder.
#![no_std] plus explicit allocation maps directly onto the no-kernel-heap discipline. Memory comes from a Reticle the Task already owns — never from a hidden global.
Zero [dependencies] in the kernel crates. The trusted computing base ends at the rustc binary. Nothing the team has not read line by line.
The firmware parsers and the Reticle memory model are ordinary library crates with real unit tests — 93 of them — runnable on your laptop, no QEMU required.
| Crate | Role | Tested |
|---|---|---|
| vectra-firmware-parse | Pure-Rust FDT / ACPI / PVH parsers — host-testable boot topology discovery | 26 tests |
| vectra-reticle | The memory model: Reticles, carve, bump allocator, page-table encoders, capability types | 50 tests |
| vectra-kernel | The kernel binary — #![no_std], dual-arch, depends only on the two crates above | QEMU smoke |
| libvectra + services | Syscall library and real Rust ELF Tasks: init/initd, topod, namingd, vfsd, a virtio-blk driver, a shell | runs in-image |
| libposix + libc + std-pal | A C standard library + libm, a Rust std platform layer (threads, fs, io), and the POSIX shim — validated by real Lua 5.4 | QEMU smoke |
| vectra-fat32 + the ZFS port | A native FAT32 reader, and a vendored OpenZFS built against the freestanding libc — a real pool on a virtio-blk disk | 17 tests + QEMU |
The four kernel-adjacent crates carry zero third-party
dependencies — the TCB ends at rustc. Above them the userland has grown a C/Rust
standard library and a ported filesystem, the OpenZFS sources held at the file boundary under their own
licence. Builds to a raw arm64 Image for QEMU -M virt and a PVH-bootable ELF for
QEMU -M q35; make qemu-* boots and greps the UART transcript for stage markers;
make test runs the host tests.
Every stage lands on aarch64 and x86_64 together, verified by a UART marker grep in QEMU. The kernel stages came first; the userland arcs below them are built on the same six primitives.
| Stage | What landed | State |
|---|---|---|
| 0 · Boot + UART | EL2→EL1 drop / PVH stub, high-half kernel mapping, PL011 & NS16550 serial | done |
| 1 · Topology | FDT walker (arm64) and PVH memmap + ACPI/MADT/SRAT scan (x86) — memory regions, harts, NUMA | done |
| 2 · Paging + Reticle | Trap vectors, 4-level paging, the Reticle subsystem: typed memory, boot carve, bump allocator | done |
| 3 · First user Task | Drop to user mode on both arches; first syscalls — console_write, task_exit | done |
| 4 · Multi-task + caps | Per-Task capability table, context switch, Task descriptors, SPSC Ring, cooperative scheduler, Bundles | done |
| 5 · Async events + SMP | Signal masks, in-kernel ELF loader, monotonic timer, IRQ controllers, ChaCha20 CSPRNG, TLS, semaphores, surfaces, secondary-hart bring-up + IPI | done |
| 6a–6c · Real userland | Genuine Rust ELFs (init/worker/topod), reply rings + doorbells, blocking signal-wait, a long-lived cooperative service loop, a 6-band priority lattice | done |
| 6c++ · Spec-canonical | Ring-signal doorbells, a general spawn driven entirely by a Bundle spec, priority delivered as a Bundle value slot, user-pointer / ELF-bounds hardening, contained user-mode faults | done |
| 6d · Blocking IPC | Block-on-empty ring_recv and below-target sem_wait — fully restartable: a woken Task re-runs and completes its syscall | done |
| 6e · Preemptive SMP | Per-hart runqueues + work-stealing within a coherence domain; timer-driven round-robin preemption; cross-hart preempt IPI — Tasks run on every hart, preempted at a safe boundary | done |
| 6f · FP / SIMD | First-class floating-point & vector state — kernel-capable, frame-carried vector context preserved across traps and preemption, both arches | done |
Above the kernel, four userland arcs — each landed on both arches, each its own UART marker:
| Arc | What landed | State |
|---|---|---|
| Threads | Kernel thread_create/exit/join over a shared address space + a futex pair; a C pthread library, then Rust std::thread / Mutex / Condvar / real TLS; cross-hart TLB shootdown | done |
| A C standard library | A broad freestanding libc + libm (a FreeBSD msun subset) + setjmp, over the syscall layer — validated by a real Lua 5.4 interpreter running on the metal | done |
| Rust std on the metal | A std platform layer: std::thread, std::fs, std::io, process entry — real Rust std programs boot and run as Tasks | done |
| Storage + OpenZFS | A virtio-blk driver + BLOCK_V1, the vfsd router + FS_BACKEND_V1, a native FAT32 backend — and a ported OpenZFS: a real pool on a virtio-blk disk (create / import / export, datasets, ZAP, DMU data) served as a POSIX filesystem behind vfsd | done |
Forty-two operations, grouped by primitive — still well under the spec's ceiling of fifty. Errors come back as a small SyscallError enum encoded into the return register. The threads, futex, memory, and cap-passing-Ring calls are what the libc, Rust std, and OpenZFS arcs needed.
// console + lifecycle SYS_CONSOLE_WRITE 0 SYS_TASK_EXIT 1 SYS_GETPID 28 SYS_WAITPID 29 SYS_DESTROY 38 // tear a child Task down // capability table SYS_CAP_INSPECT 2 SYS_CAP_DROP 3 // rings — SPSC, cap-passing, burst SYS_RING_CREATE 5 SYS_RING_SEND 6 SYS_RING_RECV 7 SYS_RING_TRY_RECV 24 SYS_RING_MAP 13 SYS_BIND 20 // consumer → signal bit SYS_RING_SEND_CAP 30 SYS_RING_RECV_CAP 31 SYS_RING_TRY_RECV_CAP 32 SYS_RING_SEND_BURST 33 SYS_RING_RECV_BURST 34 // scheduling + signal mask (the doorbell) SYS_YIELD 8 SYS_SIGNAL_POST 9 SYS_SIGNAL_WAIT 10 // threads (shared address space) + futex SYS_THREAD_CREATE 39 SYS_THREAD_EXIT 40 SYS_THREAD_JOIN 41 SYS_FUTEX_WAIT 42 SYS_FUTEX_WAKE 43 // per-task state · time · memory SYS_SET_TLS 11 SYS_GET_TLS 44 SYS_CLOCK_GET_TIME 25 SYS_NANOSLEEP 26 SYS_MEM_ALLOC 27 SYS_MEM_FREE 37 // devices · DMA · entropy SYS_DEVICE_BIND_IRQ 12 SYS_DEVICE_MAP_MMIO 22 SYS_DMA_ALLOC 23 SYS_GETRANDOM 36 SYS_FP_CLOBBER 35 // test: clobber vec regs // semaphores + surfaces SYS_SEM_CREATE 15 SYS_SEM_SIGNAL 16 SYS_SEM_WAIT 17 SYS_SURFACE_CREATE 18 // the general spawn — image cap + Bundle spec, nothing else SYS_SPAWN 21
std::threadspawn; initd supervisionstd — a real Lua 5.4 runsvfsd router, and a ported OpenZFS filesystemBadAddress cleanlyNo silent caps. The Task table is a fixed 256 entries; capability tables are eight pages (512 entries); Rings default to 16 slots. These are spec-stage limits, written down, not pretended away.