212 lines
5.7 KiB
Zig
212 lines
5.7 KiB
Zig
// 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;
|
|
}
|