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
Architecture guides
| Guide | Description |
|---|---|
| Architecture Overview | Kernel subsystems, design principles, and data flow diagrams |
| Silo System | Process isolation, resource limits, pledge/unveil, module loading |
| Memory Management | Buddy allocator, slab heap, COW, page tables, vmalloc |
| Boot Sequence | BIOS → bootloader → Limine → kernel init flow |
| IPC Mechanisms | Channels, shared rings, semaphores, futexes |
| IPC Transport Architecture | 3-level hybrid IPC model (TypeSafe / LockFree / MMU) |
| Driver Model | Component trait, PCI, NIC, storage, USB drivers |
| Syscall Reference | Complete syscall table with parameters and errors |
| ABI Overview | Kernel/userspace ABI definitions and versioning |
| ABI Changelog | Recent ABI changes (auto-generated) |
| ABI Support Matrix | Syscall and struct compatibility matrix |
| Syscall Layer | Userspace syscall wrappers and error handling |
| Changelog | Project changelog (auto-generated from git) |
| Publishing | Build, release, and deployment instructions |
API reference by category
Core
The kernel, ABI definitions, and bootloader : the foundation of the OS.
| Crate | Description | API |
|---|---|---|
| strat9-kernel | OS kernel: scheduler, memory management, drivers, IPC | docs · source |
| strat9-abi | ABI definitions shared between kernel and userspace (syscalls, data structs, flags, errno) | docs · source |
| strat9-bootloader | BIOS/UEFI bootloader: stage1 MBR, stage2 protected/long mode switch | docs · source |
Syscall & Userspace
Userspace libraries for interacting with the kernel.
| Crate | Description | API |
|---|---|---|
| strat9-syscall | High-level syscall wrappers, error mapping, and constants | docs · source |
| strate-init | Init process: system bootstrap and service management | docs · source |
Component Framework
Trait-based component model for drivers and services.
| Crate | Description | API |
|---|---|---|
| component | Component trait and registration framework | docs · source |
| component-macro | Derive macros for component registration | docs · source |
| strat9-bus-drivers | Bus driver infrastructure (PCI, VirtIO) | docs · source |
| strate-bus | Bus abstraction layer | docs · source |
Network Drivers
Intel Ethernet and NIC queue management.
| Crate | Description | API |
|---|---|---|
| e1000 | Intel E1000/E1000e network driver | docs · source |
| intel-ethernet | Intel Ethernet common register definitions | docs · source |
| driver-net-proto | Network protocol driver abstractions | docs · source |
| nic-queues | NIC TX/RX queue management | docs · source |
| nic-buffers | NIC buffer allocation and management | docs · source |
| net-core | Network core utilities | docs · source |
Filesystem
Filesystem abstraction and implementations.
| Crate | Description | API |
|---|---|---|
| strate-fs-abstraction | Filesystem abstraction layer with safe math and Unicode | docs · source |
| strate-fs-ext4 | ext4 filesystem implementation | docs · source |
| strate-fs-ramfs | In-memory RAM filesystem | docs · source |
Networking
Network stack, silo network service, and tools.
| Crate | Description | API |
|---|---|---|
| strate-net | Network stack (TCP/UDP/ICMP) | docs · source |
| strate-net-silo | Network silo service (TCP/UDP listener) | docs · source |
| dhcp-client | DHCP client status monitor | docs · source |
| ping | ICMP ping utility | docs · source |
| udp-tool | UDP scheme test utility | docs · source |
| telnetd | Telnet server | docs · source |
| ice-candidate | ICE candidate discovery over scheme UDP | docs · source |
System Services
Admin interfaces, compatibility layers, and experimental features.
| Crate | Description | API |
|---|---|---|
| strat9-components-api | Shared component API types and traits | docs · source |
| strate-console-admin | Interactive console shell with silo management | docs · source |
| strate-web-admin | Web-based admin interface | docs · source |
| strate-wasm | WebAssembly runtime support | docs · source |
| strate-webrtc | WebRTC support | docs · source |
| musl-compat | musl libc compatibility layer | docs · source |
| alloc-freelist | Free-list allocator | docs · source |
Testing
| Crate | Description | API |
|---|---|---|
| silo-test | Silo integration tests | source |
| mem-test | Memory subsystem tests | docs · source |
| test-syscalls | Syscall integration tests | docs · source |
| test-exec | Exec syscall tests | docs · 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
| Subsystem | Module | Purpose |
|---|---|---|
| Boot | boot/ | Assembly stubs (16→64 bit), Limine handoff, early init |
| Scheduler | process/scheduler/ | Per-CPU run queues, multi-class scheduling (RT FIFO/RR, Normal, Idle) |
| Memory | memory/ | Buddy allocator, slab heap, COW, page tables, vmalloc |
| IPC | ipc/ | 3-level Transport Manager (TypeSafe/LockFree/MMU), typed channels, shared rings, semaphores |
| Capability | capability.rs | Unforgeable tokens, per-resource refcounting |
| Silo | silo/ | Process isolation containers with resource quotas |
| VFS | vfs/ | Virtual filesystem with scheme-based I/O |
| Syscall | syscall/ | Syscall dispatch and validation |
| Drivers | hardware/ | NIC, storage, USB, GPU, VirtIO, PCI |
Design principles
-
Capability-based security : All kernel resources (memory, IPC ports, devices) are accessed through unforgeable
CapIdtokens. No raw pointers leak to userspace. -
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.
-
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.
-
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. -
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 range | Tier | Purpose |
|---|---|---|
| 1–9 | Critical | Kernel system services (init, logger) |
| 10–999 | System | Drivers, filesystems, network |
| 1000+ | User | User 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:
| Bits | Group | Permissions |
|---|---|---|
| 8–10 | Control | LIST (0b100), STOP (0b010), SPAWN (0b001) |
| 5–7 | Hardware | INTERRUPT (0b100), IO (0b010), DMA (0b001) |
| 2–4 | Registry | LOOKUP (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
| Family | Value | Purpose |
|---|---|---|
SYS | 0 | System services (init, admin) |
DRV | 1 | Hardware drivers |
FS | 2 | Filesystem handlers |
NET | 3 | Network stack |
WASM | 4 | WebAssembly runtime |
USR | 5 | User applications |
Feature flags
| Flag | Value | Description |
|---|---|---|
SILO_FLAG_ADMIN | 1 << 0 | Silo has admin capabilities |
SILO_FLAG_GRAPHICS | 1 << 1 | Graphics session support |
SILO_FLAG_WEBRTC_NATIVE | 1 << 2 | WebRTC native support (requires GRAPHICS) |
SILO_FLAG_GRAPHICS_READ_ONLY | 1 << 3 | Graphics read-only mode |
SILO_FLAG_WEBRTC_TURN_FORCE | 1 << 4 | Force 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:
- Admin calls
SYS_MODULE_LOADwith a blob (from file, IPC stream, or initfs path) - Kernel validates the header (magic, version, alignment, signature)
- Module is registered in the global
ModuleRegistry - Admin calls
SYS_SILO_ATTACH_MODULEto bind the module to a silo - Admin calls
SYS_SILO_STARTto 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.
| Event | Trigger |
|---|---|
Started | Silo started or config updated |
Stopped | Graceful stop |
Killed | Force kill |
Crashed | Fault/panic (data0 encodes fault reason + subcode) |
Paused | Suspended |
Resumed | Resumed 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:
| Operation | Function | Description |
|---|---|---|
| Create | kernel_spawn_strate() | Register module, create silo, spawn task |
| Start | kernel_start_silo() | Transitions Ready → Running |
| Stop | kernel_stop_silo() | Graceful stop (tasks exit) |
| Kill | kernel_stop_silo(force=true) | Force kill all tasks |
| Destroy | kernel_destroy_silo() | Remove silo (must be stopped) |
| Rename | kernel_rename_silo_label() | Change silo label |
| Pledge | sys_silo_pledge() | Restrict permissions |
| Unveil | sys_silo_unveil() | Restrict filesystem access |
| Sandbox | sys_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
| Mechanism | Scope | Enforcement |
|---|---|---|
| Silo | Process group + resources + capabilities | Kernel (SiloManager) |
| Capability | Individual resource access | Kernel (CapabilityManager) |
| Pledge | Syscall permission subset | Kernel (OctalMode) |
| Unveil | Filesystem path access | Kernel (UnveilRules) |
| Sandbox | Full 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 size | Typical use |
|---|---|
| 16 B | Small structs, list nodes |
| 32 B | Capability entries |
| 64 B | IPC message headers |
| 128 B | Task control blocks |
| 256 B | VMA entries |
| 512 B | Pathname buffers |
| 1024 B | Syscall argument buffers |
| 2048 B | Large 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).
| Level | Covers | Entry size |
|---|---|---|
| PML4 | 512 GiB | 8 bytes |
| PDPT | 1 GiB | 8 bytes |
| PD | 2 MiB (huge) | 8 bytes |
| PT | 4 KiB | 8 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:
- Load Stage 2 from disk (LBA reads via BIOS INT 13h)
- Enable A20 line
- Enter protected mode (32-bit)
- Jump to Stage 2
Stage 2 : Protected → Long mode
Responsibilities:
- Detect available memory (INT 15h, E820)
- Load the kernel binary from disk
- Set up initial page tables (identity mapping + higher-half)
- Enable PAE, PGE, long mode
- 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:
- Verify BSS is zero, data is non-zero (sanity check)
- Set up kernel stack (128 KiB, from
STACKstatic) - Jump to
start()(Rust)
Kernel init : start() (Rust)
Located in boot/limine.rs → main.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:
| Step | Module | What happens |
|---|---|---|
| Serial | serial.rs | Initialize COM1 (0x3F8) at 115200 baud |
| GDT | gdt.rs | Set up kernel/user code/data segments |
| IDT | idt.rs | Install interrupt handlers (timer, syscall, page fault) |
| Memory | memory/ | Parse E820, initialize buddy allocator |
| Paging | paging.rs | Set up kernel page tables (HHDM + higher-half) |
| Syscall | syscall.rs | Install syscall/sysret MSRs |
| Heap | heap.rs | Initialize slab allocator on top of buddy |
| ACPI | acpi/ | Parse MADT (APICs), IOAPIC, interrupt overrides |
| APIC | apic.rs | Initialize Local APIC (xAPIC or x2APIC) |
| SMP | smp.rs | INIT+SIPI sequence to boot Application Processors |
| Timer | timer.rs | Calibrate and start APIC timer (periodic) |
| Scheduler | scheduler/ | Create per-CPU run queues, spawn idle tasks |
| Init | shell/ | 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 \ Dest | Critical | System | User |
|---|---|---|---|
| Critical | N1 (TypeSafe) | N1 (TypeSafe) | N2 (LockFree) |
| System | N1 (TypeSafe) | N2 (LockFree) | N2 (LockFree) |
| User | N2 (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
| Mode | Latency | Use case |
|---|---|---|
| N2a (busy-poll) | approx. 400 cycles | Hot path, low-latency |
| N2b (futex sleep) | approx. 1000-4000 cycles | Background 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:
| Tier | Mechanism | Cost | Condition |
|---|---|---|---|
| N3a | Same-core handoff | approx. 200-400c | Same core, mappings valid |
| N3b | PCID-preserving CR3 | approx. 400-800c | PCID active, prefaulted |
| N3c | Full migration | approx. 800-2000c | First 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)
| Syscall | Description |
|---|---|
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_CREATE | 240 | Create a transport |
SYS_TRANSPORT_SEND | 241 | Send a message |
SYS_TRANSPORT_RECV | 242 | Receive a message |
SYS_TRANSPORT_CLOSE | 243 | Close transport |
SYS_TRANSPORT_INFO | 244 | Get transport info |
Performance comparison
| Mechanism | Round-trip 64B | CPU usage/pkt | Isolation |
|---|---|---|---|
| Legacy IPC (syscall) | approx. 4000 cycles | approx. 2% | MMU |
| N1 TypeSafe | approx. 6-20 cycles | approx. 0.01% | Rust types |
| N2 LockFree (busy) | approx. 400-800 cycles | approx. 0.1% | MMU |
| N2 LockFree (futex) | approx. 1000-4000 cycles | approx. 0.2% | MMU |
| N3 MMU (research) | approx. 800-2000 cycles | approx. 0.5% | MMU (max) |
References
- Xu, P. & Roscoe, T. (2025) : The NIC should be part of the OS, HotOS'25 : arXiv
- Liedtke, J. (1995) : On µ-Kernel Construction, SOSP
- Hunt, G.C. & Larus, J.R. (2007) : Singularity: Rethinking the Software Stack, ACM Queue
- Levy, A. et al. (2017) : Multiprogramming a 64kB Computer Safely and Efficiently with Tock, SOSP
- Vyukov, D. : Bounded MPMC queue : lock-free SPSC/MPMC benchmarks
- 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:
- For each (bus, device), probe function 0 first
- If vendor == 0xFFFF → skip all 8 functions (early exit)
- Read header type bit 7 for multi-function flag
- 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:
| Type | Description |
|---|---|
PciAddress | Bus/device/function address |
PciDevice | Device info (vendor, class, BARs, IRQ) |
ProbeCriteria | Filter 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
| Module | Purpose |
|---|---|
nic-queues | TX/RX queue management, descriptor ring abstraction |
nic-buffers | Buffer allocation, DMA-safe memory |
net-core | Packet parsing, protocol headers |
driver-net-proto | Protocol 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:
| Device | Module | Purpose |
|---|---|---|
| VirtIO Block | virtio/block | Block I/O |
| VirtIO Net | virtio/net | Network |
| VirtIO Console | virtio/console | Serial console |
| VirtIO GPU | virtio/gpu | Display |
| VirtIO Input | virtio/input | Keyboard/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::syscallfor syscall numbersstrat9_abi::datafor shared wire/data structsstrat9_abi::flagfor ABI-level flagsstrat9_abi::errnofor error codesstrat9_abi::bootfor 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 = 0ABI_VERSION_MINOR = 1- Packed:
0.1
See:
Recent ABI updates (auto-generated)
- 2026-06-25
4fb871fRefactor error codes and syscall flags; implement getrandom syscall - 2026-06-25
a522fb8Refactor NIC data plane and IPC transport statistics - 2026-06-25
d1e838ffeat: implement IPC transport layer with 3-level architecture - 2026-06-25
411f5aafeat: add IPC transport layer support and enhance ICMP handling - 2026-06-25
5a3d69cfeat: migrate input system to userspace - 2026-06-24
3fea3f3SMP hardware debug, NVMe fixes, VGA refactor, telnetd hardening, docs - 2026-06-16
e4ab1a9Enhance network stack, NIC drivers, USB/NVMe subsystems, and thermal management - 2026-06-03
0c40058Refactor the network stack and add dual-stack userspace tooling - 2026-05-24
aeade5eCode cleanup - 2026-05-24
b2bbcc0Improve and fix IPC - 2026-05-23
db23b53Fix major memory leak and remove sshd silo - 2026-05-19
93c8927async: implement and optimize async I/O completion handling - 2026-05-18
7c5efb4async: io_uring-like async I/O — ring, dispatch, AHCI bridge (Phases 1-4) - 2026-05-14
cc4944aRefactor and clean up code in various modules - 2026-05-14
ecc416drefactor: strate-init refactoring, ELF/VFS/signal hardening, TSC calibration fix - 2026-05-08
f070d41Add kernel entropy pool with interrupt-driven collection - 2026-05-08
9dedb9fImplement robust list support (set_robust_list/get_robust_list) - 2026-05-08
d2e90a2Bridge clone() thread creation via SYS_THREAD_CREATE, add faccessat routing - 2026-05-08
dabcad2Add sys_access(), sys_faccessat(), and SYS_GETRANDOM() in syscall dispatcher - 2026-05-08
946f200Add missing call for clock_nanosleep and update the calling manager - 2026-05-06
117863eEnhance network and silo management functionality - 2026-04-12
6963e28fix: reduce scheduler contention and harden early boot memory init - 2026-04-12
f3647c1feat(memory): production-grade allocator architecture (#49) - 2026-04-06
a941264feat: capability-based CWD, *at syscalls, and O_RESOLVE_BENEATH sandboxing - 2026-04-06
309a9c1refactor: runtime allocation, scheduler lock decoupling, FixedQueue, and VGA improvements - 2026-03-26
a9a6cd6Implement block-oriented memory management and ownership tracking - 2026-03-23
ec8ee9frefactor(memory): update reference counting logic for COW frames - 2026-03-23
aaa89e0Refactor: Decouple per-CPU scheduler state and logic from the global scheduler instance by movingSchedulerCputo local CPU storage. - 2026-03-21
c3f93c6feat: Implement TSC-based boot timing and milestones, along with an analysis... - 2026-03-17
eb7818dfeat: Implement static module loading from initfs paths and increase module blob size limit.
Changelog entries
0.1
- Introduced canonical
strat9-abicrate 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
| API | Status | Notes |
|---|---|---|
| open / openat | OK | Via SYS_OPEN |
| read | OK | Via SYS_READ |
| write | OK | Via SYS_WRITE |
| close | OK | Via SYS_CLOSE |
| lseek | OK | Via SYS_LSEEK |
| pread | OK | Via SYS_PREAD |
| pwrite | OK | Via SYS_PWRITE |
| fstat / fstatat | OK | Via SYS_FSTAT / SYS_STAT |
| dup / dup2 | OK | Via SYS_DUP / SYS_DUP2 |
| pipe / pipe2 | OK | Via SYS_PIPE |
| fcntl | OK | Via SYS_FCNTL |
| mkdir / mkdirat | OK | Via SYS_MKDIR |
| unlink | OK | Via SYS_UNLINK |
| rmdir | OK | Via SYS_RMDIR |
| rename / renameat | OK | Via SYS_RENAME |
| link | OK | Via SYS_LINK |
| symlink | OK | Via SYS_SYMLINK |
| readlink | OK | Via SYS_READLINK |
| chmod / fchmod | OK | Via SYS_CHMOD / SYS_FCHMOD |
| truncate / ftruncate | OK | Via SYS_TRUNCATE / SYS_FTRUNCATE |
| chdir / fchdir | OK | Via SYS_CHDIR / SYS_FCHDIR |
| getcwd | OK | Via SYS_GETCWD |
| getdents | OK | Via SYS_GETDENTS |
| access | OK | Open + close probe |
| umask | OK | Via SYS_UMASK |
| fsync / fdatasync | Stub | ENOSYS |
| flock | Stub | ENOSYS |
| chown / fchown / lchown | Stub | ENOSYS |
| statvfs / fstatvfs | Stub | ENOSYS |
| mknod / mknodat / mkfifoat | Stub | ENOSYS |
Process Management
| API | Status | Notes |
|---|---|---|
| exit | OK | Via SYS_PROC_EXIT |
| fork | OK | Via SYS_PROC_FORK |
| execve | OK | Via SYS_PROC_EXEC |
| waitpid | OK | Via SYS_PROC_WAITPID |
| getpid / getppid / gettid | OK | |
| setsid / setpgid / getpgid / getsid | OK | |
| sched_yield | OK | Via SYS_PROC_YIELD |
| nanosleep | OK | Via SYS_NANOSLEEP |
| clock_gettime | OK | Via SYS_CLOCK_GETTIME |
| brk | OK | Via SYS_BRK |
| mmap / munmap | OK | Via SYS_MMAP / SYS_MUNMAP |
| uname | OK | Via SYS_PROC_UNAME |
| getuid / geteuid / getgid / getegid | Partial | Returns 0 (no UID model) |
| mprotect / mlock / munlock | Stub | ENOSYS |
| getrandom | OK | Via SYS_GETRANDOM (601), supports GRND_NONBLOCK |
Signals
| API | Status | Notes |
|---|---|---|
| kill | OK | Via SYS_KILL |
| sigaction | OK | Via SYS_SIGACTION |
| sigprocmask | OK | Via SYS_SIGPROCMASK |
| sigsuspend | OK | Via SYS_SIGSUSPEND |
| sigtimedwait | OK | Via SYS_SIGTIMEDWAIT |
| getitimer / setitimer | OK | Via SYS_GETITIMER / SYS_SETITIMER |
| sigaltstack | OK | Via SYS_SIGALTSTACK |
Network / Sockets
| API | Status | Notes |
|---|---|---|
| socketpair (AF_UNIX) | Partial | Backed by pipe (unidirectional) |
| recvfrom / sendto | Partial | Delegates to read/write |
| socket / bind / listen / accept / connect | Stub | ENOSYS |
| setsockopt / getsockopt | Stub | ENOSYS |
| shutdown | Stub | ENOSYS |
Epoll
| API | Status | Notes |
|---|---|---|
| epoll_create1 | Partial | Backed by pipe fd |
| epoll_ctl | Stub | No-op |
| epoll_pwait | Partial | Sleeps, 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)
| Constant | Value | Description |
|---|---|---|
AT_FDCWD | -100 | Use the process's current working directory as the base directory |
AT_REMOVEDIR | 0x200 | Remove a directory (for SYS_UNLINKAT) |
AT_SYMLINK_NOFOLLOW | 0x100 | Do not follow symbolic links (for SYS_FSTATAT) |
AT_EMPTY_PATH | 0x1000 | Operate on the fd itself when path is empty |
Open flags
| Flag | Value | Description |
|---|---|---|
O_RDONLY | 0 | Open for reading |
O_WRONLY | 1 | Open for writing |
O_RDWR | 2 | Open for reading and writing |
O_CREAT | 0x40 | Create file if it does not exist |
O_EXCL | 0x800 | Fail if file already exists (with O_CREAT) |
O_TRUNC | 0x200 | Truncate file to zero length |
O_APPEND | 0x400 | Append to end of file |
O_NONBLOCK | 0x800 | Non-blocking mode |
O_DIRECTORY | 0x10000 | Open as directory |
O_NOFOLLOW | 0x20000 | Do not follow symlinks |
Protection flags (mmap)
| Flag | Value | Description |
|---|---|---|
PROT_READ | 1 | Page can be read |
PROT_WRITE | 2 | Page can be written |
PROT_EXEC | 4 | Page can be executed |
Signal constants
| Constant | Value | Description |
|---|---|---|
SIG_DFL | 0 | Default signal handling |
SIG_IGN | 1 | Ignore signal |
SIG_BLOCK | 0 | Block signals in set |
SIG_UNBLOCK | 1 | Unblock signals in set |
SIG_SETMASK | 2 | Set signal mask to set |
Waitpid options
| Flag | Value | Description |
|---|---|---|
WNOHANG | 1 | Return immediately if no child has exited |
WUNTRACED | 2 | Also return for stopped children |
WCONTINUED | 4 | Also return for continued children |
Clock IDs
| Constant | Value | Description |
|---|---|---|
CLOCK_REALTIME | 0 | System-wide real-time clock |
CLOCK_MONOTONIC | 1 | Monotonic clock (not affected by adjustments) |
CLOCK_PROCESS_CPUTIME_ID | 2 | Per-process CPU time |
CLOCK_THREAD_CPUTIME_ID | 3 | Per-thread CPU time |
Handle operations
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 0 | SYS_NULL | : | 0 | No-op (used for benchmarking) |
| 1 | SYS_HANDLE_DUPLICATE | handle: u64 | new handle | Duplicate a capability handle |
| 2 | SYS_HANDLE_CLOSE | handle: u64 | 0 | Close a capability handle |
| 3 | SYS_HANDLE_WAIT | handle: u64, timeout_ns: u64 | 0 | Wait on a handle (blocks until ready or timeout) |
| 4 | SYS_HANDLE_GRANT | handle: u64, target_pid: u64 | 0 | Grant a capability to another process |
| 5 | SYS_HANDLE_REVOKE | handle: u64 | 0 | Revoke a capability (all holders lose access) |
| 6 | SYS_HANDLE_INFO | handle: u64, out_ptr: u64 | 0 | Query capability info (writes HandleInfo struct) |
Errors: EBADF (invalid handle), EPERM (no grant permission), ESRCH (target process not found)
Memory management
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 100 | SYS_MMAP | addr: u64, len: u64, prot: u64, flags: u64, fd: u64, offset: u64 | mapped address | Map a memory region |
| 101 | SYS_MUNMAP | addr: u64, len: u64 | 0 | Unmap a memory region |
| 102 | SYS_BRK | addr: u64 | new break | Set/clear the data break |
| 103 | SYS_MREMAP | old_addr: u64, old_len: u64, new_len: u64, flags: u64, new_addr: u64 | new address | Remap a memory region |
| 104 | SYS_MPROTECT | addr: u64, len: u64, prot: u64 | 0 | Change memory protection flags |
| 105 | SYS_MEM_REGION_EXPORT | addr: u64, len: u64 | region handle | Export a memory region as a shareable handle |
| 106 | SYS_MEM_REGION_MAP | region_handle: u64, addr: u64, len: u64 | mapped address | Map an exported memory region |
| 107 | SYS_MEM_REGION_INFO | region_handle: u64, out_ptr: u64 | 0 | Query 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
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 200 | SYS_IPC_CREATE_PORT | : | port handle | Create a new IPC port |
| 201 | SYS_IPC_SEND | port_handle: u64, msg_ptr: u64, msg_len: u64 | 0 | Send a message to a port |
| 202 | SYS_IPC_RECV | port_handle: u64, buf_ptr: u64, buf_len: u64 | bytes received | Receive a message (blocks) |
| 203 | SYS_IPC_CALL | port_handle: u64, msg_ptr: u64, msg_len: u64 | bytes received | Synchronous RPC (send + wait for reply) |
| 204 | SYS_IPC_REPLY | msg_ptr: u64, msg_len: u64 | 0 | Reply to the current IPC call |
| 205 | SYS_IPC_BIND_PORT | port_handle: u64 | 0 | Bind a port as a listener |
| 206 | SYS_IPC_UNBIND_PORT | port_handle: u64 | 0 | Unbind a listening port |
| 207 | SYS_IPC_TRY_RECV | port_handle: u64, buf_ptr: u64, buf_len: u64 | bytes received (0 if empty) | Non-blocking receive |
| 208 | SYS_IPC_CONNECT | port_handle: u64 | 0 | Connect to a bound port |
| 210 | SYS_IPC_RING_CREATE | size_log2: u64 | ring handle | Create a shared ring buffer |
| 211 | SYS_IPC_RING_MAP | ring_handle: u64, addr: u64 | 0 | Map 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)
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 220 | SYS_CHAN_CREATE | capacity: u64 | channel handle | Create a typed channel |
| 221 | SYS_CHAN_SEND | handle: u64, msg_ptr: u64 | 0 | Send a message (blocks if full) |
| 222 | SYS_CHAN_RECV | handle: u64, msg_ptr: u64 | 0 | Receive a message (blocks if empty) |
| 223 | SYS_CHAN_TRY_RECV | handle: u64, msg_ptr: u64 | 1 if received, 0 if empty | Non-blocking receive |
| 224 | SYS_CHAN_CLOSE | handle: u64 | 0 | Close channel handle |
Errors: EBADF (invalid handle), EPIPE (all endpoints disconnected), EAGAIN (try_recv on empty channel)
IPC : Semaphores
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 230 | SYS_SEM_CREATE | initial_value: u64 | semaphore handle | Create a counting semaphore |
| 231 | SYS_SEM_WAIT | handle: u64 | 0 | Decrement (blocks if zero) |
| 232 | SYS_SEM_TRYWAIT | handle: u64 | 1 if acquired, 0 if would block | Non-blocking decrement |
| 233 | SYS_SEM_POST | handle: u64 | 0 | Increment (wake a waiter) |
| 234 | SYS_SEM_CLOSE | handle: u64 | 0 | Close semaphore handle |
Errors: EBADF (invalid handle), EAGAIN (try_wait on zero semaphore)
PCI
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 240 | SYS_PCI_ENUM | criteria_ptr: u64, out_ptr: u64, max_count: u64 | device count | Enumerate PCI devices matching criteria |
| 241 | SYS_PCI_CFG_READ | addr_ptr: u64, offset: u64, width: u64 | config value | Read PCI configuration register |
| 242 | SYS_PCI_CFG_WRITE | addr_ptr: u64, offset: u64, width: u64, value: u64 | 0 | Write PCI configuration register |
Errors: EINVAL (invalid width/offset), EACCES (no PCI capability)
Async I/O
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 250 | SYS_ASYNC_SETUP | handle: u64, event_mask: u64 | async context | Set up async notification on a handle |
| 251 | SYS_ASYNC_ENTER | ctx: u64 | 0 | Enter async wait (yields until event) |
| 252 | SYS_ASYNC_CANCEL | ctx: u64 | 0 | Cancel pending async wait |
| 253 | SYS_ASYNC_MAP | ctx: u64, ring_handle: u64 | 0 | Map an event ring to the async context |
| 254 | SYS_ASYNC_DESTROY | ctx: u64 | 0 | Destroy async context |
Process management
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 300 | SYS_PROC_EXIT | exit_code: u64 | : (never returns) | Terminate current process |
| 301 | SYS_PROC_YIELD | : | 0 | Yield CPU to scheduler |
| 302 | SYS_PROC_FORK | frame: &SyscallFrame | child PID (parent), 0 (child) | Fork the current process (COW) |
| 308 | SYS_PROC_GETPID | : | process ID | Get current process ID |
| 309 | SYS_PROC_GETPPID | : | parent PID | Get parent process ID |
| 310 | SYS_PROC_WAITPID | pid: i64, status_ptr: u64, options: u64 | child PID | Wait for a child process |
| 311 | SYS_GETPID | : | process ID | Alias for SYS_PROC_GETPID |
| 312 | SYS_GETTID | : | thread ID | Get current thread ID |
| 314 | SYS_PROC_WAIT | : | : | Wait for any child |
| 315 | SYS_PROC_EXECVE | path_ptr: u64, path_len: u64, argv_ptr: u64, envp_ptr: u64 | : (replaces image) | Execute a new program |
| 341 | SYS_THREAD_CREATE | entry: u64, stack: u64, arg: u64 | thread ID | Create a new thread |
| 342 | SYS_THREAD_JOIN | tid: u64, status_ptr: u64 | 0 | Wait for thread to exit |
| 343 | SYS_THREAD_EXIT | status: u64 | : (never returns) | Terminate current thread |
Errors: ECHILD (no child processes), EAGAIN (thread creation failed), ENOMEM (out of memory)
Futex
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 303 | SYS_FUTEX_WAIT | addr: u64, val: u32, timeout_ns: u64 | 0 | Sleep if *addr == val |
| 304 | SYS_FUTEX_WAKE | addr: u64, max_wake: u32 | woken count | Wake up to N waiters |
| 305 | SYS_FUTEX_REQUEUE | addr: u64, max_wake: u32, addr2: u64, max_requeue: u32 | woken count | Wake + requeue to addr2 |
| 306 | SYS_FUTEX_CMP_REQUEUE | addr: u64, max_wake: u32, addr2: u64, max_requeue: u32, cmp_val: u32 | woken count | Conditional requeue |
| 307 | SYS_FUTEX_WAKE_OP | addr: u64, max_wake: u32, addr2: u64, max_requeue: u32, wake_op: u32 | woken count | Atomic op + wake |
Errors: EAGAIN (value mismatch in WAIT), ETIMEDOUT (timeout expired), EFAULT (invalid address)
Signals
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 320 | SYS_KILL | pid: i64, signum: u32 | 0 | Send signal to a process |
| 321 | SYS_SIGPROCMASK | how: i32, set_ptr: u64, oldset_ptr: u64 | 0 | Get/set signal mask |
| 322 | SYS_SIGACTION | signum: u64, act_ptr: u64, oact_ptr: u64 | 0 | Set signal handler |
| 323 | SYS_SIGALTSTACK | ss_ptr: u64, old_ss_ptr: u64 | 0 | Set alternate signal stack |
| 324 | SYS_SIGPENDING | set_ptr: u64 | 0 | Get pending signals |
| 325 | SYS_SIGSUSPEND | mask_ptr: u64 | : (restarted on signal) | Suspend until signal |
| 326 | SYS_SIGTIMEDWAIT | set_ptr: u64, info_ptr: u64, timeout_ptr: u64 | signal number | Wait for specific signal |
| 327 | SYS_SIGQUEUE | pid: i64, signum: u32, sigval_ptr: u64 | 0 | Queue a signal with data |
| 328 | SYS_KILLPG | pgrp: u64, signum: u32 | 0 | Send signal to process group |
| 352 | SYS_TGKILL | tgid: u64, tid: u64, signum: u32 | 0 | Send signal to specific thread |
| 353 | SYS_RT_SIGRETURN | : | : | Return from signal handler |
Process groups & sessions
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 316 | SYS_FCNTL | fd: u64, cmd: u64, arg: u64 | depends on cmd | File control operations |
| 317 | SYS_SETPGID | pid: u64, pgid: u64 | 0 | Set process group ID |
| 318 | SYS_GETPGID | pid: u64 | pgid | Get process group ID |
| 319 | SYS_SETSID | : | session ID | Create new session |
| 329 | SYS_GETITIMER | which: u64, out_ptr: u64 | 0 | Get interval timer |
| 330 | SYS_SETITIMER | which: u64, in_ptr: u64, out_ptr: u64 | 0 | Set interval timer |
| 331 | SYS_GETPGRP | : | pgrp | Get current process group |
| 332 | SYS_GETSID | pid: u64 | sid | Get session ID |
| 333 | SYS_SET_TID_ADDRESS | tidptr: u64 | 0 | Set clear-on-exit TID address |
| 334 | SYS_EXIT_GROUP | exit_code: u64 | : (never returns) | Exit all threads in process |
User/group IDs
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 335 | SYS_GETUID | : | uid | Get real user ID |
| 336 | SYS_GETEUID | : | euid | Get effective user ID |
| 337 | SYS_GETGID | : | gid | Get real group ID |
| 338 | SYS_GETEGID | : | egid | Get effective group ID |
| 339 | SYS_SETUID | uid: u64 | 0 | Set user ID |
| 340 | SYS_SETGID | gid: u64 | 0 | Set group ID |
Misc process
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 344 | SYS_UNAME | uts_ptr: u64 | 0 | Get system information (name, release, etc.) |
| 350 | SYS_ARCH_PRCTL | code: u64, addr: u64 | 0 | Architecture-specific process control |
File I/O
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 403 | SYS_OPEN | path_ptr: u64, path_len: u64, flags: u64 | file descriptor | Open a file |
| 404 | SYS_WRITE | fd: u64, buf_ptr: u64, buf_len: u64 | bytes written | Write to a file descriptor |
| 405 | SYS_READ | fd: u64, buf_ptr: u64, buf_len: u64 | bytes read | Read from a file descriptor |
| 406 | SYS_CLOSE | fd: u64 | 0 | Close a file descriptor |
| 407 | SYS_LSEEK | fd: u64, offset: u64, whence: u64 | new position | Seek in a file |
| 408 | SYS_FSTAT | fd: u64, stat_ptr: u64 | 0 | Get file status (fstat) |
| 409 | SYS_STAT | path_ptr: u64, path_len: u64, stat_ptr: u64 | 0 | Get file status by path |
| 413 | SYS_ACCESS | path_ptr: u64, path_len: u64, mode: u64 | 0 | Check file accessibility (uses effective UID/GID, not real). Prefer SYS_FACCESSAT for new code. |
| 430 | SYS_GETDENTS | fd: u64, buf_ptr: u64, buf_len: u64 | bytes read | Read directory entries |
| 431 | SYS_PIPE | fds_ptr: u64 | 0 | Create a pipe pair |
| 432 | SYS_DUP | old_fd: u64 | new fd | Duplicate file descriptor |
| 433 | SYS_DUP2 | old_fd: u64, new_fd: u64 | new fd | Duplicate to specific fd |
| 456 | SYS_PREAD | fd: u64, buf_ptr: u64, buf_len: u64, offset: u64 | bytes read | Pread at offset |
| 457 | SYS_PWRITE | fd: u64, buf_ptr: u64, buf_len: u64, offset: u64 | bytes written | Pwrite 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
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 440 | SYS_CHDIR | path_ptr: u64, path_len: u64 | 0 | Change working directory |
| 441 | SYS_FCHDIR | fd: u64 | 0 | Change working directory by fd |
| 442 | SYS_GETCWD | buf_ptr: u64, buf_len: u64 | bytes written | Get current working directory |
| 443 | SYS_IOCTL | fd: u64, cmd: u64, arg: u64 | depends on cmd | Device I/O control |
| 444 | SYS_UMASK | mask: u64 | old mask | Set file mode creation mask |
| 445 | SYS_UNLINK | path_ptr: u64, path_len: u64 | 0 | Delete a file |
| 446 | SYS_RMDIR | path_ptr: u64, path_len: u64 | 0 | Remove a directory |
| 447 | SYS_MKDIR | path_ptr: u64, path_len: u64, mode: u64 | 0 | Create a directory |
| 448 | SYS_RENAME | old_ptr: u64, old_len: u64, new_ptr: u64, new_len: u64 | 0 | Rename a file |
| 449 | SYS_LINK | old_ptr: u64, old_len: u64, new_ptr: u64, new_len: u64 | 0 | Create a hard link |
| 450 | SYS_SYMLINK | target_ptr: u64, target_len: u64, link_ptr: u64, link_len: u64 | 0 | Create a symbolic link |
| 451 | SYS_READLINK | path_ptr: u64, path_len: u64, buf_ptr: u64, buf_len: u64 | bytes read | Read symbolic link target |
| 452 | SYS_CHMOD | path_ptr: u64, path_len: u64, mode: u64 | 0 | Change file permissions |
| 453 | SYS_FCHMOD | fd: u64, mode: u64 | 0 | Change file permissions by fd |
| 454 | SYS_TRUNCATE | path_ptr: u64, path_len: u64, len: u64 | 0 | Truncate a file |
| 455 | SYS_FTRUNCATE | fd: u64, len: u64 | 0 | Truncate 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
| Value | Constant | Meaning |
|---|---|---|
-100 | AT_FDCWD | Use the process's current working directory (CWD) as the base |
≥ 0 | valid fd | Use the opened directory referenced by this file descriptor |
Syscall reference
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 462 | SYS_OPENAT | dirfd: u64, path_ptr: u64, path_len: u64, flags: u64 | file descriptor | Open a file relative to dirfd. If path_ptr is absolute, dirfd is ignored. |
| 463 | SYS_FSTATAT | dirfd: u64, path_ptr: u64, path_len: u64, stat_ptr: u64, flags: u64 | 0 | Get file status relative to dirfd. stat_ptr receives a FileStat struct. |
| 464 | SYS_UNLINKAT | dirfd: u64, path_ptr: u64, path_len: u64, flags: u64 | 0 | Delete a file relative to dirfd. If AT_REMOVEDIR flag is set, removes a directory. |
| 465 | SYS_RENAMEAT | olddirfd: u64, old_ptr: u64, old_len: u64, newdirfd: u64, new_ptr: u64, new_len: u64 | 0 | Rename/move a file. Source and destination can have different base directories. |
| 466 | SYS_MKDIRAT | dirfd: u64, path_ptr: u64, path_len: u64, mode: u64 | 0 | Create a directory relative to dirfd. |
| 467 | SYS_READLINKAT | dirfd: u64, path_ptr: u64, path_len: u64, buf_ptr: u64, buf_len: u64 | bytes read | Read the target of a symbolic link relative to dirfd. |
| 468 | SYS_FACCESSAT | dirfd: u64, path_ptr: u64, path_len: u64, mode: u64, flags: u64 | 0 | Check file accessibility. mode: R_OK (4), W_OK (2), X_OK (1), F_OK (0). |
Flags
| Flag | Value | Description |
|---|---|---|
AT_FDCWD | -100 | Use process CWD as base directory |
AT_REMOVEDIR | 0x200 | Unlink a directory instead of a file (for SYS_UNLINKAT) |
AT_SYMLINK_NOFOLLOW | 0x100 | Do not follow symlinks (for SYS_FSTATAT) |
AT_EMPTY_PATH | 0x1000 | Operate 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
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 460 | SYS_POLL | fds_ptr: u64, nfds: u64, timeout_ms: i64 | ready count | Poll file descriptors |
| 461 | SYS_PPOLL | fds_ptr: u64, nfds: u64, timeout_ptr: u64, sigmask_ptr: u64 | ready count | Ppoll with signal mask |
Network
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 410 | SYS_NET_RECV | buf_ptr: u64, buf_len: u64 | bytes received | Receive network packet |
| 411 | SYS_NET_SEND | buf_ptr: u64, buf_len: u64 | bytes sent | Send network packet |
| 412 | SYS_NET_INFO | info_type: u64, buf_ptr: u64 | 0 | Query network info (IP, gateway, etc.) |
Volume (block device)
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 420 | SYS_VOLUME_READ | handle: u64, offset: u64, buf_ptr: u64, buf_len: u64 | bytes read | Read from volume |
| 421 | SYS_VOLUME_WRITE | handle: u64, offset: u64, buf_ptr: u64, buf_len: u64 | bytes written | Write to volume |
| 422 | SYS_VOLUME_INFO | handle: u64, out_ptr: u64 | 0 | Query volume info |
Time
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 500 | SYS_CLOCK_GETTIME | clock_id: u64, tp_ptr: u64 | 0 | Get clock time |
| 501 | SYS_NANOSLEEP | req_ptr: u64, rem_ptr: u64 | 0 | Sleep for a duration |
| 502 | SYS_CLOCK_NANOSLEEP | clock_id: u64, flags: u64, req_ptr: u64, rem_ptr: u64 | 0 | Sleep on a specific clock |
Clock IDs: CLOCK_REALTIME (0), CLOCK_MONOTONIC (1), CLOCK_PROCESS_CPUTIME_ID (2), CLOCK_THREAD_CPUTIME_ID (3)
Debug & miscellaneous
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 600 | SYS_DEBUG_LOG | msg_ptr: u64, msg_len: u64 | 0 | Write a debug message to kernel log |
| 601 | SYS_GETRANDOM | buf: u64, len: usize, flags: u32 | bytes written | Fill buffer with random bytes |
| 610 | SYS_SET_ROBUST_LIST | head: u64, len: usize | 0 | Set robust futex list head |
| 611 | SYS_GET_ROBUST_LIST | pid: i64, head_ptr: u64, len_ptr: u64 | 0 | Get robust futex list head |
Module management
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 700 | SYS_MODULE_LOAD | path_ptr: u64, path_len: u64 | module ID | Load a kernel module |
| 701 | SYS_MODULE_UNLOAD | module_id: u64 | 0 | Unload a kernel module |
| 702 | SYS_MODULE_GET_SYMBOL | module_id: u64, name_ptr: u64, name_len: u64 | symbol address | Look up a symbol in a loaded module |
| 703 | SYS_MODULE_QUERY | out_ptr: u64, max_count: u64 | module count | List loaded modules |
Silo management
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 800 | SYS_SILO_CREATE | : | silo ID | Create a new silo |
| 801 | SYS_SILO_CONFIG | silo_id: u64, key_ptr: u64, key_len: u64, val_ptr: u64, val_len: u64 | 0 | Configure a silo |
| 802 | SYS_SILO_ATTACH_MODULE | silo_id: u64, module_id: u64 | 0 | Attach a module to a silo |
| 803 | SYS_SILO_START | silo_id: u64 | 0 | Start a silo |
| 804 | SYS_SILO_STOP | silo_id: u64 | 0 | Stop a silo |
| 805 | SYS_SILO_KILL | silo_id: u64 | 0 | Kill a silo (force stop) |
| 806 | SYS_SILO_EVENT_NEXT | silo_id: u64, out_ptr: u64 | 0 | Wait for next silo event |
| 807 | SYS_SILO_SUSPEND | silo_id: u64 | 0 | Suspend a silo |
| 808 | SYS_SILO_RESUME | silo_id: u64 | 0 | Resume a silo |
| 809 | SYS_SILO_PLEDGE | promises_ptr: u64, promises_len: u64 | 0 | Restrict syscalls (pledge) |
| 810 | SYS_SILO_UNVEIL | path_ptr: u64, path_len: u64, perms_ptr: u64, perms_len: u64 | 0 | Restrict filesystem access (unveil) |
| 811 | SYS_SILO_ENTER_SANDBOX | : | 0 | Enter sandbox mode (irreversible) |
| 812 | SYS_SILO_RENAME | silo_id: u64, name_ptr: u64, name_len: u64 | 0 | Rename a silo |
ABI version
| # | Syscall | Parameters | Return | Description |
|---|---|---|---|---|
| 900 | SYS_ABI_VERSION | : | (major << 16) | minor | Query ABI version |
Common errno values
| Value | Name | Description |
|---|---|---|
| 1 | EPERM | Operation not permitted |
| 2 | ENOENT | No such file or directory |
| 3 | ESRCH | No such process |
| 4 | EINTR | Interrupted system call |
| 5 | EIO | Input/output error |
| 7 | E2BIG | Argument list too long |
| 9 | EBADF | Bad file descriptor |
| 10 | ECHILD | No child processes |
| 11 | EAGAIN | Resource temporarily unavailable |
| 12 | ENOMEM | Out of memory |
| 13 | EACCES | Permission denied |
| 14 | EFAULT | Bad address |
| 17 | EEXIST | File exists |
| 20 | ENOTDIR | Not a directory |
| 21 | EISDIR | Is a directory |
| 22 | EINVAL | Invalid argument |
| 28 | ENOSPC | No space left on device |
| 32 | EPIPE | Broken pipe |
| 38 | ENOSYS | Function not implemented |
| 52 | ENOTSUP | Not supported |
| 98 | EADDRINUSE | Address already in use |
| 110 | ETIMEDOUT | Connection timed out |
| 111 | ECONNREFUSED | Connection refused |
Syscall Layer
The userspace syscall crate is workspace/components/syscall (strat9-syscall).
Useful entry points:
strat9_syscall::callfor high-level wrappersstrat9_syscall::numberfor syscall constantsstrat9_syscall::errorfor userspace error mappingstrat9_syscall::datafor shared data structs
API reference:
Changelog
Project stats
- Total commits:
554 - Latest tag:
0.1.0 - Repository: git.strat9-os.org
Recent commits (auto-generated)
- 2026-06-26
941a995feat: update ABI changelog and documentation - 2026-06-25
4fb871fRefactor error codes and syscall flags; implement getrandom syscall - 2026-06-25
f0f891cdocs: update published documentation - 2026-06-25
9b31c08docs: update published documentation - 2026-06-25
a522fb8Refactor NIC data plane and IPC transport statistics - 2026-06-25
23cbeaddocs: update published documentation - 2026-06-25
454a828feat: add N2 data plane implementation with lock-free rings and enhance NIC interrupt handling - 2026-06-25
1f1362bdocs: update published documentation - 2026-06-25
d1e838ffeat: implement IPC transport layer with 3-level architecture - 2026-06-25
411f5aafeat: add IPC transport layer support and enhance ICMP handling - 2026-06-25
c034c91docs: update published documentation - 2026-06-25
bbad275Implement IPC transport layer with lock-free ring and intrusive mailbox - 2026-06-25
77b1a74docs: add IPC architecture document (3 access levels) - 2026-06-25
848baafMerge branch 'feat/input-to-userspace' into 'main' - 2026-06-25
5a3d69cfeat: migrate input system to userspace - 2026-06-24
1b98905Merge branch 'test/smp-hardware-debug' into 'main' - 2026-06-24
3fea3f3SMP hardware debug, NVMe fixes, VGA refactor, telnetd hardening, docs - 2026-06-17
f1bccb9Merge branch 'fix/typed-irq-guard-allocator' into 'main' - 2026-06-17
b1d7c35buddy: use PreemptDisabled guardian on per-CPU frame caches (#37) - 2026-06-17
1ca93d1Merge branch 'fix/tech-debt-allocation-under-lock' into 'main' - 2026-06-17
78e18ceTech debt: allocation-under-lock and global-lock patterns (#50) - 2026-06-16
6455a23Merge branch 'fix/irq-token-encapsulation' into 'main' - 2026-06-16
cb4ce4dRefactor: document IrqDisabledToken creation paths and encapsulation - 2026-06-16
bdec79dMerge branch 'fix/arc-strong-count-wording' into 'main' - 2026-06-16
c642da4Fix: refine Arc::strong_count diagnostic wording to heuristic - 2026-06-16
f85e757Merge branch 'feat/spinlock-multi-watch-debug' into 'main' - 2026-06-16
3fec849Feat: replace single-lock trace with fixed-size multi-watch array - 2026-06-16
84db9dfMerge branch 'fix/slab-refill-irq-assert' into 'main' - 2026-06-16
021fb49Fix: add debug_assert IRQ-disabled invariant on slab refill - 2026-06-16
8ebf658Merge branch 'fix/heap-page-count-overflow' into 'main' - 2026-06-16
d1f7eefFix: use saturating arithmetic for vmalloc page count rounding - 2026-06-16
99d4edeMerge branch 'fix/reparent-children-deterministic' into 'main' - 2026-06-16
dcc239cFix: make orphan reparenting deterministic by dropping links when PID 1 absent - 2026-06-16
d2722eeMerge branch 'fix/legacy-pic-timer-parity' into 'main' - 2026-06-16
e53a4b6Fix: mirror LAPIC timer Ring-3 preemption policy in legacy PIC handler - 2026-06-16
257b694Merge branch 'fix/buddy-free-to-zone-logging' into 'main' - 2026-06-16
18b1037Fix: escalate free_to_zone protected-overlap to panic matching alloc side - 2026-06-16
28bbc90Merge branch 'fix/keyboard-lost-key-counter' into 'main' - 2026-06-16
b19d6bfFix keyboard driver: shared state, US extended keys, numpad, lost-key counter - 2026-06-16
93302a5docs: update published documentation - 2026-06-16
b2edb49Merge branch 'enhance-network-tools' into 'main' - 2026-06-16
e4ab1a9Enhance network stack, NIC drivers, USB/NVMe subsystems, and thermal management - 2026-06-03
5ee7f8dMerge branch 'fix-some-mistake-in-network-stack' into 'main' - 2026-06-03
0c40058Refactor the network stack and add dual-stack userspace tooling - 2026-05-24
aeade5eCode cleanup - 2026-05-24
86c810eRaüs silo sshd - 2026-05-24
40d4d46Merge branch 'IPC-refactor' into 'main' - 2026-05-24
b2bbcc0Improve and fix IPC - 2026-05-23
b7c3e27Merge branch 'hunt-memory-corruption' into 'main' - 2026-05-23
db23b53Fix major memory leak and remove sshd silo
Publishing
One-command publication script
At repository root:
./publish-doc.sh
This script:
- builds docs (
cargo make docs-site) - regenerates ABI changelog auto section from git history
- commits/pushes current branch changes
- uploads built website to the remote vhost via SSH
The docs builder publishes:
- mdBook pages under
docs-site/ - rustdoc for all workspace crates (
cargo doc --workspace --no-deps) - a combined static site in
build/docs-site