How it is put together
Architecture
Authority flows strictly downward from a root supervisor and never upward. The kernel holds no policy — it answers "here is a capability, perform the operation it denotes", never "may this component do X".
Source of record: ARCHITECTURE.md in the Bivdi repository.
The layers#
┌────────────────────────────────────────────────────────────────────────┐
│ Applications │
│ native (WASI) · Linux ABI · micro-VM (legacy / Windows) │
├────────────────────────────────────────────────────────────────────────┤
│ System services (unprivileged · restartable · capability-confined) │
│ object store capability runtime state engine event bus │
│ identity agent host network storage provenance packaging │
│ component supervisor compositor (later) │
├────────────────────────────────────────────────────────────────────────┤
│ Capability boundary (kernel capabilities <-> durable tokens) │
├────────────────────────────────────────────────────────────────────────┤
│ Drivers (one isolation domain each · IOMMU-confined) │
│ virtio-* · nvme · ahci · xhci · net · gpu · rtc · tpm · hda │
├────────────────────────────────────────────────────────────────────────┤
│ Linux kernel (today — the Runtime is the product) │
│ a microkernel is parked research, not a dependency │
├────────────────────────────────────────────────────────────────────────┤
│ Hardware or VM (anywhere Linux runs) │
└────────────────────────────────────────────────────────────────────────┘Components are referred to by generic, descriptive terms — "object store", "capability runtime", "state engine", "event bus", "identity service", "agent host". No codenames or daemon-style abbreviations appear anywhere until a naming decision is recorded. Self-documenting names are a feature, not a placeholder.
The kernel#
The kernel does only what requires the highest privilege: scheduling, virtual address spaces, inter-process communication, capability enforcement, interrupt delivery, and virtualisation support for driver VMs and micro-VMs.
It contains no device drivers, no filesystem, no network stack, and it never parses a string. Physical memory is distributed as untyped memory at boot; after boot the kernel allocates nothing, which removes an entire class of exhaustion and use-after-free defects.
The kernel choice is deferred indefinitely, and the diagram above describes the parked track. The Runtime is the product and runs on Linux today; the capability boundary is enforced in the Runtime, with seccomp and Landlock hardening the process around it. seL4 remains the leading proposal if the research track is ever reactivated — it carries machine-checked proofs, though their coverage varies by architecture and none of them covers device address translation. The interface contract forbids kernel concepts, so the option stays open without gating anything.
Interfaces and the ABI#
All inter-component communication uses typed protocols defined in a language-neutral interface definition language. Bindings are generated for Rust, C, C++, Go, Swift and WASI components rather than hand-written.
The wire format is the contract, not a language calling convention.
Two consequences follow. The interface stays stable across language updates and across both implementation tracks. And Rust's lack of a stable ABI becomes irrelevant: Rust is a language for implementing components, never a binding target others must call into.
A conforming interface must be able to express objects, capabilities, typed calls, events, bounded and backpressured streams, explicit cancellation, transactions, structured errors, and deadlines and priorities.
- Asynchronous by default, with a fast synchronous path for short local operations where latency matters.
- Large data moves by ownership transfer. A buffer is passed as a capability and the sender loses access in the same instant — move semantics across a trust boundary. Shared, simultaneously mutable memory across trust boundaries is not allowed, with one exception: explicitly agreed ring buffers between a driver and its service.
Which IDL, and its encoding, is an open question. The requirements above are decided; the choice is not.
Scheduling and resources#
Every workload and request carries explicit budgets: memory, CPU time, energy, latency class, and I/O bandwidth. There are no unbounded queues.
CPU time is itself a capability. A scheduling context — budget, period, criticality — is granted like any other authority. Admission control at bind time rejects oversubscription, so a reservation is guaranteed rather than hoped for. A donate operation lets a client lend its reservation to a server for the duration of a call, so the server's work is accounted to the requester rather than to the server.
CPU, GPU, NPU and crypto accelerators are peers in the resource model. In practice accelerators carry their own, often closed, firmware and driver stacks, so initially they are exposed as capabilities from their driver domains with a per-device budget.
Drivers and hardware#
Every driver is an ordinary unprivileged, restartable component. The kernel contains no drivers at all.
A driver receives MMIO regions, an interrupt handler, an IOMMU domain restricted to its explicitly registered DMA buffers, and a scheduling context sized for its latency requirement. It receives no ability to touch memory outside that domain — which is why a compromised GPU driver is a graphics outage rather than a root compromise.
The strategy is layered:
- Native drivers for standardised device classes — virtio, NVMe, AHCI, xHCI, a few NIC families — small, well documented, written in Rust.
- Driver VMs for everything else. GPU and Wi-Fi driver stacks are enormous and Linux-specific; a deprivileged Linux VM behind an IOMMU, exposed through virtio, is the pragmatic answer.
- Native drivers take over gradually, one device class at a time.
Hardware tiers#
| Tier | Scope | Status |
|---|---|---|
| 1 — Virtualised | KVM/QEMU, VirtualBox, VMware, Firecracker, Proxmox, AWS, GCP, Azure | First target |
| 2 — Reference servers | One or two chosen x86-64 and ARM server platforms | Second target |
| 3 — Reference laptop | One chosen laptop | Later phase |
| 4 — Arbitrary hardware | Through a driver VM, where an IOMMU exists | Best effort |
| — No IOMMU | — | Never supported |
Driver support is historically where new operating systems die. Starting in virtual machines gives a short, well-understood driver list, an instantly available development target, and defers every one of the hardest desktop-hardware problems: GPU, Wi-Fi and suspend.
Networking#
- Identity-based. Applications request a service by identity and capability, not by IP address and port. The operating system resolves identity to location and transport.
- Flow capabilities, not raw sockets. A component receives "you may connect to this endpoint with this trust anchor". There is no ambient namespace in which to
bind(0.0.0.0), and listening requires a listener capability naming a specific interface and port. - Encryption by default, with mutual authentication, and no way to disable it for external connections.
- DNS is a capability decision. Name resolution and connection authority are one decision rather than two, which closes DNS rebinding.
- Uniform, but never hidden. The same API and capability model apply locally and remotely — and latency, timeouts and partial failure are explicit in the types. The network is never disguised as local.
- Offline-first. Devices are replicas and caches; disconnected operation is normal. CRDTs are used where they are meaningful, with explicit conflict resolution where they are not.
- Clusters are explicit. Several machines can form a configured cluster for workload and object placement. Never an illusion of one giant machine.
Compatibility#
| Level | Mechanism | Compatibility | Integration |
|---|---|---|---|
| Native | WASI components and native programs | New software | Full — capabilities, objects, events |
| Linux ABI | User-space syscall translation | High for CLI and server software | Sees objects as files, bounded by its capabilities |
| Micro-VM | An isolated Linux or Windows kernel | Very high | Through virtio and proxies |
| Recompile | A POSIX library | Source-available software | Medium |
Each Linux process's filesystem view is a catalog it was handed: / is its root and nothing more. open("/etc/passwd") succeeds only if the granted catalog contains that entry.
The cannibalisation risk is acknowledged. A compatibility layer that is too good prevents a native ecosystem from forming — the OS/2 effect. The answers are cheap porting through WASI, native advantages that legacy software cannot get (capabilities, provenance, generations, cross-device sharing), and starting in greenfield areas where there is no incumbent software to run.
The boot chain#
[1] Platform firmware root of trust (UEFI SB / ARM TF-A / OpenSBI)
│ measures into TPM / measured-boot log
[2] bivdi-shim (signed) minimal, verifies the next stage
[3] bivdi-boot loads kernel + root supervisor + composition
[4] Kernel initialises, retypes memory, starts root supervisor
[5] Root supervisor instantiates the composition per manifest
[6] Steady state storage key unsealed against expected measurementsRemote attestation returns a signed quote plus the boot record, so a verifier can check exactly which components are running, by content hash.
Observability#
Observability is built in rather than installed afterwards: metrics per component and workload; structured logs as typed events; distributed tracing with causality preserved across IPC and the network; resource usage per budget and per capability; security events; and a dependency graph between components. Programmable, verified hooks are available for deeper analysis — always as capabilities.
Performance#
Performance is a first-class attribute. It is designed in, measured, and regression-gated in CI — and it is never won by weakening the security model. Isolation has an accepted, budgeted cost, and the goal is predictability within that budget rather than peak throughput at any price.
These are reference targets to be ratified in specification v0.1 and then turned into CI gates. The principle is decided; the numbers are proposed.
| Metric | Target |
|---|---|
| IPC round trip, same core, about 4 words | under 500 cycles |
| IPC round trip, cross-core | under 2,000 cycles |
| Interrupt to userspace driver thread | under 3 µs |
| Component instantiation, cold | under 2 ms |
| Driver restart after a fault | under 10 ms |
| Boot, firmware to login | under 400 ms |
| Kernel static memory | under 1 MiB |
| Minimum useful system — kernel, object store, shell | under 32 MiB RAM |
| Object store, sequential read | at least 85% of the raw device |
| Object store, 4K random IOPS | at least 70% of the raw device |
| Durable-token verification, 5 caveats | under 20 µs |
| Syscall-heavy workload versus a monolithic kernel | within 30% |
The last row frames the whole table. Bivdi accepts a measurable cost for isolation, and staying inside that budget is a hard requirement rather than an apology.
Recovery#
Recovery is declarative: "restore system generation 42", "restore user data snapshot X". Migration moves objects, identities, policies, workloads and desired state rather than requiring a machine to be rebuilt by hand.
There is no continuous machine-state persistence. Bivdi persists data and configuration, not running instruction-level state. A reboot yields clean execution state over consistent data — which is what makes "restart fixes it" true rather than folklore. Persisting instruction-level state would persist corruption along with it.