Reference port · pure Rust · no_std

It boots.

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.

2architectures · arm64 + x86-64
0third-party crates · kernel TCB ends at rustc
42syscalls on the wire · ceiling is 50
93host unit tests green
Why Rust

The named fallback, building the real thing.

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 typestate

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 implicit allocator

#![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.

Auditable TCB

Zero [dependencies] in the kernel crates. The trusted computing base ends at the rustc binary. Nothing the team has not read line by line.

Host-testable cores

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.

The workspace

A four-crate kernel. A userland that grew up.

CrateRoleTested
vectra-firmware-parsePure-Rust FDT / ACPI / PVH parsers — host-testable boot topology discovery26 tests
vectra-reticleThe memory model: Reticles, carve, bump allocator, page-table encoders, capability types50 tests
vectra-kernelThe kernel binary — #![no_std], dual-arch, depends only on the two crates aboveQEMU smoke
libvectra + servicesSyscall library and real Rust ELF Tasks: init/initd, topod, namingd, vfsd, a virtio-blk driver, a shellruns in-image
libposix + libc + std-palA C standard library + libm, a Rust std platform layer (threads, fs, io), and the POSIX shim — validated by real Lua 5.4QEMU smoke
vectra-fat32 + the ZFS portA native FAT32 reader, and a vendored OpenZFS built against the freestanding libc — a real pool on a virtio-blk disk17 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.

The milestone map

Stages 0–6, then a whole userland.

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.

StageWhat landedState
0 · Boot + UARTEL2→EL1 drop / PVH stub, high-half kernel mapping, PL011 & NS16550 serialdone
1 · TopologyFDT walker (arm64) and PVH memmap + ACPI/MADT/SRAT scan (x86) — memory regions, harts, NUMAdone
2 · Paging + ReticleTrap vectors, 4-level paging, the Reticle subsystem: typed memory, boot carve, bump allocatordone
3 · First user TaskDrop to user mode on both arches; first syscalls — console_write, task_exitdone
4 · Multi-task + capsPer-Task capability table, context switch, Task descriptors, SPSC Ring, cooperative scheduler, Bundlesdone
5 · Async events + SMPSignal masks, in-kernel ELF loader, monotonic timer, IRQ controllers, ChaCha20 CSPRNG, TLS, semaphores, surfaces, secondary-hart bring-up + IPIdone
6a–6c · Real userlandGenuine Rust ELFs (init/worker/topod), reply rings + doorbells, blocking signal-wait, a long-lived cooperative service loop, a 6-band priority latticedone
6c++ · Spec-canonicalRing-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 faultsdone
6d · Blocking IPCBlock-on-empty ring_recv and below-target sem_wait — fully restartable: a woken Task re-runs and completes its syscalldone
6e · Preemptive SMPPer-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 boundarydone
6f · FP / SIMDFirst-class floating-point & vector state — kernel-capable, frame-carried vector context preserved across traps and preemption, both archesdone

Above the kernel, four userland arcs — each landed on both arches, each its own UART marker:

ArcWhat landedState
ThreadsKernel 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 shootdowndone
A C standard libraryA broad freestanding libc + libm (a FreeBSD msun subset) + setjmp, over the syscall layer — validated by a real Lua 5.4 interpreter running on the metaldone
Rust std on the metalA std platform layer: std::thread, std::fs, std::io, process entry — real Rust std programs boot and run as Tasksdone
Storage + OpenZFSA 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 vfsddone
The wire

The syscall surface.

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
Honest accounting

What's real. What's deferred.

RUNNING TODAY
  • All six primitives, on both arches
  • Capability tables, narrowing, per-syscall validation
  • SPSC Rings — userland fast-path, blocking recv, cap-passing, burst
  • Preemptive per-hart SMP: runqueues + work-stealing + timer round-robin
  • Kernel threads + futex; a C pthread library and Rust std::thread
  • FP / SIMD preserved across traps and preemption
  • In-kernel ELF loader; userland-driven spawn; initd supervision
  • A C libc + libm + Rust std — a real Lua 5.4 runs
  • A virtio-blk disk, the vfsd router, and a ported OpenZFS filesystem
  • Contained user-mode faults — a fault kills a Task, not a hart
DEFERRED — AND NAMED
  • A reboot-surviving ZFS pool — export/import on shutdown/boot next
  • Reclaiming a detached thread's stack for an indefinitely-running service
  • Typed uncacheable LAPIC mapping on real hardware
  • Software page-table walk to return BadAddress cleanly
  • Ring free path + binding eviction
  • Hardware-entropy seeding (today: boot-jitter ChaCha20)

No 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.