rumpk/libs/membrane/ion.zig

158 lines
4.1 KiB
Zig

const std = @import("std");
// --- 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
asm volatile ("fence" ::: .{ .memory = true });
self.head = (head + 1) & mask;
return true;
}
};
}
pub const SysTable = extern struct {
magic: u32,
s_rx: *RingBuffer(IonPacket),
s_tx: *RingBuffer(IonPacket),
s_event: *RingBuffer(IonPacket),
s_cmd: *RingBuffer(CmdPacket),
s_input: *RingBuffer(IonPacket),
// Hypercalls
// Hypercalls
fn_vfs_open: u64, // pointer
fn_vfs_read: u64, // pointer
fn_vfs_list: u64, // pointer
fn_vfs_write: u64, // pointer (ptr, buffer, len) -> i64
fn_vfs_close: u64, // pointer (fd) -> i32
fn_log: u64, // pointer (ptr, len) -> void
};
comptime {
if (@sizeOf(IonPacket) != 24) @compileError("IonPacket size mismatch!");
if (@sizeOf(SysTable) != 96) @compileError("SysTable size mismatch!");
}
const SYSTABLE_ADDR: usize = 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;
}