rumpk/core/ion.nim

245 lines
7.9 KiB
Nim

# 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.
## Rumpk Layer 1: ION Interface (The Sovereign Protocol)
##
## Defines the core communication protocol between Kernel and Userland.
## Implements the SysTable structure, packet types, and Sovereign Channels.
##
## SAFETY: Provides the ABI contract for lock-free communication.
# CRITICAL: Only import memory module for kernel builds
# Userspace builds (with -d:is_membrane) should NOT get the 2MB pool
when not defined(is_membrane):
import ion/memory
export memory
const
PLEDGE_STDIO* = 0x0001'u64
PLEDGE_RPATH* = 0x0002'u64
PLEDGE_WPATH* = 0x0004'u64
PLEDGE_INET* = 0x0008'u64
PLEDGE_EXEC* = 0x0010'u64
PLEDGE_ALL* = 0xFFFFFFFFFFFFFFFF'u64
type
CmdType* = enum
CMD_SYS_NOOP = 0
CMD_SYS_EXIT = 1
CMD_ION_STOP = 2
CMD_ION_START = 3
CMD_GPU_MATRIX = 0x100
CMD_GPU_CLEAR = 0x101
CMD_GET_GPU_STATUS = 0x102
CMD_FS_OPEN = 0x200
CMD_FS_READ = 0x201
CMD_FS_READDIR = 0x202
CMD_FS_WRITE = 0x203
CMD_FS_MOUNT = 0x204
CMD_ION_FREE = 0x300
CMD_SYS_EXEC = 0x400
CMD_NET_TX = 0x500
CMD_NET_RX = 0x501
CMD_BLK_READ = 0x600
CMD_BLK_WRITE = 0x601
CMD_SPAWN_FIBER = 0x700
CmdPacket* = object
kind*: uint32
reserved*: uint32
arg*: uint64
id*: array[16, byte]
NetArgs* = object
buf*: uint64
len*: uint64
BlkArgs* = object
sector*: uint64
buf*: uint64
len*: uint64
FileArgs* = object
name*: uint64
data*: uint64
len*: uint64
HAL_Ring*[T] = object
head*: uint32
tail*: uint32
mask*: uint32
data*: array[256, T]
SovereignChannel*[T] = object
ring*: ptr HAL_Ring[T]
SysTable* = object
magic*: uint32 # 0x4E585553
reserved*: uint32
s_rx*: ptr HAL_Ring[IonPacket]
s_tx*: ptr HAL_Ring[IonPacket]
s_event*: ptr HAL_Ring[IonPacket]
s_cmd*: ptr HAL_Ring[CmdPacket]
s_input*: ptr HAL_Ring[IonPacket]
# Function Pointers
fn_vfs_open*: proc(path: cstring, flags: int32): int32 {.cdecl.}
fn_vfs_read*: proc(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.}
fn_vfs_list*: proc(buf: pointer, max_len: uint64): int64 {.cdecl.}
fn_vfs_write*: proc(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.}
fn_vfs_close*: proc(fd: int32): int32 {.cdecl.}
fn_vfs_dup*: proc(fd: int32, min_fd: int32): int32 {.cdecl.}
fn_vfs_dup2*: proc(old_fd, new_fd: int32): int32 {.cdecl.}
fn_log*: pointer
fn_pledge*: proc(promises: uint64): int32 {.cdecl.}
# Framebuffer
fb_addr*: uint64
fb_width*: uint32
fb_height*: uint32
fb_stride*: uint32
fb_bpp*: uint32
fn_yield*: proc() {.cdecl.}
# Phase 35e: Crypto
fn_siphash*: proc(key: ptr array[16, byte], data: pointer, len: uint64, out_hash: ptr array[16, byte]) {.cdecl.}
fn_ed25519_verify*: proc(sig: ptr array[64, byte], msg: pointer, len: uint64, pk: ptr array[32, byte]): bool {.cdecl.}
# SPEC-503: Monolith Key Derivation
fn_blake3*: proc(data: pointer, len: uint64, out_hash: ptr array[32, byte]) {.cdecl.}
# Phase 36.2: Network Membrane (The Veins)
s_net_rx*: ptr HAL_Ring[IonPacket] # Kernel Producer -> User Consumer
s_net_tx*: ptr HAL_Ring[IonPacket] # User Producer -> Kernel Consumer
# Phase 36.3: Shared ION (16 bytes)
fn_ion_alloc*: proc(out_id: ptr uint16): uint64 {.cdecl.}
fn_ion_free*: proc(id: uint16) {.cdecl.}
# Phase 36.4: I/O Multiplexing (8 bytes)
fn_wait_multi*: proc(mask: uint64): int32 {.cdecl.}
# Phase 36.5: Network Hardware Info (8 bytes)
net_mac*: array[6, byte]
reserved_mac*: array[2, byte]
# Project LibWeb: LWF Sovereign Channel (16 bytes)
s_lwf_rx*: ptr HAL_Ring[IonPacket] # Kernel Producer -> User Consumer (LWF frames)
s_lwf_tx*: ptr HAL_Ring[IonPacket] # User Producer -> Kernel Consumer (LWF frames)
include invariant
# --- Sovereign Logic ---
# HAL Imports
proc hal_channel_push*(ring: uint64, pkt: IonPacket): bool {.importc, cdecl.}
proc hal_channel_pop*(ring: uint64, out_pkt: ptr IonPacket): bool {.importc, cdecl.}
proc hal_cmd_push*(ring: uint64, pkt: CmdPacket): bool {.importc, cdecl.}
proc hal_cmd_pop*(ring: uint64, out_pkt: ptr CmdPacket): bool {.importc, cdecl.}
proc send*[T](c: var SovereignChannel[T], pkt: T): bool =
if c.ring == nil: return false
when T is IonPacket:
return hal_channel_push(cast[uint64](c.ring), pkt)
elif T is CmdPacket:
return hal_cmd_push(cast[uint64](c.ring), pkt)
else:
return false
proc recv*[T](c: var SovereignChannel[T], out_pkt: var T): bool =
if c.ring == nil: return false
when T is IonPacket:
return hal_channel_pop(cast[uint64](c.ring), addr out_pkt)
elif T is CmdPacket:
return hal_cmd_pop(cast[uint64](c.ring), addr out_pkt)
var chan_input*: SovereignChannel[IonPacket]
var chan_cmd*: SovereignChannel[CmdPacket]
var chan_rx*: SovereignChannel[IonPacket]
var chan_tx*: SovereignChannel[IonPacket]
var guest_input_hal: HAL_Ring[IonPacket]
var cmd_hal: HAL_Ring[CmdPacket]
var rx_hal: HAL_Ring[IonPacket]
var tx_hal: HAL_Ring[IonPacket]
# Phase 36.2: Network Channels
var chan_net_rx*: SovereignChannel[IonPacket]
var chan_net_tx*: SovereignChannel[IonPacket]
var chan_netswitch_rx*: SovereignChannel[IonPacket] # Internal: Driver -> NetSwitch
var net_rx_hal: HAL_Ring[IonPacket]
var net_tx_hal: HAL_Ring[IonPacket]
var netswitch_rx_hal: HAL_Ring[IonPacket]
# Project LibWeb: LWF Sovereign Channels
var chan_lwf_rx*: SovereignChannel[IonPacket] # Kernel -> User (LWF frames)
var chan_lwf_tx*: SovereignChannel[IonPacket] # User -> Kernel (LWF frames)
var lwf_rx_hal: HAL_Ring[IonPacket]
var lwf_tx_hal: HAL_Ring[IonPacket]
proc ion_init_input*() {.exportc, cdecl.} =
guest_input_hal.head = 0
guest_input_hal.tail = 0
guest_input_hal.mask = 255
chan_input.ring = addr guest_input_hal
proc ion_init_network*() {.exportc, cdecl.} =
# NOTE: This function is called early in kernel boot.
# The actual ring memory will be allocated in SYSTABLE region by kmain.
# We just initialize the local HAL rings here for internal kernel use.
net_rx_hal.head = 0
net_rx_hal.tail = 0
net_rx_hal.mask = 255
chan_net_rx.ring = addr net_rx_hal
net_tx_hal.head = 0
net_tx_hal.tail = 0
net_tx_hal.mask = 255
chan_net_tx.ring = addr net_tx_hal
netswitch_rx_hal.head = 0
netswitch_rx_hal.tail = 0
netswitch_rx_hal.mask = 255
chan_netswitch_rx.ring = addr netswitch_rx_hal
# Project LibWeb: LWF Rings
lwf_rx_hal.head = 0
lwf_rx_hal.tail = 0
lwf_rx_hal.mask = 255
chan_lwf_rx.ring = addr lwf_rx_hal
lwf_tx_hal.head = 0
lwf_tx_hal.tail = 0
lwf_tx_hal.mask = 255
chan_lwf_tx.ring = addr lwf_tx_hal
# Initialize user slab
ion_user_slab_init()
# Internal allocators removed - use shared/systable versions
# =========================================================
# SysTable-Compatible Wrappers for User Slab
# =========================================================
# These wrappers have the same signature as fn_ion_alloc/fn_ion_free
# but use the user slab instead of the kernel ION pool.
# Track allocated buffers by pseudo-ID (index in slab)
proc ion_user_alloc_systable*(out_id: ptr uint16): uint64 {.exportc, cdecl.} =
## SysTable-compatible allocator using user slab (via shared bitmap)
return ion_alloc_shared(out_id)
proc ion_user_free_systable*(id: uint16) {.exportc, cdecl.} =
## SysTable-compatible free using user slab
var pkt: IonPacket
pkt.id = id
pkt.data = cast[ptr UncheckedArray[byte]](1) # Dummy non-nil
ion_free(pkt)
static: doAssert(sizeof(IonPacket) == 24, "IonPacket size mismatch!")
static: doAssert(sizeof(CmdPacket) == 32, "CmdPacket size mismatch!")
static: doAssert(sizeof(SysTable) == 240, "SysTable size mismatch! (Expected 240 after LibWeb LWF channels)")