Skip to content

Kernel Protocol

Contract

The kernel boundary is a protocol, not a function call. The CPU-facing trap ABI is a tiny implementation detail; the contract that applications actually depend on is a stable message protocol built on ION Rings and signed BKDL descriptors.

The ABI is an implementation detail. The protocol is the contract.

Three Layers, Not One

Most operating systems conflate three very different things under the word "syscall." Nexus separates them deliberately.

LayerWhat it isWho cares about itStability
Trap ABIRegisters, trap instruction, entry trampolineThe compiler backend and libnexusArchitectural; can change per CPU family
Kernel ProtocolTyped ION Ring packets + BKDL descriptor schemas + capability verbsApplication authors, language binding authorsThe frozen contract
Language BindingsIdiomatic surfaces in Janus, Nim, C, Zig, etc.Application authors in a specific languagePer-language; idiomatic, versioned independently

Conflating these into a single "syscall ABI" is what forces every OS that took that path to ship a new /usr/include/unistd.h per architecture and to tie application compatibility to a specific compiler's calling convention. Nexus rejects that coupling.

Why a Protocol

A function call has to choose a calling convention before it can exist. A protocol only has to choose a byte layout. Once the kernel boundary is messages rather than calls, several things become trivial that were previously impossible:

  • Languages become transport adapters. Janus, Nim, C, Zig, and anything with a C FFI speak the same wire contract. No language is privileged.
  • Versioning is additive. New packet types do not invalidate old packet types. There is no syscall_64.tbl to renumber.
  • Local and remote unify. The same protocol runs between a fiber and the kernel on the same core, between fibers on different cores, and between cells across the hypervisor boundary. The transport changes; the contract does not.
  • Capabilities, not integer descriptors. Handles are typed, scoped, and revocable. There is no global int fd table to attack.
  • Transactional operations. Multi-step kernel interactions are submitted as single descriptor blobs (BKDL), validated atomically, and either complete or fail without partial state.

This is the same evolutionary step that filesystems took when they moved from "read sector 1234" to higher-level protocols: once the boundary is a protocol, it scales far beyond a single process on a single machine.

The Protocol Surface

The Kernel Protocol is the union of four contracts. Each is documented in detail under its own page or spec family; this section indexes them.

1. ION Rings — the pipe

ION Rings are lock-free single-producer/single-consumer ring buffers in shared memory. They are the sole inter-process communication mechanism in Nexus. Every kernel interaction — every byte of stdin, every network frame, every storage request — flows through an ION Ring.

  • Producer writes a slot and advances an index. Consumer reads and advances. No locks. No CAS. No contention.
  • Once a ring is mapped into a fiber's address space, the kernel is not on the hot path. The kernel delivers the mail; it does not read the letter.

ION v2 (Generation 2, ratified by K9 — Lessons from io_uring) is the active wire contract. v2 carries typed object operations — not POSIX opcodes — on a small closed interaction layer of five protocol verbs riding on the seven capability verbs:

Interaction (5, closed)Authority used (7, closed)Completes
SUBMITSEND on TX Channel capone (or none for fire-and-forget)
CANCELSEND on TX Channel capone ack
SUBSCRIBESEND + RECV (paired)many (multishot stream)
REPLYSEND on reply Channel capone
TRANSFERGRANT on the moved capone ack

Every SUBMIT returns a Ticket(u64); wait_multi blocks on tickets. Semantic operations (OpenObject, PublishEvent, CommitTransaction, MirrorDomain, …) are typed payload families gated by capability class — they extend the protocol additively without adding entry points. This is what makes the io_uring exploit class (open opcode table = privileged entry points) structurally impossible in Nexus. Multishot subscriptions, registered (capability-backed) buffers, and atomic transactions are first-class. See SPEC-022B for the wire format and the full verb/payload contract.

2. Packet Schemas — the typed messages

Rings carry typed packets, not byte streams. Each packet type has an explicit schema (KDL-encoded in source, binary-canonical on the wire). Examples already in flight:

  • IonPacket — generic event/data envelope (IonPacket on every well-known channel: console, telemetry, STDIN, SSP transport)
  • CmdPacket — command channel for control-plane operations
  • TextureRef — display surface handoff from NipCell guests to the compositor
  • Registry query / responseCMD_REG_QUERY, CMD_REG_UPDATE, KDL-encoded result sets
  • BLK_REQ / BLK_RESP — Block Valve storage request/response

New packet types are added by spec amendment. Old packet types are never removed; they are deprecated, then ignored, but the wire format stays parseable.

3. BKDL — signed descriptors for spawn and load

The Binary signed descriptor (BKDL) is the universal kernel-adjacent signed descriptor format. Every artifact the kernel validates and loads — application manifests, driver descriptors, package descriptors, cell templates, boot artifacts, checkpoints — is a BKDL.

Key properties:

  • Two-tier header. Tier 1 is a universal 144-byte signed head parsed by the kernel for any kind. Tier 2 is kind-specific and dispatched to the appropriate loader.
  • Ed25519 signature over the body; BLAKE3-256 for every content hash.
  • No parsing in ring 0. The kernel never reads text. Source manifests are KDL; the Forge compiles them to signed binary before they reach the kernel.
  • manifest_kind dispatch. App, Driver-Native, Driver-Mimic, NipPackage, Cell, Boot, Checkpoint, Skill — each routes to its own tier-2 parser.

The result is that spawn, load_driver, install_package, and boot_generation all share one verification path. The kernel does not have one parser per artifact type.

4. Capability Verbs — the authority algebra

Authority is not a syscall argument. It is a separate, orthogonal surface. Every effectful operation reduces to a small verb algebra operating over typed capability handles:

VerbMeaning
SPAWNCreate a new fiber from a signed descriptor
SENDPush a packet onto a TX channel
RECVPop a packet from an RX channel
MAPBind a memory or device region into a cell
MASKNarrow the pledge mask (irreversible)
TICKYield to the scheduler
GRANTDelegate a capability to another fiber

Capabilities are bundles (see Capability Algebra). A capability bundle is itself a BKDL-tier-2 structure, so it is validated atomically at spawn time. There is no partial CSpace population: either every cap in the bundle resolves from the parent's CSpace, or spawn fails.

What Happened to Syscalls

The CPU still needs an entry path. RISC-V uses ecall, ARM64 uses svc #0, x86_64 uses syscall. That will never go away; it is physics.

The Trap ABI page (Trap ABI Reference) documents that lowest layer: the register conventions, the small dispatch table, and the per-arch entry code. It exists so that libnexus and language runtimes know how to perform the four mechanical operations the protocol needs:

  • submit(packet_ptr, len) — push a packet to a TX ring
  • await(reply_ptr, cap) — pop from an RX ring, yielding if empty
  • invoke(cap_bundle, op, args) — invoke a capability verb
  • yield — surrender the remaining quantum

Everything above those four primitives is a message in the Kernel Protocol. Everything below them is architecture-specific glue. Nothing in between is a "syscall" in the POSIX sense.

Application Shape

A Nexus Native application is not a program with a main(argc, argv). It is a fiber that reacts to events. The contract is:

  1. The kernel spawns the fiber from a signed BKDL.
  2. The fiber receives a manifest_ptr carrying its configuration as a parsed KDL object — no environment variables, no argv.
  3. The manifest enumerates the channels the fiber may connect (console, network, storage, etc.). Each connection returns a typed Channel object backed by an ION Ring.
  4. The fiber enters a reactive loop: wait_multi([chan_a, chan_b, ...]), dispatch on event source and type, emit structured objects on its TX ring.
  5. The fiber never sees an int fd, never calls printf, never reads errno. Output is structured KDL objects; errors are Result<T, E> with typed codes.

Details live in the SDK page. The point here is that this is what the Kernel Protocol enables: an application model that is reactive, typed, and capability-bounded from the first instruction.

Compatibility Bridges

The protocol is the contract for Native applications. Legacy code does not have to be rewritten to run on Nexus; it runs behind one of two bridges, both of which translate to the Kernel Protocol internally.

BridgeDirectionForeign codeTax
Chimera (POSIX bridge)UpwardPOSIX userspace apps (recompile-friendly)Per-syscall translation, ~5–10× Native
NipCell Linux (Hypervisor-bound)DownwardFull Linux guests (Firefox, gcc, Chrome)ION Ring boundary only; POSIX-inside is free

Foreign Ring-0 drivers (NDIS, USBD) get a third bridge: the Mimic membrane wraps them in a NipCell, translates their kernel-ABI calls into capability-gated Native operations, and exposes them upward as native SignalForge nodes. Same membrane pattern, opposite arrow.

These bridges exist to inherit the world we have. They are not the contract.

What This Means for Language Choice

Because the kernel speaks one protocol and exposes one canonical C ABI (libnexus), every language with a C FFI can be a first-class Nexus client. There is no "blessed" language at the protocol layer.

The SDK tiering — what is preferred for what — is documented separately under SDK. The short version: Janus and Nim are Native NPL targets; C is the FFI surface; Zig is the HAL; Rust and C++ are bridge-only.

A Rust binary and a Janus binary speaking the same protocol through the same libnexus surface are indistinguishable from the kernel's point of view. That is the entire point.

References