// SPDX-License-Identifier: LSL-1.0 // Copyright (c) 2026 Markus Maiwald // Stewardship: Self Sovereign Society Foundation // // This file is part of the Nexus Sovereign Core. // See legal/LICENSE_SOVEREIGN.md for license terms. //! Nexus Membrane: ION Interface (The Sovereign Protocol) //! //! Defines the shared memory interface, packet structures, and command types //! used for communication between the kernel and userland. //! //! SAFETY: Implements lock-free ring buffers for the SysTable channels. //! All memory accesses to the SysTable are through volatile pointers. const std = @import("std"); const builtin = @import("builtin"); // --- Protocol Definitions (Match core/ion.nim) --- pub const CMD_SYS_NOOP: u32 = 0; pub const CMD_SYS_EXIT: u32 = 1; pub const CMD_ION_STOP: u32 = 2; pub const CMD_ION_START: u32 = 3; pub const CMD_GPU_MATRIX: u32 = 0x100; pub const CMD_GPU_CLEAR: u32 = 0x101; pub const CMD_GET_GPU_STATUS: u32 = 0x102; pub const CMD_FS_OPEN: u32 = 0x200; pub const CMD_FS_READ: u32 = 0x201; pub const CMD_FS_READDIR: u32 = 0x202; pub const CMD_ION_FREE: u32 = 0x300; pub const CMD_SYS_EXEC: u32 = 0x400; pub const CMD_NET_TX: u32 = 0x500; pub const CMD_NET_RX: u32 = 0x501; pub const CMD_BLK_READ: u32 = 0x600; pub const CMD_BLK_WRITE: u32 = 0x601; pub const CmdPacket = extern struct { kind: u32, _pad: u32, // Explicit Padding for 8-byte alignment arg: u64, id: u128, // SipHash Provenance (16 bytes) }; // Compile-time validation: 32 bytes comptime { if (@sizeOf(CmdPacket) != 32) { @compileError("CmdPacket size mismatch! Expected 32, got " ++ @as([]const u8, &[_]u8{@sizeOf(CmdPacket)})); } } pub const FsReadArgs = extern struct { fd: u64, buffer: u64, len: u64, }; pub const NetArgs = extern struct { buf: u64, len: u64, }; pub const BlkArgs = extern struct { sector: u64, buf: u64, len: u64, }; pub const IonPacket = extern struct { data: u64, // ptr phys: u64, len: u16, id: u16, }; // Generic Lock-Free Ring Buffer (Single Producer / Single Consumer safe) pub fn RingBuffer(comptime T: type) type { return extern struct { head: u32, tail: u32, mask: u32, data: [256]T, pub fn push(self: *volatile @This(), item: T) bool { const head = self.head; const tail = self.tail; const mask = self.mask; // Check full if (((head + 1) & mask) == (tail & mask)) { return false; } // Write data self.data[head & mask] = item; // Commit switch (builtin.cpu.arch) { .riscv64 => asm volatile ("fence" ::: .{ .memory = true }), .aarch64 => asm volatile ("dmb ish" ::: .{ .memory = true }), else => @compileError("unsupported arch"), } self.head = (head + 1) & mask; return true; } }; } pub const SysTable = extern struct { magic: u32, reserved: u32, s_rx: *RingBuffer(IonPacket), s_tx: *RingBuffer(IonPacket), s_event: *RingBuffer(IonPacket), s_cmd: *RingBuffer(CmdPacket), s_input: *RingBuffer(IonPacket), // Hypercalls fn_vfs_open: u64, fn_vfs_read: u64, fn_vfs_list: u64, fn_vfs_write: u64, fn_vfs_close: u64, fn_vfs_dup: u64, fn_vfs_dup2: u64, fn_log: u64, fn_pledge: u64, // Framebuffer fb_addr: u64, fb_width: u32, fb_height: u32, fb_stride: u32, fb_bpp: u32, fn_yield: u64, // Crypto fn_siphash: u64, fn_ed25519_verify: u64, fn_blake3: u64, // Network s_net_rx: *RingBuffer(IonPacket), s_net_tx: *RingBuffer(IonPacket), // Phase 36.3: Shared ION (16 bytes) fn_ion_alloc: u64, fn_ion_free: u64, // Phase 36.4: Wait Multi fn_wait_multi: u64, // Phase 36.5: HW Info net_mac: [6]u8, reserved_mac: [2]u8, // Project LibWeb: LWF Sovereign Channel s_lwf_rx: *RingBuffer(IonPacket), // Kernel -> User (LWF frames) s_lwf_tx: *RingBuffer(IonPacket), // User -> Kernel (LWF frames) }; comptime { if (@sizeOf(IonPacket) != 24) @compileError("IonPacket size mismatch!"); if (@sizeOf(SysTable) != 240) { @compileError("SysTable size mismatch! Expected 240 (LibWeb LWF channels added)"); } } const SYSTABLE_ADDR: usize = if (builtin.cpu.arch == .aarch64) 0x50000000 else 0x83000000; // --- API --- extern fn console_write(ptr: [*]const u8, len: usize) void; pub fn sys_cmd_push(pkt: CmdPacket) bool { const sys = @as(*const volatile SysTable, @ptrFromInt(SYSTABLE_ADDR)); // Debug: Check magic if (sys.magic != 0x4E585553) { const msg = "[DEBUG] SysTable magic check FAILED!\n"; console_write(msg.ptr, msg.len); return false; } // const msg2 = "[DEBUG] Pushing to command ring...\n"; // console_write(msg2.ptr, msg2.len); // Push to Command Ring const result = sys.s_cmd.push(pkt); // if (result) { // const msg3 = "[DEBUG] Command ring push SUCCESS\n"; // console_write(msg3.ptr, msg3.len); // } else { // const msg4 = "[DEBUG] Command ring push FAILED (ring full?)\n"; // console_write(msg4.ptr, msg4.len); // } return result; } pub fn sys_input_pop(out_pkt: *IonPacket) bool { const sys = @as(*const volatile SysTable, @ptrFromInt(SYSTABLE_ADDR)); if (sys.magic != 0x4E585553) return false; const ring = sys.s_input; const head = @atomicLoad(u32, &ring.head, .acquire); const tail = @atomicLoad(u32, &ring.tail, .monotonic); if (head == tail) return false; out_pkt.* = ring.data[tail & ring.mask]; @atomicStore(u32, &ring.tail, tail + 1, .release); return true; }