Strat9 OS

An experimental operating system kernel written in Rust, targeting x86_64 (primary) and aarch64 (secondary).


Quick start

Building from source

# Build the full OS image (bootloader + kernel)
cargo make build-all

# Run in QEMU
cargo make run-gui

# Run with SMP (multi-core)
cargo make run-gui-smp

Build guide · Source repository


Architecture guides

GuideDescription
Architecture OverviewKernel subsystems, design principles, and data flow diagrams
Silo SystemProcess isolation, resource limits, pledge/unveil, module loading
Memory ManagementBuddy allocator, slab heap, COW, page tables, vmalloc
Boot SequenceBIOS → bootloader → Limine → kernel init flow
IPC MechanismsChannels, shared rings, semaphores, futexes
IPC Transport Architecture3-level hybrid IPC model (TypeSafe / LockFree / MMU)
Driver ModelComponent trait, PCI, NIC, storage, USB drivers
Syscall ReferenceComplete syscall table with parameters and errors
ABI OverviewKernel/userspace ABI definitions and versioning
ABI ChangelogRecent ABI changes (auto-generated)
ABI Support MatrixSyscall and struct compatibility matrix
Syscall LayerUserspace syscall wrappers and error handling
ChangelogProject changelog (auto-generated from git)
PublishingBuild, release, and deployment instructions

API reference by category

Core

The kernel, ABI definitions, and bootloader : the foundation of the OS.

CrateDescriptionAPI
strat9-kernelOS kernel: scheduler, memory management, drivers, IPCdocs · source
strat9-abiABI definitions shared between kernel and userspace (syscalls, data structs, flags, errno)docs · source
strat9-bootloaderBIOS/UEFI bootloader: stage1 MBR, stage2 protected/long mode switchdocs · source

Syscall & Userspace

Userspace libraries for interacting with the kernel.

CrateDescriptionAPI
strat9-syscallHigh-level syscall wrappers, error mapping, and constantsdocs · source
strate-initInit process: system bootstrap and service managementdocs · source

Component Framework

Trait-based component model for drivers and services.

CrateDescriptionAPI
componentComponent trait and registration frameworkdocs · source
component-macroDerive macros for component registrationdocs · source
strat9-bus-driversBus driver infrastructure (PCI, VirtIO)docs · source
strate-busBus abstraction layerdocs · source

Network Drivers

Intel Ethernet and NIC queue management.

CrateDescriptionAPI
e1000Intel E1000/E1000e network driverdocs · source
intel-ethernetIntel Ethernet common register definitionsdocs · source
driver-net-protoNetwork protocol driver abstractionsdocs · source
nic-queuesNIC TX/RX queue managementdocs · source
nic-buffersNIC buffer allocation and managementdocs · source
net-coreNetwork core utilitiesdocs · source

Filesystem

Filesystem abstraction and implementations.

CrateDescriptionAPI
strate-fs-abstractionFilesystem abstraction layer with safe math and Unicodedocs · source
strate-fs-ext4ext4 filesystem implementationdocs · source
strate-fs-ramfsIn-memory RAM filesystemdocs · source

Networking

Network stack, silo network service, and tools.

CrateDescriptionAPI
strate-netNetwork stack (TCP/UDP/ICMP)docs · source
strate-net-siloNetwork silo service (TCP/UDP listener)docs · source
dhcp-clientDHCP client status monitordocs · source
pingICMP ping utilitydocs · source
udp-toolUDP scheme test utilitydocs · source
telnetdTelnet serverdocs · source
ice-candidateICE candidate discovery over scheme UDPdocs · source

System Services

Admin interfaces, compatibility layers, and experimental features.

CrateDescriptionAPI
strat9-components-apiShared component API types and traitsdocs · source
strate-console-adminInteractive console shell with silo managementdocs · source
strate-web-adminWeb-based admin interfacedocs · source
strate-wasmWebAssembly runtime supportdocs · source
strate-webrtcWebRTC supportdocs · source
musl-compatmusl libc compatibility layerdocs · source
alloc-freelistFree-list allocatordocs · source

Testing

CrateDescriptionAPI
silo-testSilo integration testssource
mem-testMemory subsystem testsdocs · source
test-syscallsSyscall integration testsdocs · source
test-execExec syscall testsdocs · source

Building docs locally

# Build the full docs site (mdBook + rustdoc)
bash tools/scripts/build-docs-site.sh

# Serve locally
python3 -m http.server --directory build/docs-site 8000

# Check for broken links
python3 tools/scripts/check-links.py --site-dir build/docs-site

Architecture Overview

Strat9 OS is a microkernel-inspired operating system written in Rust. The kernel runs in Ring 0 on x86_64, with userspace processes isolated through capability-based security and silo boundaries.


Kernel subsystems

graph TB
    subgraph "Ring 0 : Kernel"
        BOOT[Boot / Init]
        SCHED[Scheduler]
        MEM[Memory Manager]
        IPC[IPC]
        CAP[Capability System]
        SILO[Silo Manager]
        VFS[VFS]
        SYSCALL[Syscall Entry]
        HW[Hardware Drivers]
    end

    subgraph "Ring 3 : Userspace"
        INIT[Init Process]
        APP[Applications]
        SVC[Services]
    end

    BOOT --> SCHED
    BOOT --> MEM
    SYSCALL --> SCHED
    SYSCALL --> MEM
    SYSCALL --> IPC
    SYSCALL --> CAP
    SYSCALL --> VFS
    SCHED --> MEM
    IPC --> MEM
    IPC --> CAP
    SILO --> CAP
    SILO --> MEM
    VFS --> MEM
    HW --> SYSCALL

    APP --> SYSCALL
    SVC --> SYSCALL
    INIT --> SYSCALL
    SILO -.-> APP
    SILO -.-> SVC

Subsystem summary

SubsystemModulePurpose
Bootboot/Assembly stubs (16→64 bit), Limine handoff, early init
Schedulerprocess/scheduler/Per-CPU run queues, multi-class scheduling (RT FIFO/RR, Normal, Idle)
Memorymemory/Buddy allocator, slab heap, COW, page tables, vmalloc
IPCipc/3-level Transport Manager (TypeSafe/LockFree/MMU), typed channels, shared rings, semaphores
Capabilitycapability.rsUnforgeable tokens, per-resource refcounting
Silosilo/Process isolation containers with resource quotas
VFSvfs/Virtual filesystem with scheme-based I/O
Syscallsyscall/Syscall dispatch and validation
Drivershardware/NIC, storage, USB, GPU, VirtIO, PCI

Design principles

  1. Capability-based security : All kernel resources (memory, IPC ports, devices) are accessed through unforgeable CapId tokens. No raw pointers leak to userspace.

  2. Silo isolation : Processes run inside silos (analogous to containers). Each silo has memory quotas, capability boundaries, and IPC restrictions. Policy lives in userspace; the kernel enforces mechanisms.

  3. Per-CPU scheduling : Each CPU core has its own run queue set. Tasks are pinned to cores via the scheduler, avoiding cross-core lock contention on the hot path.

  4. COW-first memory : fork() shares pages via copy-on-write. Physical frames are freed only when the last reference disappears. Buddy allocator provides O(1) order-0 allocations via per-CPU caches.

  5. Scheme-based I/O : Filesystem operations go through a VFS layer that routes to scheme handlers (like Plan 9). Userspace can implement custom schemes for devices, networks, and IPC.


Data flow: userspace syscall

sequenceDiagram
    participant U as Userspace
    participant K as Syscall Entry
    participant C as Capability Check
    participant S as Subsystem

    U->>K: syscall(SYS_READ, fd, buf, len)
    K->>K: Validate args, disable IRQs
    K->>C: Resolve CapId from fd
    C->>C: Check permissions (read)
    C->>S: Dispatch to VFS read
    S->>S: Page fault / buffer I/O
    S-->>K: Return bytes read
    K-->>U: Result in RAX

Silo System

Silos are Strat9 OS's primary isolation mechanism. Each silo is a container for processes with bounded resources, restricted capabilities, and filesystem access control. Policy lives in userspace; the kernel enforces mechanisms.


Overview

graph TB
    subgraph "Admin (Silo Admin)"
        ADMIN[Console Admin / Web Admin]
    end

    subgraph "Kernel"
        SM[Silo Manager]
        CAP[Capability System]
        MEM[Memory Accounting]
        EV[Event Queue]
    end

    subgraph "Silo 1 (System)"
        T1[Task A]
        T2[Task B]
    end

    subgraph "Silo 2 (User)"
        T3[Task C]
    end

    ADMIN -->|create/config/start/stop| SM
    SM --> CAP
    SM --> MEM
    SM --> EV
    T1 --> CAP
    T2 --> CAP
    T3 --> CAP
    T1 -.-> MEM
    T3 -.-> MEM

Silo identity

Each silo has a numeric ID (SiloId) and a tier derived from the ID range:

ID rangeTierPurpose
1–9CriticalKernel system services (init, logger)
10–999SystemDrivers, filesystems, network
1000+UserUser applications

User-tier silos cannot have hardware or control permissions (enforced at creation).


Silo lifecycle

stateDiagram-v2
    [*] --> Created : SYS_SILO_CREATE
    Created --> Ready : SYS_SILO_CONFIG + SYS_SILO_ATTACH_MODULE
    Ready --> Running : SYS_SILO_START
    Running --> Paused : SYS_SILO_SUSPEND
    Paused --> Running : SYS_SILO_RESUME
    Running --> Stopping : SYS_SILO_STOP (graceful)
    Stopping --> Stopped : tasks exit
    Running --> Stopped : SYS_SILO_KILL (force)
    Stopped --> [*] : SYS_SILO_DESTROY
    Running --> Crashed : fault / panic
    Crashed --> Stopped : cleanup

States: Created → Loading → Ready → Running → Paused → Stopping → Stopped → Destroyed (also Crashed, Zombie)


Resource limits

The SiloConfig struct defines per-silo resource bounds:

SiloConfig {
    mem_min: u64,           // Minimum guaranteed memory (bytes)
    mem_max: u64,           // Maximum allowed memory (0 = unlimited)
    cpu_shares: u32,        // CPU share weight (for proportional scheduling)
    cpu_quota_us: u64,      // CPU time quota per period (microseconds)
    cpu_period_us: u64,     // Quota period (microseconds)
    cpu_affinity_mask: u64, // CPU affinity bitmask
    max_tasks: u32,         // Maximum concurrent tasks
    io_bw_read: u64,        // Read bandwidth limit
    io_bw_write: u64,       // Write bandwidth limit
    flags: u64,             // Feature flags
    family: u8,             // Silo family (SYS/DRV/FS/NET/WASM/USR)
}

Memory accounting: Every allocation through the kernel heap charges against the silo's mem_usage_bytes. When mem_max is exceeded, charge_current_task_memory() returns OutOfMemory. This is enforced transparently in the buddy allocator and slab paths.


Octal mode (pledge/unveil)

Access control uses an OctalMode with three permission groups, encoded as a 12-bit octal value:

BitsGroupPermissions
8–10ControlLIST (0b100), STOP (0b010), SPAWN (0b001)
5–7HardwareINTERRUPT (0b100), IO (0b010), DMA (0b001)
2–4RegistryLOOKUP (0b100), BIND (0b010), PROXY (0b001)

Example: 0o755 = LIST+STOP+SPAWN + INTERRUPT+IO + LOOKUP+BIND

Pledge

SYS_SILO_PLEDGE(mode) restricts the silo's permissions. The new mode must be a subset of the current mode : escalation is rejected with PermissionDenied.

silo.mode.pledge(new_mode):
    if !new_mode.is_subset_of(self.mode):
        return PermissionDenied  // escalation attempt
    self.mode = new_mode

Unveil

SYS_SILO_UNVEIL(path, rights) restricts filesystem access to specific paths with read/write/execute permissions. Multiple rules can be added; if a path matches no rule, access is denied.

Rights bits: read (0x1), write (0x2), execute (0x4)

Matching: A rule /srv/data matches /srv/data/file.txt but not /srv/other. Rule / matches everything.

Enter Sandbox

SYS_SILO_ENTER_SANDBOX() is irreversible : it clears all registry permissions and prevents further capability grants. Once sandboxed, the silo cannot escape.


Family types

FamilyValuePurpose
SYS0System services (init, admin)
DRV1Hardware drivers
FS2Filesystem handlers
NET3Network stack
WASM4WebAssembly runtime
USR5User applications

Feature flags

FlagValueDescription
SILO_FLAG_ADMIN1 << 0Silo has admin capabilities
SILO_FLAG_GRAPHICS1 << 1Graphics session support
SILO_FLAG_WEBRTC_NATIVE1 << 2WebRTC native support (requires GRAPHICS)
SILO_FLAG_GRAPHICS_READ_ONLY1 << 3Graphics read-only mode
SILO_FLAG_WEBRTC_TURN_FORCE1 << 4Force TURN relay for WebRTC

Module system (CMOD)

Silos can load code modules in the CMOD binary format:

Strat9ModuleHeader {
    magic: "CMOD",
    version: 1 or 2,
    cpu_arch: 0 (x86_64),
    flags: MODULE_FLAG_SIGNED | MODULE_FLAG_KERNEL,
    code_offset/size, data_offset/size, bss_size,
    entry_point,
    export/import/relocation tables,
    key_id, signature,
    cpu_features_required (v2+),
}

Loading flow:

  1. Admin calls SYS_MODULE_LOAD with a blob (from file, IPC stream, or initfs path)
  2. Kernel validates the header (magic, version, alignment, signature)
  3. Module is registered in the global ModuleRegistry
  4. Admin calls SYS_SILO_ATTACH_MODULE to bind the module to a silo
  5. Admin calls SYS_SILO_START to launch the silo's entry point

Events

The kernel pushes events to a fixed-capacity ring buffer (256 entries). Userspace polls via SYS_SILO_EVENT_NEXT.

EventTrigger
StartedSilo started or config updated
StoppedGraceful stop
KilledForce kill
CrashedFault/panic (data0 encodes fault reason + subcode)
PausedSuspended
ResumedResumed from pause

Crash encoding: data0 = fault_reason | (subcode << 16)

  • PageFault (1), GeneralProtection (2), InvalidOpcode (3)

Silo admin

Admin operations require a ResourceType::Silo capability with grant permission. The SILO_ADMIN_RESOURCE (resource 0) is the special admin handle.

Bootstrap: The init process receives a silo-admin capability at boot via create_silo_admin_capability().

Admin operations:

OperationFunctionDescription
Createkernel_spawn_strate()Register module, create silo, spawn task
Startkernel_start_silo()Transitions Ready → Running
Stopkernel_stop_silo()Graceful stop (tasks exit)
Killkernel_stop_silo(force=true)Force kill all tasks
Destroykernel_destroy_silo()Remove silo (must be stopped)
Renamekernel_rename_silo_label()Change silo label
Pledgesys_silo_pledge()Restrict permissions
Unveilsys_silo_unveil()Restrict filesystem access
Sandboxsys_silo_enter_sandbox()Lock down (irreversible)

Path-based label assignment

When a filesystem path matches /srv/strate-fs-<type>/<label>/, the label is automatically assigned to the silo. This allows convention-based service discovery.


Silo vs. other isolation mechanisms

MechanismScopeEnforcement
SiloProcess group + resources + capabilitiesKernel (SiloManager)
CapabilityIndividual resource accessKernel (CapabilityManager)
PledgeSyscall permission subsetKernel (OctalMode)
UnveilFilesystem path accessKernel (UnveilRules)
SandboxFull lockdown (irreversible)Kernel (sandboxed flag)

Memory Management

Strat9 OS uses a layered memory architecture: physical frame allocation (buddy), kernel heap (slab), virtual memory (page tables + COW), and large-object allocation (vmalloc).


Memory hierarchy

graph TB
    subgraph "Physical"
        BUDDY[Buddy Allocator]
        ZONES[Zone DMA / Normal / HighMem]
        FRAMES[Physical Frames 4KiB]
    end

    subgraph "Kernel Heap"
        SLAB[Slab Sub-allocator]
        HEAP[GlobalAlloc Heap]
    end

    subgraph "Virtual Memory"
        AS[Address Space / PML4]
        VMA[Virtual Memory Regions]
        COW[COW Pages]
        PAGING[Page Tables]
    end

    subgraph "Large Objects"
        VMALLOC[Vmalloc]
    end

    BUDDY --> FRAMES
    ZONES --> BUDDY
    FRAMES --> SLAB
    SLAB --> HEAP
    FRAMES --> PAGING
    AS --> VMA
    VMA --> COW
    COW --> PAGING
    FRAMES --> VMALLOC

Buddy allocator

The buddy allocator manages physical frames. It divides memory into zones (DMA, Normal, HighMem) and uses a free-list per order (0–10) for power-of-two allocations.

Key properties:

  • Order-0 allocations go through per-CPU caches (LOCAL_FRAME_CACHES) for O(1) fast path
  • Cross-CPU stealing when local cache is empty
  • Compaction assist when high-order allocations fail
  • Refcount sentinel: free-list frames carry REFCOUNT_UNUSED (u32::MAX)
alloc order-0:
  1. Try local cache (per-CPU, PreemptDisabled lock)
  2. Refill cache from buddy global
  3. Steal from other CPU caches
  4. Fallback to global buddy allocator

Slab heap

The kernel heap uses a slab sub-allocator for small objects (≤ 2048 bytes). Each size class has its own free list backed by whole pages from the buddy allocator.

Class sizeTypical use
16 BSmall structs, list nodes
32 BCapability entries
64 BIPC message headers
128 BTask control blocks
256 BVMA entries
512 BPathname buffers
1024 BSyscall argument buffers
2048 BLarge temporary buffers

Allocations > 2048 bytes go directly to the buddy allocator via vmalloc.


Copy-on-Write (COW)

COW enables efficient fork() by sharing physical frames between parent and child.

sequenceDiagram
    participant P as Parent
    participant K as Kernel
    participant C as Child

    P->>K: fork()
    K->>K: Clone page tables (mark all RO + COW)
    K->>K: Share physical frames (refcount++)
    K-->>C: New address space

    Note over C: Child writes to shared page
    C->>K: Page fault (COW)
    K->>K: Allocate new frame, copy page
    K->>K: Remap child's PTE (RW, clear COW)
    K->>K: Decrement parent refcount
    K-->>C: Write succeeds

COW refcount invariant:

  • refcount == 1 → sole owner (no sharing)
  • refcount > 1 → shared (writes trigger COW fault)
  • refcount == REFCOUNT_UNUSED → free-list frame

Page tables

The kernel uses x86_64 4-level paging (PML4 → PDPT → PD → PT).

LevelCoversEntry size
PML4512 GiB8 bytes
PDPT1 GiB8 bytes
PD2 MiB (huge)8 bytes
PT4 KiB8 bytes

Address space layout:

  • PML4[0..256] → user space (per-process)
  • PML4[256..512] → kernel space (shared across all processes)

Each user process gets a fresh PML4 with the kernel half cloned from the boot PML4. This shares kernel L3/L2/L1 subtrees : kernel mapping changes propagate automatically.


Vmalloc

Large non-contiguous allocations use vmalloc, which maps arbitrary physical pages into a contiguous virtual range. Used for:

  • Large metadata arrays
  • Buffers that don't need physical contiguity
  • Allocations > buddy max order

Boot Sequence

Strat9 OS boots on x86_64 via the Limine boot protocol. The boot flow transitions from 16-bit real mode through protected mode to 64-bit long mode before jumping into Rust.


Boot flow

flowchart TD
    A[BIOS/UEFI] --> B[MBR / Stage 1]
    B --> C[Stage 2]
    C --> D[Limine Protocol]
    D --> E[kstart - Assembly]
    E --> F[start - Rust init]
    F --> G[main.rs - Kernel main]

    style A fill:#333,color:#fff
    style D fill:#1a6b3a,color:#fff
    style G fill:#1a6b3a,color:#fff

Stage 1 : MBR bootloader (bootloader/asm/)

The bootloader is written in NASM assembly. Stage 1 fits in exactly 512 bytes (MBR).

Responsibilities:

  1. Load Stage 2 from disk (LBA reads via BIOS INT 13h)
  2. Enable A20 line
  3. Enter protected mode (32-bit)
  4. Jump to Stage 2

Stage 2 : Protected → Long mode

Responsibilities:

  1. Detect available memory (INT 15h, E820)
  2. Load the kernel binary from disk
  3. Set up initial page tables (identity mapping + higher-half)
  4. Enable PAE, PGE, long mode
  5. Jump to 64-bit code

Limine handoff

The kernel is loaded by the Limine bootloader protocol. Limine provides:

  • Memory map (E820 equivalent)
  • HHDM (Higher Half Direct Map) base address
  • PML4 physical address
  • RSDP (ACPI tables)
  • Framebuffer info

The KernelArgs struct captures all handoff data:

KernelArgs {
    hhdm_offset: u64,       // Higher-half direct map base
    pml4_physical: u64,     // Boot page table
    acpi_rsdp: Option<NonNull<u8>>,  // ACPI RSDP
    memory_regions: &[MemoryRegion],  // E820 memory map
    framebuffer: FramebufferInfo,     // VGA/framebuffer
}

Kernel entry : kstart (assembly)

Located in boot/boot64.S:

  1. Verify BSS is zero, data is non-zero (sanity check)
  2. Set up kernel stack (128 KiB, from STACK static)
  3. Jump to start() (Rust)

Kernel init : start() (Rust)

Located in boot/limine.rsmain.rs:

flowchart TD
    A[serial::init] --> B[gdt::init_bsp]
    B --> C[idt::init_bsp]
    C --> D[memory::init]
    D --> E[paging::init]
    E --> F[interrupt::syscall::init]
    F --> G[allocator::init - buddy + slab]
    G --> H[acpi::init - parse MADT/IOAPIC]
    H --> I[apic::init - Local APIC]
    I --> J[smp::init - boot APs]
    J --> K[timer::init - APIC timer]
    K --> L[process::init - scheduler]
    L --> M[shell::init - init process]
    M --> N[scheduler::run - never returns]

Key init steps:

StepModuleWhat happens
Serialserial.rsInitialize COM1 (0x3F8) at 115200 baud
GDTgdt.rsSet up kernel/user code/data segments
IDTidt.rsInstall interrupt handlers (timer, syscall, page fault)
Memorymemory/Parse E820, initialize buddy allocator
Pagingpaging.rsSet up kernel page tables (HHDM + higher-half)
Syscallsyscall.rsInstall syscall/sysret MSRs
Heapheap.rsInitialize slab allocator on top of buddy
ACPIacpi/Parse MADT (APICs), IOAPIC, interrupt overrides
APICapic.rsInitialize Local APIC (xAPIC or x2APIC)
SMPsmp.rsINIT+SIPI sequence to boot Application Processors
Timertimer.rsCalibrate and start APIC timer (periodic)
Schedulerscheduler/Create per-CPU run queues, spawn idle tasks
Initshell/Spawn the first userspace process (init)

SMP boot : Application Processors

sequenceDiagram
    participant BSP
    participant TRAMP as Trampoline (0x8000)
    participant AP

    BSP->>TRAMP: Copy trampoline to 0x8000
    BSP->>TRAMP: Write CR3 + RSP to data area
    BSP->>AP: INIT IPI (0x4500)
    Note right of AP: 16-bit real mode
    BSP->>AP: SIPI (vector=0x8 → 0x8000)
    TRAMP->>AP: Enable protected mode
    TRAMP->>AP: Enable long mode + paging
    TRAMP->>AP: Load kernel stack
    TRAMP->>AP: Jump to smp_main (Rust)
    AP->>BSP: BOOTED_CORES++
    BSP->>BSP: Wait for all APs
    BSP->>AP: Open scheduler gate
    AP->>AP: Start per-CPU scheduler

IPC Mechanisms

Strat9 OS provides a 3-level hybrid IPC transport model with a central Transport Manager that selects the appropriate isolation level per silo pair. Each level offers a different trade-off between performance and isolation.


IPC Architecture Overview

graph TB
    subgraph "Transport Manager"
        TM[Decision Matrix<br/>Tier × Tier → Level]
    end

    subgraph "N1 : TypeSafe IPC"
        N1[IntrusiveMailbox<br/>Ring 0, approx. 3-10 cycles<br/>Rust type isolation]
    end

    subgraph "N2 : Lock-Free Ring"
        N2[LockFreeRing<br/>Ring 3, approx. 400-4000 cycles<br/>SPSC + futex notification]
    end

    subgraph "N3 : MMU Thread Migration"
        N3[MmuEndpoint<br/>Ring 3, approx. 800-2000 cycles<br/>CR3 switch + PCID]
    end

    TM --> N1
    TM --> N2
    TM --> N3

Transport selection matrix

Source \ DestCriticalSystemUser
CriticalN1 (TypeSafe)N1 (TypeSafe)N2 (LockFree)
SystemN1 (TypeSafe)N2 (LockFree)N2 (LockFree)
UserN2 (LockFree)N2 (LockFree)N3 (MMU)

N1 : Type-Safe IPC (IntrusiveMailbox)

The fastest transport : kernel-internal, same address space, approx. 3-10 cycles per message.

How it works

Two kernel components (e.g., scheduler ↔ VFS) communicate via an intrusive LIFO mailbox. Messages are linked directly in kernel memory using tagged pointers (x86-64 ABA-safe). No copy, no lock, no syscall.

Constraints

  • Ring 0 only : both sender and receiver must be kernel components
  • 100% Rust Safe : #[forbid(unsafe_code)] required, cargo-geiger = 0
  • LIFO ordering : not FIFO; use N2 if ordering matters
  • No untrusted input : forbidden for network, user data, external files

Usage

let mailbox = IntrusiveMailbox::new();
mailbox.push(b"notification")?;  // approx. 3 cycles
let msg = mailbox.pop();          // LIFO: last message first

N2 : Lock-Free Ring (SPSC)

High-throughput shared-memory transport : approx. 400-4000 cycles depending on sleep mode.

How it works

A lock-free SPSC ring buffer backed by physically contiguous DMA-accessible pages. The producer writes data, sets a Release barrier on len, then publishes via tail.store(Release). The consumer observes tail, reads data via Acquire, and advances head. Futex notification for sleeping consumers.

Two sub-modes

ModeLatencyUse case
N2a (busy-poll)approx. 400 cyclesHot path, low-latency
N2b (futex sleep)approx. 1000-4000 cyclesBackground processing

Memory layout

Page 0: RingHeader (cache-line padded)
  Line 0: magic, capacity, slot_size, flags, notify_seq
  Line 1: head (consumer hot)  : 60B padding
  Line 2: tail (producer hot)  : 60B padding
Pages 1+: RingSlot entries
  Each: [len:u16][flags:u16][data:u8; SLOT_SIZE]

Usage

let (producer, consumer) = create_spsc_pair(256);  // 256 slots

// Producer (kernel or Ring 3)
producer.write(b"packet data")?;
producer.notify_consumer();  // futex wake

// Consumer (strate-net, Ring 3)
let mut buf = [0u8; 2048];
let n = consumer.read(&mut buf)?;

NIC integration (data plane)

NIC HW Queue 0 → Ring SPSC 0 → strate-net (poll round-robin)
NIC HW Queue 1 → Ring SPSC 1 →
NIC HW Queue 2 → Ring SPSC 2 →

Each RSS queue gets its own SPSC ring : no MPSC contention, no head-of-line blocking.


N3 : MMU Thread Migration (Research Track)

Maximum isolation : approx. 800-2000 cycles : currently research track with N2 fallback.

How it works

Inspired by L4 Thread Migration (Liedtke 1995): instead of a full syscall + context switch, the kernel migrates the CPU quantum directly to the target process by switching CR3 (address space) and jumping to the handler. Three tiers:

TierMechanismCostCondition
N3aSame-core handoffapprox. 200-400cSame core, mappings valid
N3bPCID-preserving CR3approx. 400-800cPCID active, prefaulted
N3cFull migrationapprox. 800-2000cFirst call, TLB flush

Status

⚠️ Research track : N3 is not yet implemented. All User↔User pairs fall back to N2 (LockFree Ring).


Legacy mechanisms (still available)

These mechanisms predate the Transport Manager and remain functional:

IPC Ports (synchronous message-passing)

SyscallDescription
SYS_IPC_CREATE_PORT (200)Create a new port
SYS_IPC_SEND (201)Send a message
SYS_IPC_RECV (202)Receive a message
SYS_IPC_CALL (203)Send and wait for reply
SYS_IPC_REPLY (204)Reply to a call
SYS_IPC_BIND_PORT (205)Bind to namespace
SYS_IPC_UNBIND_PORT (206)Unbind

Typed MPMC Channels

let (tx, rx) = channel::<MyMessage>(64);
tx.send(msg)?;           // blocks if full
let msg = rx.recv()?;    // blocks if empty

Shared Ring (legacy)

High-throughput bulk IPC using shared-memory ring buffers. Superseded by N2 Lock-Free Ring for new code.

Semaphore

POSIX-like counting semaphore for synchronization.


Transport Manager API

Creating a transport

let manager = TransportManager::new();
let result = manager.establish(
    src_silo, dst_silo,
    TransportConfig {
        min_level: TransportLevel::LockFree,
        ring_capacity: Some(256),
        slot_size: None,
    },
)?;
// result.local and result.remote are the endpoints

Dynamic policy override

// Force N2 for a specific silo pair
manager.set_policy(src_sid, dst_sid, TransportLevel::LockFree, 512);

Syscall interface (planned)

Syscall#Description
SYS_TRANSPORT_CREATE240Create a transport
SYS_TRANSPORT_SEND241Send a message
SYS_TRANSPORT_RECV242Receive a message
SYS_TRANSPORT_CLOSE243Close transport
SYS_TRANSPORT_INFO244Get transport info

Performance comparison

MechanismRound-trip 64BCPU usage/pktIsolation
Legacy IPC (syscall)approx. 4000 cyclesapprox. 2%MMU
N1 TypeSafeapprox. 6-20 cyclesapprox. 0.01%Rust types
N2 LockFree (busy)approx. 400-800 cyclesapprox. 0.1%MMU
N2 LockFree (futex)approx. 1000-4000 cyclesapprox. 0.2%MMU
N3 MMU (research)approx. 800-2000 cyclesapprox. 0.5%MMU (max)

References

  1. Xu, P. & Roscoe, T. (2025) : The NIC should be part of the OS, HotOS'25 : arXiv
  2. Liedtke, J. (1995) : On µ-Kernel Construction, SOSP
  3. Hunt, G.C. & Larus, J.R. (2007) : Singularity: Rethinking the Software Stack, ACM Queue
  4. Levy, A. et al. (2017) : Multiprogramming a 64kB Computer Safely and Efficiently with Tock, SOSP
  5. Vyukov, D. : Bounded MPMC queue : lock-free SPSC/MPMC benchmarks
  6. Axboe, J. (2019) : Efficient IO with io_uring, kernel.org

IPC Transport Architecture

Driver Model

Strat9 OS uses a trait-based component model for drivers. Each driver registers itself during boot and is discovered through PCI/VirtIO enumeration.


Driver categories

graph TB
    subgraph "Storage"
        NVMe[NVMe]
        AHCI[AHCI/SATA]
        VIO_BLK[VirtIO Block]
    end

    subgraph "Network"
        E1000[E1000/E1000e]
        IGC[IGC]
        VIO_NET[VirtIO Net]
    end

    subgraph "Input"
        USB_HID[USB HID]
        PS2[PS/2 Keyboard]
    end

    subgraph "Display"
        FB[Framebuffer]
        VGA[VGA text mode]
    end

    subgraph "Bus"
        PCI[PCI enumeration]
        VIO[VirtIO transport]
        USB[XHCI host controller]
    end

    PCI --> NVMe
    PCI --> AHCI
    PCI --> E1000
    PCI --> IGC
    VIO --> VIO_BLK
    VIO --> VIO_NET
    USB --> USB_HID

Component trait

All drivers implement the Component trait, which provides a uniform registration interface:

pub trait Component: Send + Sync {
    fn name(&self) -> &str;
    fn init(&self) -> Result<(), ComponentError>;
    fn shutdown(&self);
}

Components are registered at boot via the component-macro derive macro:

#[derive(Component)]
struct MyDriver { /* ... */ }

PCI enumeration

The PCI bus is scanned at boot using a BFS algorithm with early-exit optimization:

  1. For each (bus, device), probe function 0 first
  2. If vendor == 0xFFFF → skip all 8 functions (early exit)
  3. Read header type bit 7 for multi-function flag
  4. If PCI-to-PCI bridge → enqueue secondary bus

This reduces worst-case probes from 65,536 to approx. 8,192 for typical topologies.

Key PCI types:

TypeDescription
PciAddressBus/device/function address
PciDeviceDevice info (vendor, class, BARs, IRQ)
ProbeCriteriaFilter for device discovery

NIC drivers

E1000 / E1000e

Intel Ethernet drivers supporting:

  • Legacy descriptor rings (T/R)
  • MSI-X interrupt moderation
  • Multicast filter
  • VLAN offload

IGC

Intel I225/I226 2.5GbE driver with:

  • Advanced RX/TX descriptors
  • Time-based interrupt coalescing
  • Hardware timestamping

Common NIC infrastructure

ModulePurpose
nic-queuesTX/RX queue management, descriptor ring abstraction
nic-buffersBuffer allocation, DMA-safe memory
net-corePacket parsing, protocol headers
driver-net-protoProtocol driver trait

Storage drivers

NVMe

Full NVMe driver with:

  • I/O queues (per-CPU submission/completion pairs)
  • MSI-X interrupt steering
  • Namespace management
  • Admin queue for controller commands

AHCI / SATA

AHCI controller driver for SATA devices:

  • Port enumeration
  • DMA PRDT (Physical Region Descriptor Table)
  • FIS-based communication

VirtIO Block

Paravirtualized block device for QEMU/KVM:

  • VirtIO queue negotiation
  • Multi-queue support
  • Feature bits (discard, write cache)

USB stack

graph TD
    XHCI[XHCI Host Controller] --> HUB[Hub Driver]
    HUB --> HID[USB HID - Keyboard/Mouse]
    HUB --> MASS[USB Mass Storage]
    HUB --> NET[USB Ethernet]

The XHCI driver manages the USB host controller, enumerates devices through hub traversal, and dispatches to class-specific drivers (HID, mass storage, etc.).


VirtIO transport

VirtIO provides paravirtualized device access for QEMU/KVM:

DeviceModulePurpose
VirtIO Blockvirtio/blockBlock I/O
VirtIO Netvirtio/netNetwork
VirtIO Consolevirtio/consoleSerial console
VirtIO GPUvirtio/gpuDisplay
VirtIO Inputvirtio/inputKeyboard/mouse

Device discovery flow

sequenceDiagram
    participant BOOT as Boot
    participant PCI as PCI Scanner
    participant DRV as Driver Registry
    participant DEV as Device

    BOOT->>PCI: Scan PCI bus
    PCI->>DRV: Notify: device found
    DRV->>DRV: Match vendor/device ID
    DRV->>DEV: Initialize driver
    DEV->>DEV: Map BARs, enable bus mastering
    DEV->>DEV: Register IRQ handler
    DEV-->>BOOT: Device ready

ABI Overview

The canonical ABI definitions live in workspace/abi (strat9-abi crate).

Focus modules:

  • strat9_abi::syscall for syscall numbers
  • strat9_abi::data for shared wire/data structs
  • strat9_abi::flag for ABI-level flags
  • strat9_abi::errno for error codes
  • strat9_abi::boot for boot handoff ABI

API reference:

ABI Changelog

This page tracks ABI evolution for strat9-abi.

Versioning policy

  • Major (ABI_VERSION_MAJOR) changes only for incompatible wire/layout changes.
  • Minor (ABI_VERSION_MINOR) changes for backward-compatible additions.
  • No silent renumbering of existing syscall IDs.
  • repr(C) and explicit size checks are mandatory for exported ABI structs.

Current version

  • ABI_VERSION_MAJOR = 0
  • ABI_VERSION_MINOR = 1
  • Packed: 0.1

See:

Recent ABI updates (auto-generated)

  • 2026-06-25 4fb871f Refactor error codes and syscall flags; implement getrandom syscall
  • 2026-06-25 a522fb8 Refactor NIC data plane and IPC transport statistics
  • 2026-06-25 d1e838f feat: implement IPC transport layer with 3-level architecture
  • 2026-06-25 411f5aa feat: add IPC transport layer support and enhance ICMP handling
  • 2026-06-25 5a3d69c feat: migrate input system to userspace
  • 2026-06-24 3fea3f3 SMP hardware debug, NVMe fixes, VGA refactor, telnetd hardening, docs
  • 2026-06-16 e4ab1a9 Enhance network stack, NIC drivers, USB/NVMe subsystems, and thermal management
  • 2026-06-03 0c40058 Refactor the network stack and add dual-stack userspace tooling
  • 2026-05-24 aeade5e Code cleanup
  • 2026-05-24 b2bbcc0 Improve and fix IPC
  • 2026-05-23 db23b53 Fix major memory leak and remove sshd silo
  • 2026-05-19 93c8927 async: implement and optimize async I/O completion handling
  • 2026-05-18 7c5efb4 async: io_uring-like async I/O — ring, dispatch, AHCI bridge (Phases 1-4)
  • 2026-05-14 cc4944a Refactor and clean up code in various modules
  • 2026-05-14 ecc416d refactor: strate-init refactoring, ELF/VFS/signal hardening, TSC calibration fix
  • 2026-05-08 f070d41 Add kernel entropy pool with interrupt-driven collection
  • 2026-05-08 9dedb9f Implement robust list support (set_robust_list/get_robust_list)
  • 2026-05-08 d2e90a2 Bridge clone() thread creation via SYS_THREAD_CREATE, add faccessat routing
  • 2026-05-08 dabcad2 Add sys_access(), sys_faccessat(), and SYS_GETRANDOM() in syscall dispatcher
  • 2026-05-08 946f200 Add missing call for clock_nanosleep and update the calling manager
  • 2026-05-06 117863e Enhance network and silo management functionality
  • 2026-04-12 6963e28 fix: reduce scheduler contention and harden early boot memory init
  • 2026-04-12 f3647c1 feat(memory): production-grade allocator architecture (#49)
  • 2026-04-06 a941264 feat: capability-based CWD, *at syscalls, and O_RESOLVE_BENEATH sandboxing
  • 2026-04-06 309a9c1 refactor: runtime allocation, scheduler lock decoupling, FixedQueue, and VGA improvements
  • 2026-03-26 a9a6cd6 Implement block-oriented memory management and ownership tracking
  • 2026-03-23 ec8ee9f refactor(memory): update reference counting logic for COW frames
  • 2026-03-23 aaa89e0 Refactor: Decouple per-CPU scheduler state and logic from the global scheduler instance by moving SchedulerCpu to local CPU storage.
  • 2026-03-21 c3f93c6 feat: Implement TSC-based boot timing and milestones, along with an analysis...
  • 2026-03-17 eb7818d feat: Implement static module loading from initfs paths and increase module blob size limit.

Changelog entries

0.1

  • Introduced canonical strat9-abi crate as single source of truth.
  • Unified syscall numbers in strat9_abi::syscall.
  • Unified shared structs (TimeSpec, IpcMessage, FileStat, PCI types).
  • Added boot handoff ABI (KernelArgs, MemoryRegion, MemoryKind) with magic/version checks.
  • Added ABI introspection syscall SYS_ABI_VERSION.

Entry template

Use this template for future ABI entries:

### X.Y
- Added:
  - <new syscalls/types/flags>
- Changed (compatible):
  - <field additions, new constants, optional semantics>
- Changed (breaking):
  - <layout/numbering/semantic breaks>
- Migration notes:
  - <what userspace/kernel must update>

ABI Support Matrix

Status of musl platform APIs on x86_64-unknown-strat9.

Legend: OK = implemented, Stub = returns ENOSYS, Partial = limited.

POSIX File I/O

APIStatusNotes
open / openatOKVia SYS_OPEN
readOKVia SYS_READ
writeOKVia SYS_WRITE
closeOKVia SYS_CLOSE
lseekOKVia SYS_LSEEK
preadOKVia SYS_PREAD
pwriteOKVia SYS_PWRITE
fstat / fstatatOKVia SYS_FSTAT / SYS_STAT
dup / dup2OKVia SYS_DUP / SYS_DUP2
pipe / pipe2OKVia SYS_PIPE
fcntlOKVia SYS_FCNTL
mkdir / mkdiratOKVia SYS_MKDIR
unlinkOKVia SYS_UNLINK
rmdirOKVia SYS_RMDIR
rename / renameatOKVia SYS_RENAME
linkOKVia SYS_LINK
symlinkOKVia SYS_SYMLINK
readlinkOKVia SYS_READLINK
chmod / fchmodOKVia SYS_CHMOD / SYS_FCHMOD
truncate / ftruncateOKVia SYS_TRUNCATE / SYS_FTRUNCATE
chdir / fchdirOKVia SYS_CHDIR / SYS_FCHDIR
getcwdOKVia SYS_GETCWD
getdentsOKVia SYS_GETDENTS
accessOKOpen + close probe
umaskOKVia SYS_UMASK
fsync / fdatasyncStubENOSYS
flockStubENOSYS
chown / fchown / lchownStubENOSYS
statvfs / fstatvfsStubENOSYS
mknod / mknodat / mkfifoatStubENOSYS

Process Management

APIStatusNotes
exitOKVia SYS_PROC_EXIT
forkOKVia SYS_PROC_FORK
execveOKVia SYS_PROC_EXEC
waitpidOKVia SYS_PROC_WAITPID
getpid / getppid / gettidOK
setsid / setpgid / getpgid / getsidOK
sched_yieldOKVia SYS_PROC_YIELD
nanosleepOKVia SYS_NANOSLEEP
clock_gettimeOKVia SYS_CLOCK_GETTIME
brkOKVia SYS_BRK
mmap / munmapOKVia SYS_MMAP / SYS_MUNMAP
unameOKVia SYS_PROC_UNAME
getuid / geteuid / getgid / getegidPartialReturns 0 (no UID model)
mprotect / mlock / munlockStubENOSYS
getrandomOKVia SYS_GETRANDOM (601), supports GRND_NONBLOCK

Signals

APIStatusNotes
killOKVia SYS_KILL
sigactionOKVia SYS_SIGACTION
sigprocmaskOKVia SYS_SIGPROCMASK
sigsuspendOKVia SYS_SIGSUSPEND
sigtimedwaitOKVia SYS_SIGTIMEDWAIT
getitimer / setitimerOKVia SYS_GETITIMER / SYS_SETITIMER
sigaltstackOKVia SYS_SIGALTSTACK

Network / Sockets

APIStatusNotes
socketpair (AF_UNIX)PartialBacked by pipe (unidirectional)
recvfrom / sendtoPartialDelegates to read/write
socket / bind / listen / accept / connectStubENOSYS
setsockopt / getsockoptStubENOSYS
shutdownStubENOSYS

Epoll

APIStatusNotes
epoll_create1PartialBacked by pipe fd
epoll_ctlStubNo-op
epoll_pwaitPartialSleeps, no real multiplexing

Syscall Reference

Complete reference for all Strat9 OS syscalls. Syscalls are invoked via the syscall instruction (x86_64). Arguments are passed in registers; the return value is in RAX.

ABI convention: Success returns a non-negative value. Errors return a negative errno value (two's complement). Userspace checks if result > 0xFFFF_F000 to detect errors, then applies !result + 1 to get the errno number.

Constants

AT_* flags (for *at syscalls)

ConstantValueDescription
AT_FDCWD-100Use the process's current working directory as the base directory
AT_REMOVEDIR0x200Remove a directory (for SYS_UNLINKAT)
AT_SYMLINK_NOFOLLOW0x100Do not follow symbolic links (for SYS_FSTATAT)
AT_EMPTY_PATH0x1000Operate on the fd itself when path is empty

Open flags

FlagValueDescription
O_RDONLY0Open for reading
O_WRONLY1Open for writing
O_RDWR2Open for reading and writing
O_CREAT0x40Create file if it does not exist
O_EXCL0x800Fail if file already exists (with O_CREAT)
O_TRUNC0x200Truncate file to zero length
O_APPEND0x400Append to end of file
O_NONBLOCK0x800Non-blocking mode
O_DIRECTORY0x10000Open as directory
O_NOFOLLOW0x20000Do not follow symlinks

Protection flags (mmap)

FlagValueDescription
PROT_READ1Page can be read
PROT_WRITE2Page can be written
PROT_EXEC4Page can be executed

Signal constants

ConstantValueDescription
SIG_DFL0Default signal handling
SIG_IGN1Ignore signal
SIG_BLOCK0Block signals in set
SIG_UNBLOCK1Unblock signals in set
SIG_SETMASK2Set signal mask to set

Waitpid options

FlagValueDescription
WNOHANG1Return immediately if no child has exited
WUNTRACED2Also return for stopped children
WCONTINUED4Also return for continued children

Clock IDs

ConstantValueDescription
CLOCK_REALTIME0System-wide real-time clock
CLOCK_MONOTONIC1Monotonic clock (not affected by adjustments)
CLOCK_PROCESS_CPUTIME_ID2Per-process CPU time
CLOCK_THREAD_CPUTIME_ID3Per-thread CPU time

Handle operations

#SyscallParametersReturnDescription
0SYS_NULL:0No-op (used for benchmarking)
1SYS_HANDLE_DUPLICATEhandle: u64new handleDuplicate a capability handle
2SYS_HANDLE_CLOSEhandle: u640Close a capability handle
3SYS_HANDLE_WAIThandle: u64, timeout_ns: u640Wait on a handle (blocks until ready or timeout)
4SYS_HANDLE_GRANThandle: u64, target_pid: u640Grant a capability to another process
5SYS_HANDLE_REVOKEhandle: u640Revoke a capability (all holders lose access)
6SYS_HANDLE_INFOhandle: u64, out_ptr: u640Query capability info (writes HandleInfo struct)

Errors: EBADF (invalid handle), EPERM (no grant permission), ESRCH (target process not found)


Memory management

#SyscallParametersReturnDescription
100SYS_MMAPaddr: u64, len: u64, prot: u64, flags: u64, fd: u64, offset: u64mapped addressMap a memory region
101SYS_MUNMAPaddr: u64, len: u640Unmap a memory region
102SYS_BRKaddr: u64new breakSet/clear the data break
103SYS_MREMAPold_addr: u64, old_len: u64, new_len: u64, flags: u64, new_addr: u64new addressRemap a memory region
104SYS_MPROTECTaddr: u64, len: u64, prot: u640Change memory protection flags
105SYS_MEM_REGION_EXPORTaddr: u64, len: u64region handleExport a memory region as a shareable handle
106SYS_MEM_REGION_MAPregion_handle: u64, addr: u64, len: u64mapped addressMap an exported memory region
107SYS_MEM_REGION_INFOregion_handle: u64, out_ptr: u640Query region metadata

Prot flags: PROT_READ (1), PROT_WRITE (2), PROT_EXEC (4)

Errors: EINVAL (bad alignment/flags), ENOMEM (out of memory), EACCES (permission denied), EEXIST (region already mapped)


IPC : Ports

#SyscallParametersReturnDescription
200SYS_IPC_CREATE_PORT:port handleCreate a new IPC port
201SYS_IPC_SENDport_handle: u64, msg_ptr: u64, msg_len: u640Send a message to a port
202SYS_IPC_RECVport_handle: u64, buf_ptr: u64, buf_len: u64bytes receivedReceive a message (blocks)
203SYS_IPC_CALLport_handle: u64, msg_ptr: u64, msg_len: u64bytes receivedSynchronous RPC (send + wait for reply)
204SYS_IPC_REPLYmsg_ptr: u64, msg_len: u640Reply to the current IPC call
205SYS_IPC_BIND_PORTport_handle: u640Bind a port as a listener
206SYS_IPC_UNBIND_PORTport_handle: u640Unbind a listening port
207SYS_IPC_TRY_RECVport_handle: u64, buf_ptr: u64, buf_len: u64bytes received (0 if empty)Non-blocking receive
208SYS_IPC_CONNECTport_handle: u640Connect to a bound port
210SYS_IPC_RING_CREATEsize_log2: u64ring handleCreate a shared ring buffer
211SYS_IPC_RING_MAPring_handle: u64, addr: u640Map a shared ring into address space

Errors: EBADF (invalid handle), ENOSPC (ring full), EAGAIN (non-blocking, nothing available), ETIMEDOUT (timeout exceeded)


IPC : Channels (typed MPMC)

#SyscallParametersReturnDescription
220SYS_CHAN_CREATEcapacity: u64channel handleCreate a typed channel
221SYS_CHAN_SENDhandle: u64, msg_ptr: u640Send a message (blocks if full)
222SYS_CHAN_RECVhandle: u64, msg_ptr: u640Receive a message (blocks if empty)
223SYS_CHAN_TRY_RECVhandle: u64, msg_ptr: u641 if received, 0 if emptyNon-blocking receive
224SYS_CHAN_CLOSEhandle: u640Close channel handle

Errors: EBADF (invalid handle), EPIPE (all endpoints disconnected), EAGAIN (try_recv on empty channel)


IPC : Semaphores

#SyscallParametersReturnDescription
230SYS_SEM_CREATEinitial_value: u64semaphore handleCreate a counting semaphore
231SYS_SEM_WAIThandle: u640Decrement (blocks if zero)
232SYS_SEM_TRYWAIThandle: u641 if acquired, 0 if would blockNon-blocking decrement
233SYS_SEM_POSThandle: u640Increment (wake a waiter)
234SYS_SEM_CLOSEhandle: u640Close semaphore handle

Errors: EBADF (invalid handle), EAGAIN (try_wait on zero semaphore)


PCI

#SyscallParametersReturnDescription
240SYS_PCI_ENUMcriteria_ptr: u64, out_ptr: u64, max_count: u64device countEnumerate PCI devices matching criteria
241SYS_PCI_CFG_READaddr_ptr: u64, offset: u64, width: u64config valueRead PCI configuration register
242SYS_PCI_CFG_WRITEaddr_ptr: u64, offset: u64, width: u64, value: u640Write PCI configuration register

Errors: EINVAL (invalid width/offset), EACCES (no PCI capability)


Async I/O

#SyscallParametersReturnDescription
250SYS_ASYNC_SETUPhandle: u64, event_mask: u64async contextSet up async notification on a handle
251SYS_ASYNC_ENTERctx: u640Enter async wait (yields until event)
252SYS_ASYNC_CANCELctx: u640Cancel pending async wait
253SYS_ASYNC_MAPctx: u64, ring_handle: u640Map an event ring to the async context
254SYS_ASYNC_DESTROYctx: u640Destroy async context

Process management

#SyscallParametersReturnDescription
300SYS_PROC_EXITexit_code: u64: (never returns)Terminate current process
301SYS_PROC_YIELD:0Yield CPU to scheduler
302SYS_PROC_FORKframe: &SyscallFramechild PID (parent), 0 (child)Fork the current process (COW)
308SYS_PROC_GETPID:process IDGet current process ID
309SYS_PROC_GETPPID:parent PIDGet parent process ID
310SYS_PROC_WAITPIDpid: i64, status_ptr: u64, options: u64child PIDWait for a child process
311SYS_GETPID:process IDAlias for SYS_PROC_GETPID
312SYS_GETTID:thread IDGet current thread ID
314SYS_PROC_WAIT::Wait for any child
315SYS_PROC_EXECVEpath_ptr: u64, path_len: u64, argv_ptr: u64, envp_ptr: u64: (replaces image)Execute a new program
341SYS_THREAD_CREATEentry: u64, stack: u64, arg: u64thread IDCreate a new thread
342SYS_THREAD_JOINtid: u64, status_ptr: u640Wait for thread to exit
343SYS_THREAD_EXITstatus: u64: (never returns)Terminate current thread

Errors: ECHILD (no child processes), EAGAIN (thread creation failed), ENOMEM (out of memory)


Futex

#SyscallParametersReturnDescription
303SYS_FUTEX_WAITaddr: u64, val: u32, timeout_ns: u640Sleep if *addr == val
304SYS_FUTEX_WAKEaddr: u64, max_wake: u32woken countWake up to N waiters
305SYS_FUTEX_REQUEUEaddr: u64, max_wake: u32, addr2: u64, max_requeue: u32woken countWake + requeue to addr2
306SYS_FUTEX_CMP_REQUEUEaddr: u64, max_wake: u32, addr2: u64, max_requeue: u32, cmp_val: u32woken countConditional requeue
307SYS_FUTEX_WAKE_OPaddr: u64, max_wake: u32, addr2: u64, max_requeue: u32, wake_op: u32woken countAtomic op + wake

Errors: EAGAIN (value mismatch in WAIT), ETIMEDOUT (timeout expired), EFAULT (invalid address)


Signals

#SyscallParametersReturnDescription
320SYS_KILLpid: i64, signum: u320Send signal to a process
321SYS_SIGPROCMASKhow: i32, set_ptr: u64, oldset_ptr: u640Get/set signal mask
322SYS_SIGACTIONsignum: u64, act_ptr: u64, oact_ptr: u640Set signal handler
323SYS_SIGALTSTACKss_ptr: u64, old_ss_ptr: u640Set alternate signal stack
324SYS_SIGPENDINGset_ptr: u640Get pending signals
325SYS_SIGSUSPENDmask_ptr: u64: (restarted on signal)Suspend until signal
326SYS_SIGTIMEDWAITset_ptr: u64, info_ptr: u64, timeout_ptr: u64signal numberWait for specific signal
327SYS_SIGQUEUEpid: i64, signum: u32, sigval_ptr: u640Queue a signal with data
328SYS_KILLPGpgrp: u64, signum: u320Send signal to process group
352SYS_TGKILLtgid: u64, tid: u64, signum: u320Send signal to specific thread
353SYS_RT_SIGRETURN::Return from signal handler

Process groups & sessions

#SyscallParametersReturnDescription
316SYS_FCNTLfd: u64, cmd: u64, arg: u64depends on cmdFile control operations
317SYS_SETPGIDpid: u64, pgid: u640Set process group ID
318SYS_GETPGIDpid: u64pgidGet process group ID
319SYS_SETSID:session IDCreate new session
329SYS_GETITIMERwhich: u64, out_ptr: u640Get interval timer
330SYS_SETITIMERwhich: u64, in_ptr: u64, out_ptr: u640Set interval timer
331SYS_GETPGRP:pgrpGet current process group
332SYS_GETSIDpid: u64sidGet session ID
333SYS_SET_TID_ADDRESStidptr: u640Set clear-on-exit TID address
334SYS_EXIT_GROUPexit_code: u64: (never returns)Exit all threads in process

User/group IDs

#SyscallParametersReturnDescription
335SYS_GETUID:uidGet real user ID
336SYS_GETEUID:euidGet effective user ID
337SYS_GETGID:gidGet real group ID
338SYS_GETEGID:egidGet effective group ID
339SYS_SETUIDuid: u640Set user ID
340SYS_SETGIDgid: u640Set group ID

Misc process

#SyscallParametersReturnDescription
344SYS_UNAMEuts_ptr: u640Get system information (name, release, etc.)
350SYS_ARCH_PRCTLcode: u64, addr: u640Architecture-specific process control

File I/O

#SyscallParametersReturnDescription
403SYS_OPENpath_ptr: u64, path_len: u64, flags: u64file descriptorOpen a file
404SYS_WRITEfd: u64, buf_ptr: u64, buf_len: u64bytes writtenWrite to a file descriptor
405SYS_READfd: u64, buf_ptr: u64, buf_len: u64bytes readRead from a file descriptor
406SYS_CLOSEfd: u640Close a file descriptor
407SYS_LSEEKfd: u64, offset: u64, whence: u64new positionSeek in a file
408SYS_FSTATfd: u64, stat_ptr: u640Get file status (fstat)
409SYS_STATpath_ptr: u64, path_len: u64, stat_ptr: u640Get file status by path
413SYS_ACCESSpath_ptr: u64, path_len: u64, mode: u640Check file accessibility (uses effective UID/GID, not real). Prefer SYS_FACCESSAT for new code.
430SYS_GETDENTSfd: u64, buf_ptr: u64, buf_len: u64bytes readRead directory entries
431SYS_PIPEfds_ptr: u640Create a pipe pair
432SYS_DUPold_fd: u64new fdDuplicate file descriptor
433SYS_DUP2old_fd: u64, new_fd: u64new fdDuplicate to specific fd
456SYS_PREADfd: u64, buf_ptr: u64, buf_len: u64, offset: u64bytes readPread at offset
457SYS_PWRITEfd: u64, buf_ptr: u64, buf_len: u64, offset: u64bytes writtenPwrite at offset

Open flags: O_RDONLY (0), O_WRONLY (1), O_RDWR (2), O_CREAT (0x40), O_TRUNC (0x200), O_APPEND (0x400), O_EXCL (0x800)

Errors: ENOENT (file not found), EACCES (permission denied), EBADF (bad fd), ENOTDIR (not a directory), EISDIR (is a directory), ENOSPC (disk full), EIO (I/O error)


File system operations

#SyscallParametersReturnDescription
440SYS_CHDIRpath_ptr: u64, path_len: u640Change working directory
441SYS_FCHDIRfd: u640Change working directory by fd
442SYS_GETCWDbuf_ptr: u64, buf_len: u64bytes writtenGet current working directory
443SYS_IOCTLfd: u64, cmd: u64, arg: u64depends on cmdDevice I/O control
444SYS_UMASKmask: u64old maskSet file mode creation mask
445SYS_UNLINKpath_ptr: u64, path_len: u640Delete a file
446SYS_RMDIRpath_ptr: u64, path_len: u640Remove a directory
447SYS_MKDIRpath_ptr: u64, path_len: u64, mode: u640Create a directory
448SYS_RENAMEold_ptr: u64, old_len: u64, new_ptr: u64, new_len: u640Rename a file
449SYS_LINKold_ptr: u64, old_len: u64, new_ptr: u64, new_len: u640Create a hard link
450SYS_SYMLINKtarget_ptr: u64, target_len: u64, link_ptr: u64, link_len: u640Create a symbolic link
451SYS_READLINKpath_ptr: u64, path_len: u64, buf_ptr: u64, buf_len: u64bytes readRead symbolic link target
452SYS_CHMODpath_ptr: u64, path_len: u64, mode: u640Change file permissions
453SYS_FCHMODfd: u64, mode: u640Change file permissions by fd
454SYS_TRUNCATEpath_ptr: u64, path_len: u64, len: u640Truncate a file
455SYS_FTRUNCATEfd: u64, len: u640Truncate a file by fd

*at variants (relative to directory fd)

These syscalls resolve paths relative to a directory file descriptor instead of the process CWD. They are the POSIX-standard way to open, stat, and manipulate files safely in multi-threaded programs.

Special dirfd values

ValueConstantMeaning
-100AT_FDCWDUse the process's current working directory (CWD) as the base
≥ 0valid fdUse the opened directory referenced by this file descriptor

Syscall reference

#SyscallParametersReturnDescription
462SYS_OPENATdirfd: u64, path_ptr: u64, path_len: u64, flags: u64file descriptorOpen a file relative to dirfd. If path_ptr is absolute, dirfd is ignored.
463SYS_FSTATATdirfd: u64, path_ptr: u64, path_len: u64, stat_ptr: u64, flags: u640Get file status relative to dirfd. stat_ptr receives a FileStat struct.
464SYS_UNLINKATdirfd: u64, path_ptr: u64, path_len: u64, flags: u640Delete a file relative to dirfd. If AT_REMOVEDIR flag is set, removes a directory.
465SYS_RENAMEATolddirfd: u64, old_ptr: u64, old_len: u64, newdirfd: u64, new_ptr: u64, new_len: u640Rename/move a file. Source and destination can have different base directories.
466SYS_MKDIRATdirfd: u64, path_ptr: u64, path_len: u64, mode: u640Create a directory relative to dirfd.
467SYS_READLINKATdirfd: u64, path_ptr: u64, path_len: u64, buf_ptr: u64, buf_len: u64bytes readRead the target of a symbolic link relative to dirfd.
468SYS_FACCESSATdirfd: u64, path_ptr: u64, path_len: u64, mode: u64, flags: u640Check file accessibility. mode: R_OK (4), W_OK (2), X_OK (1), F_OK (0).

Flags

FlagValueDescription
AT_FDCWD-100Use process CWD as base directory
AT_REMOVEDIR0x200Unlink a directory instead of a file (for SYS_UNLINKAT)
AT_SYMLINK_NOFOLLOW0x100Do not follow symlinks (for SYS_FSTATAT)
AT_EMPTY_PATH0x1000Operate on dirfd itself when path is empty

Errors

EBADF (invalid dirfd), ENOENT (path not found), EACCES (permission denied), ENOTDIR (dirfd is not a directory), EEXIST (file exists for CREATE_EXCL), EINVAL (invalid flags)


Poll / I/O multiplexing

#SyscallParametersReturnDescription
460SYS_POLLfds_ptr: u64, nfds: u64, timeout_ms: i64ready countPoll file descriptors
461SYS_PPOLLfds_ptr: u64, nfds: u64, timeout_ptr: u64, sigmask_ptr: u64ready countPpoll with signal mask

Network

#SyscallParametersReturnDescription
410SYS_NET_RECVbuf_ptr: u64, buf_len: u64bytes receivedReceive network packet
411SYS_NET_SENDbuf_ptr: u64, buf_len: u64bytes sentSend network packet
412SYS_NET_INFOinfo_type: u64, buf_ptr: u640Query network info (IP, gateway, etc.)

Volume (block device)

#SyscallParametersReturnDescription
420SYS_VOLUME_READhandle: u64, offset: u64, buf_ptr: u64, buf_len: u64bytes readRead from volume
421SYS_VOLUME_WRITEhandle: u64, offset: u64, buf_ptr: u64, buf_len: u64bytes writtenWrite to volume
422SYS_VOLUME_INFOhandle: u64, out_ptr: u640Query volume info

Time

#SyscallParametersReturnDescription
500SYS_CLOCK_GETTIMEclock_id: u64, tp_ptr: u640Get clock time
501SYS_NANOSLEEPreq_ptr: u64, rem_ptr: u640Sleep for a duration
502SYS_CLOCK_NANOSLEEPclock_id: u64, flags: u64, req_ptr: u64, rem_ptr: u640Sleep on a specific clock

Clock IDs: CLOCK_REALTIME (0), CLOCK_MONOTONIC (1), CLOCK_PROCESS_CPUTIME_ID (2), CLOCK_THREAD_CPUTIME_ID (3)


Debug & miscellaneous

#SyscallParametersReturnDescription
600SYS_DEBUG_LOGmsg_ptr: u64, msg_len: u640Write a debug message to kernel log
601SYS_GETRANDOMbuf: u64, len: usize, flags: u32bytes writtenFill buffer with random bytes
610SYS_SET_ROBUST_LISThead: u64, len: usize0Set robust futex list head
611SYS_GET_ROBUST_LISTpid: i64, head_ptr: u64, len_ptr: u640Get robust futex list head

Module management

#SyscallParametersReturnDescription
700SYS_MODULE_LOADpath_ptr: u64, path_len: u64module IDLoad a kernel module
701SYS_MODULE_UNLOADmodule_id: u640Unload a kernel module
702SYS_MODULE_GET_SYMBOLmodule_id: u64, name_ptr: u64, name_len: u64symbol addressLook up a symbol in a loaded module
703SYS_MODULE_QUERYout_ptr: u64, max_count: u64module countList loaded modules

Silo management

#SyscallParametersReturnDescription
800SYS_SILO_CREATE:silo IDCreate a new silo
801SYS_SILO_CONFIGsilo_id: u64, key_ptr: u64, key_len: u64, val_ptr: u64, val_len: u640Configure a silo
802SYS_SILO_ATTACH_MODULEsilo_id: u64, module_id: u640Attach a module to a silo
803SYS_SILO_STARTsilo_id: u640Start a silo
804SYS_SILO_STOPsilo_id: u640Stop a silo
805SYS_SILO_KILLsilo_id: u640Kill a silo (force stop)
806SYS_SILO_EVENT_NEXTsilo_id: u64, out_ptr: u640Wait for next silo event
807SYS_SILO_SUSPENDsilo_id: u640Suspend a silo
808SYS_SILO_RESUMEsilo_id: u640Resume a silo
809SYS_SILO_PLEDGEpromises_ptr: u64, promises_len: u640Restrict syscalls (pledge)
810SYS_SILO_UNVEILpath_ptr: u64, path_len: u64, perms_ptr: u64, perms_len: u640Restrict filesystem access (unveil)
811SYS_SILO_ENTER_SANDBOX:0Enter sandbox mode (irreversible)
812SYS_SILO_RENAMEsilo_id: u64, name_ptr: u64, name_len: u640Rename a silo

ABI version

#SyscallParametersReturnDescription
900SYS_ABI_VERSION:(major << 16) | minorQuery ABI version

Common errno values

ValueNameDescription
1EPERMOperation not permitted
2ENOENTNo such file or directory
3ESRCHNo such process
4EINTRInterrupted system call
5EIOInput/output error
7E2BIGArgument list too long
9EBADFBad file descriptor
10ECHILDNo child processes
11EAGAINResource temporarily unavailable
12ENOMEMOut of memory
13EACCESPermission denied
14EFAULTBad address
17EEXISTFile exists
20ENOTDIRNot a directory
21EISDIRIs a directory
22EINVALInvalid argument
28ENOSPCNo space left on device
32EPIPEBroken pipe
38ENOSYSFunction not implemented
52ENOTSUPNot supported
98EADDRINUSEAddress already in use
110ETIMEDOUTConnection timed out
111ECONNREFUSEDConnection refused

Syscall Layer

The userspace syscall crate is workspace/components/syscall (strat9-syscall).

Useful entry points:

  • strat9_syscall::call for high-level wrappers
  • strat9_syscall::number for syscall constants
  • strat9_syscall::error for userspace error mapping
  • strat9_syscall::data for shared data structs

API reference:

Changelog

Project stats

Recent commits (auto-generated)

  • 2026-06-26 941a995 feat: update ABI changelog and documentation
  • 2026-06-25 4fb871f Refactor error codes and syscall flags; implement getrandom syscall
  • 2026-06-25 f0f891c docs: update published documentation
  • 2026-06-25 9b31c08 docs: update published documentation
  • 2026-06-25 a522fb8 Refactor NIC data plane and IPC transport statistics
  • 2026-06-25 23cbead docs: update published documentation
  • 2026-06-25 454a828 feat: add N2 data plane implementation with lock-free rings and enhance NIC interrupt handling
  • 2026-06-25 1f1362b docs: update published documentation
  • 2026-06-25 d1e838f feat: implement IPC transport layer with 3-level architecture
  • 2026-06-25 411f5aa feat: add IPC transport layer support and enhance ICMP handling
  • 2026-06-25 c034c91 docs: update published documentation
  • 2026-06-25 bbad275 Implement IPC transport layer with lock-free ring and intrusive mailbox
  • 2026-06-25 77b1a74 docs: add IPC architecture document (3 access levels)
  • 2026-06-25 848baaf Merge branch 'feat/input-to-userspace' into 'main'
  • 2026-06-25 5a3d69c feat: migrate input system to userspace
  • 2026-06-24 1b98905 Merge branch 'test/smp-hardware-debug' into 'main'
  • 2026-06-24 3fea3f3 SMP hardware debug, NVMe fixes, VGA refactor, telnetd hardening, docs
  • 2026-06-17 f1bccb9 Merge branch 'fix/typed-irq-guard-allocator' into 'main'
  • 2026-06-17 b1d7c35 buddy: use PreemptDisabled guardian on per-CPU frame caches (#37)
  • 2026-06-17 1ca93d1 Merge branch 'fix/tech-debt-allocation-under-lock' into 'main'
  • 2026-06-17 78e18ce Tech debt: allocation-under-lock and global-lock patterns (#50)
  • 2026-06-16 6455a23 Merge branch 'fix/irq-token-encapsulation' into 'main'
  • 2026-06-16 cb4ce4d Refactor: document IrqDisabledToken creation paths and encapsulation
  • 2026-06-16 bdec79d Merge branch 'fix/arc-strong-count-wording' into 'main'
  • 2026-06-16 c642da4 Fix: refine Arc::strong_count diagnostic wording to heuristic
  • 2026-06-16 f85e757 Merge branch 'feat/spinlock-multi-watch-debug' into 'main'
  • 2026-06-16 3fec849 Feat: replace single-lock trace with fixed-size multi-watch array
  • 2026-06-16 84db9df Merge branch 'fix/slab-refill-irq-assert' into 'main'
  • 2026-06-16 021fb49 Fix: add debug_assert IRQ-disabled invariant on slab refill
  • 2026-06-16 8ebf658 Merge branch 'fix/heap-page-count-overflow' into 'main'
  • 2026-06-16 d1f7eef Fix: use saturating arithmetic for vmalloc page count rounding
  • 2026-06-16 99d4ede Merge branch 'fix/reparent-children-deterministic' into 'main'
  • 2026-06-16 dcc239c Fix: make orphan reparenting deterministic by dropping links when PID 1 absent
  • 2026-06-16 d2722ee Merge branch 'fix/legacy-pic-timer-parity' into 'main'
  • 2026-06-16 e53a4b6 Fix: mirror LAPIC timer Ring-3 preemption policy in legacy PIC handler
  • 2026-06-16 257b694 Merge branch 'fix/buddy-free-to-zone-logging' into 'main'
  • 2026-06-16 18b1037 Fix: escalate free_to_zone protected-overlap to panic matching alloc side
  • 2026-06-16 28bbc90 Merge branch 'fix/keyboard-lost-key-counter' into 'main'
  • 2026-06-16 b19d6bf Fix keyboard driver: shared state, US extended keys, numpad, lost-key counter
  • 2026-06-16 93302a5 docs: update published documentation
  • 2026-06-16 b2edb49 Merge branch 'enhance-network-tools' into 'main'
  • 2026-06-16 e4ab1a9 Enhance network stack, NIC drivers, USB/NVMe subsystems, and thermal management
  • 2026-06-03 5ee7f8d Merge branch 'fix-some-mistake-in-network-stack' into 'main'
  • 2026-06-03 0c40058 Refactor the network stack and add dual-stack userspace tooling
  • 2026-05-24 aeade5e Code cleanup
  • 2026-05-24 86c810e Raüs silo sshd
  • 2026-05-24 40d4d46 Merge branch 'IPC-refactor' into 'main'
  • 2026-05-24 b2bbcc0 Improve and fix IPC
  • 2026-05-23 b7c3e27 Merge branch 'hunt-memory-corruption' into 'main'
  • 2026-05-23 db23b53 Fix major memory leak and remove sshd silo

Publishing

One-command publication script

At repository root:

./publish-doc.sh

This script:

  1. builds docs (cargo make docs-site)
  2. regenerates ABI changelog auto section from git history
  3. commits/pushes current branch changes
  4. uploads built website to the remote vhost via SSH

The docs builder publishes:

  1. mdBook pages under docs-site/
  2. rustdoc for all workspace crates (cargo doc --workspace --no-deps)
  3. a combined static site in build/docs-site