feat(rumpk): Phase 2 Complete - The Entropy Purge & Sovereign Alignment

- Rumpk Core: Complete exorcism of LwIP/NET ghosts. Transitioned to ION nomenclature.
- ABI Sync: Synchronized Zig HAL and Nim Logic Ring Buffer layouts (u32 head/tail/mask).
- Invariant Shield: Hardened HAL pipes with handle-based validation and power-of-2 sync.
- Immune System: Verified Blink Recovery (Self-Healing) with updated ION Control Plane.
- NexShell: Major refactor of Command Plane for Sovereign Ring access.
- Architecture: Updated SPEC files and Doctrines (Silence, Hexagonal Sovereignty).
- Purge: Removed legacy rumk and nip artifacts for a clean substrate.
- Web: Updated landing page vision to match Rumpk v1.1 milestones.
This commit is contained in:
Markus Maiwald 2025-12-30 21:45:00 +01:00
parent 061a2ff56b
commit b3d9c2a49d
49 changed files with 677 additions and 742 deletions

7
apps/subject_rust/Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "subject_rust"
version = "0.1.0"

View File

@ -0,0 +1,16 @@
[package]
name = "subject_rust"
version = "0.1.0"
edition = "2021"
[dependencies]
# No dependencies yet. We are raw.
[profile.release]
panic = "abort" # We will handle it
lto = true
opt-level = "z" # Optimize for size
[lib]
crate-type = ["staticlib"]
path = "src/lib.rs"

View File

@ -0,0 +1,105 @@
#![no_std]
#![no_main]
#![feature(alloc_error_handler)]
extern crate alloc;
use alloc::string::String;
use alloc::format;
// ----------------------------------------------------------------------------
// 1. The Nervous System (FFI to Membrane)
// ----------------------------------------------------------------------------
extern "C" {
fn socket(domain: i32, type_: i32, protocol: i32) -> i32;
fn connect(fd: i32, addr: *const u8, len: i32) -> i32;
fn write(fd: i32, buf: *const u8, count: usize) -> isize;
fn sleep(seconds: u32);
// We also need the allocator from libnexus (clib.c or libc.nim exports)
fn malloc(size: usize) -> *mut u8;
fn free(ptr: *mut u8);
}
// ----------------------------------------------------------------------------
// 2. The Stomach (Global Allocator)
// ----------------------------------------------------------------------------
struct NexusAllocator;
unsafe impl core::alloc::GlobalAlloc for NexusAllocator {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
malloc(layout.size())
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: core::alloc::Layout) {
free(ptr)
}
}
#[global_allocator]
static ALLOCATOR: NexusAllocator = NexusAllocator;
#[alloc_error_handler]
fn alloc_error(_layout: core::alloc::Layout) -> ! {
panic!("OOM");
}
// ----------------------------------------------------------------------------
// 3. The Voice (Panic Handler)
// ----------------------------------------------------------------------------
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
let msg = "RUST PANIC!\n";
unsafe { write(1, msg.as_ptr(), msg.len()); }
loop {}
}
// ----------------------------------------------------------------------------
// 4. The Astronaut (Main Logic)
// ----------------------------------------------------------------------------
// We need struct layouts for sockaddr if we want to be precise,
// but for this test, we can use the raw bytes or simple C structs.
#[repr(C)]
struct SockAddrIn {
sin_family: u16,
sin_port: u16,
sin_addr: u32, // 10.0.2.2 = 0x0202000A (Little Endian)
zero: [u8; 8],
}
#[no_mangle]
pub extern "C" fn main() -> i32 {
let msg = String::from("[Rust] Booting sequence...\n");
unsafe { write(1, msg.as_ptr(), msg.len()); }
let fd = unsafe { socket(2, 1, 0) }; // AF_INET, SOCK_STREAM
if fd < 0 {
let err = "[Rust] Socket failed\n";
unsafe { write(1, err.as_ptr(), err.len()); }
return 1;
}
// 10.0.2.2 = 0x0202000A
// 8080 = 0x1F90 (Big Endian)
let port_be: u16 = 8080u16.to_be();
let addr_fixed = SockAddrIn {
sin_family: 2,
sin_port: port_be,
sin_addr: 0x0202000A,
zero: [0; 8],
};
let hello = format!("[Rust] Hello from the Iron Lung! FD={}\n", fd);
unsafe {
let res = connect(fd, &addr_fixed as *const _ as *const u8, 16);
if res < 0 {
let fail = "[Rust] Connection Failed\n";
write(1, fail.as_ptr(), fail.len());
} else {
write(fd, hello.as_ptr(), hello.len());
let success = "[Rust] Payload Sent.\n";
write(1, success.as_ptr(), success.len());
}
}
loop { unsafe { sleep(1); } }
}

View File

@ -0,0 +1 @@
{"rustc_fingerprint":12492699077941185025,"outputs":{"11828851594938707206":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.a\n/usr\noff\n___\ndebug_assertions\npanic=\"abort\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"riscv64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_feature=\"a\"\ntarget_feature=\"c\"\ntarget_feature=\"m\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"none\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\n","stderr":"warning: dropping unsupported crate type `dylib` for target `riscv64gc-unknown-none-elf`\n\nwarning: dropping unsupported crate type `cdylib` for target `riscv64gc-unknown-none-elf`\n\nwarning: dropping unsupported crate type `proc-macro` for target `riscv64gc-unknown-none-elf`\n\nwarning: 3 warnings emitted\n\n"},"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.92.0 (ded5c06cf 2025-12-08) (Arch Linux rust 1:1.92.0-1)\nbinary: rustc\ncommit-hash: ded5c06cf21d2b93bffd5d884aa6e96934ee4234\ncommit-date: 2025-12-08\nhost: x86_64-unknown-linux-gnu\nrelease: 1.92.0\nLLVM version: 21.1.6\n","stderr":""},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/usr\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"1973728902973864382":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/usr\noff\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"riscv64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"a\"\ntarget_feature=\"c\"\ntarget_feature=\"m\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}

View File

@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by cargo.
# For information about cache directory tags see https://bford.info/cachedir/

View File

@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by cargo.
# For information about cache directory tags see https://bford.info/cachedir/

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1,3 @@
{"$message_type":"diagnostic","message":"can't find crate for `core`","code":{"code":"E0463","explanation":"A crate was declared but cannot be found.\n\nErroneous code example:\n\n```compile_fail,E0463\nextern crate foo; // error: can't find crate\n```\n\nYou need to link your code to the relevant crate in order to be able to use it\n(through Cargo or the `-L` option of rustc, for example).\n\n## Common causes\n\n- The crate is not present at all. If using Cargo, add it to `[dependencies]`\n in Cargo.toml.\n- The crate is present, but under a different name. If using Cargo, look for\n `package = ` under `[dependencies]` in Cargo.toml.\n\n## Common causes for missing `std` or `core`\n\n- You are cross-compiling for a target which doesn't have `std` prepackaged.\n Consider one of the following:\n + Adding a pre-compiled version of std with `rustup target add`\n + Building std from source with `cargo build -Z build-std`\n + Using `#![no_std]` at the crate root, so you won't need `std` in the first\n place.\n- You are developing the compiler itself and haven't built libstd from source.\n You can usually build it with `x.py build library/std`. More information\n about x.py is available in the [rustc-dev-guide].\n\n[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#building-the-compiler\n"},"level":"error","spans":[{"file_name":"src/lib.rs","byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1,"is_primary":true,"text":[],"label":"can't find crate","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the `riscv64gc-unknown-linux-gnu` target may not be installed","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"consider downloading the target with `rustup target add riscv64gc-unknown-linux-gnu`","code":null,"level":"help","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[1m\u001b[91merror[E0463]\u001b[0m\u001b[1m: can't find crate for `core`\u001b[0m\n \u001b[1m\u001b[94m|\u001b[0m\n \u001b[1m\u001b[94m= \u001b[0m\u001b[1mnote\u001b[0m: the `riscv64gc-unknown-linux-gnu` target may not be installed\n \u001b[1m\u001b[94m= \u001b[0m\u001b[1mhelp\u001b[0m: consider downloading the target with `rustup target add riscv64gc-unknown-linux-gnu`\n\n"}
{"$message_type":"diagnostic","message":"aborting due to 1 previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[1m\u001b[91merror\u001b[0m\u001b[1m: aborting due to 1 previous error\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"For more information about this error, try `rustc --explain E0463`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"\u001b[1mFor more information about this error, try `rustc --explain E0463`.\u001b[0m\n"}

View File

@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by cargo.
# For information about cache directory tags see https://bford.info/cachedir/

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1,3 @@
{"$message_type":"diagnostic","message":"can't find crate for `core`","code":{"code":"E0463","explanation":"A crate was declared but cannot be found.\n\nErroneous code example:\n\n```compile_fail,E0463\nextern crate foo; // error: can't find crate\n```\n\nYou need to link your code to the relevant crate in order to be able to use it\n(through Cargo or the `-L` option of rustc, for example).\n\n## Common causes\n\n- The crate is not present at all. If using Cargo, add it to `[dependencies]`\n in Cargo.toml.\n- The crate is present, but under a different name. If using Cargo, look for\n `package = ` under `[dependencies]` in Cargo.toml.\n\n## Common causes for missing `std` or `core`\n\n- You are cross-compiling for a target which doesn't have `std` prepackaged.\n Consider one of the following:\n + Adding a pre-compiled version of std with `rustup target add`\n + Building std from source with `cargo build -Z build-std`\n + Using `#![no_std]` at the crate root, so you won't need `std` in the first\n place.\n- You are developing the compiler itself and haven't built libstd from source.\n You can usually build it with `x.py build library/std`. More information\n about x.py is available in the [rustc-dev-guide].\n\n[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#building-the-compiler\n"},"level":"error","spans":[{"file_name":"src/main.rs","byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1,"is_primary":true,"text":[],"label":"can't find crate","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the `riscv64gc-unknown-none-elf` target may not be installed","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"consider downloading the target with `rustup target add riscv64gc-unknown-none-elf`","code":null,"level":"help","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[1m\u001b[91merror[E0463]\u001b[0m\u001b[1m: can't find crate for `core`\u001b[0m\n \u001b[1m\u001b[94m|\u001b[0m\n \u001b[1m\u001b[94m= \u001b[0m\u001b[1mnote\u001b[0m: the `riscv64gc-unknown-none-elf` target may not be installed\n \u001b[1m\u001b[94m= \u001b[0m\u001b[1mhelp\u001b[0m: consider downloading the target with `rustup target add riscv64gc-unknown-none-elf`\n\n"}
{"$message_type":"diagnostic","message":"aborting due to 1 previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[1m\u001b[91merror\u001b[0m\u001b[1m: aborting due to 1 previous error\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"For more information about this error, try `rustc --explain E0463`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"\u001b[1mFor more information about this error, try `rustc --explain E0463`.\u001b[0m\n"}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1,3 @@
{"$message_type":"diagnostic","message":"can't find crate for `core`","code":{"code":"E0463","explanation":"A crate was declared but cannot be found.\n\nErroneous code example:\n\n```compile_fail,E0463\nextern crate foo; // error: can't find crate\n```\n\nYou need to link your code to the relevant crate in order to be able to use it\n(through Cargo or the `-L` option of rustc, for example).\n\n## Common causes\n\n- The crate is not present at all. If using Cargo, add it to `[dependencies]`\n in Cargo.toml.\n- The crate is present, but under a different name. If using Cargo, look for\n `package = ` under `[dependencies]` in Cargo.toml.\n\n## Common causes for missing `std` or `core`\n\n- You are cross-compiling for a target which doesn't have `std` prepackaged.\n Consider one of the following:\n + Adding a pre-compiled version of std with `rustup target add`\n + Building std from source with `cargo build -Z build-std`\n + Using `#![no_std]` at the crate root, so you won't need `std` in the first\n place.\n- You are developing the compiler itself and haven't built libstd from source.\n You can usually build it with `x.py build library/std`. More information\n about x.py is available in the [rustc-dev-guide].\n\n[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#building-the-compiler\n"},"level":"error","spans":[{"file_name":"src/main.rs","byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1,"is_primary":true,"text":[],"label":"can't find crate","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the `riscv64gc-unknown-none-elf` target may not be installed","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"consider downloading the target with `rustup target add riscv64gc-unknown-none-elf`","code":null,"level":"help","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[1m\u001b[91merror[E0463]\u001b[0m\u001b[1m: can't find crate for `core`\u001b[0m\n \u001b[1m\u001b[94m|\u001b[0m\n \u001b[1m\u001b[94m= \u001b[0m\u001b[1mnote\u001b[0m: the `riscv64gc-unknown-none-elf` target may not be installed\n \u001b[1m\u001b[94m= \u001b[0m\u001b[1mhelp\u001b[0m: consider downloading the target with `rustup target add riscv64gc-unknown-none-elf`\n\n"}
{"$message_type":"diagnostic","message":"aborting due to 1 previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[1m\u001b[91merror\u001b[0m\u001b[1m: aborting due to 1 previous error\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"For more information about this error, try `rustc --explain E0463`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"\u001b[1mFor more information about this error, try `rustc --explain E0463`.\u001b[0m\n"}

126
apps/subject_zig/main.zig Normal file
View File

@ -0,0 +1,126 @@
const std = @import("std");
// 1. The SysTable Contract (Must match Kernel!)
const ION_BASE = 0x83000000;
// The Physical Token representing a packet
const IonPacket = extern struct {
data: u64, // Virtual Addr (ptr)
phys: u64, // Physical Addr
len: u16,
id: u16,
};
const RingBuffer = extern struct {
// Nim Kernel RingBuffer Layout:
// data: array[N, T]
// head: Cursor (Atomic[int64], padded to 64 bytes)
// tail: Cursor (Atomic[int64], padded to 64 bytes)
data: [256]IonPacket,
// Head Cursor
head_val: i64,
head_pad: [56]u8,
// Tail Cursor
tail_val: i64,
tail_pad: [56]u8,
};
const SysTable = extern struct {
magic: u32,
s_rx: *RingBuffer, // Kernel writes, We read
s_tx: *RingBuffer, // We write (Network Data)
s_event: *RingBuffer, // We write (Telemetry/Events)
};
// 2. The Direct Accessor
fn get_systable() *SysTable {
return @ptrFromInt(ION_BASE);
}
// 3. The Entry Point
export fn main() c_int {
// A. Announce presence
print("[ZIG] ION Raw Test: Engaging...\n");
const sys = get_systable();
// B. Verify Magic (Sanity Check)
print("[ZIG] Checking SysTable at 0x83000000...\n");
if (sys.magic == 0x4E585553) {
print("[ZIG] MAGIC VERIFIED: 0x4E585553 ('NXUS')\n");
} else {
print("[ZIG] MAGIC FAIL: 0x");
print("Unknown\n");
}
// C. ALLOCATE (Simulated for Raw Test)
const pkt = IonPacket{
.data = 0xDEADBEEF,
.phys = 0xCAFEBABE,
.len = 42,
.id = 1,
};
// D. PUSH to TX Ring (Network Sim)
{
const tx = sys.s_tx;
const head = @atomicLoad(i64, &tx.head_val, .monotonic);
const head_u64: u64 = @bitCast(head);
const head_idx: u32 = @truncate(head_u64);
tx.data[head_idx % 256] = pkt;
@atomicStore(i64, &tx.head_val, head + 1, .release);
print("[ZIG] Network Packet pushed to TX Ring.\n");
}
// E. PUSH to EVENT Ring (Telemetry Sim)
{
const ev = sys.s_event;
const head = @atomicLoad(i64, &ev.head_val, .monotonic);
const head_u64: u64 = @bitCast(head);
const head_idx: u32 = @truncate(head_u64);
const event = IonPacket{
.data = 0,
.phys = 0,
.len = 0,
.id = 777, // Event Type: 777 (Test Event)
};
ev.data[head_idx % 256] = event;
@atomicStore(i64, &ev.head_val, head + 1, .release);
print("[ZIG] Telemetry Event pushed to EVENT Ring.\n");
}
// F. YIELD / PUMP (Let Kernel Process)
print("[ZIG] Yielding to Kernel...\n");
fiber_yield();
print("[ZIG] Control returned. Test Complete.\n");
while (true) {
fiber_yield();
}
return 0;
}
// Minimal Shims
extern fn write(fd: c_int, buf: [*]const u8, count: usize) isize;
extern fn fiber_yield() void;
fn print(text: []const u8) void {
_ = write(1, text.ptr, text.len);
}
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
_ = error_return_trace;
_ = ret_addr;
print("\n[Zig] PANIC: ");
print(msg);
print("\n");
while (true) {}
}

View File

@ -220,7 +220,7 @@ nim c \
--mm:arc \
--noMain:on \
--cc:clang \
--passC:"-target ${ZIG_TARGET/-freestanding-none/-unknown-none} -ffreestanding -fno-stack-protector -fno-builtin $ARCH_FLAGS -I$RUMPK_DIR/core/include -I$RUMPK_DIR/core/net -I$RUMPK_DIR/vendor/lwip/src/include" \
--passC:"-target ${ZIG_TARGET/-freestanding-none/-unknown-none} -ffreestanding -fno-stack-protector -fno-builtin $ARCH_FLAGS -I$RUMPK_DIR/core/include" \
--define:useMalloc \
--define:nimNoLibc \
--define:noSignalHandler \
@ -261,8 +261,6 @@ for cfile in "$BUILD_DIR/nimcache"/*.c; do
-I"$RUMPK_DIR/core/include" \
-I/usr/lib/nim \
-I"$RUMPK_DIR/core" \
-I"$RUMPK_DIR/core/net" \
-I"$RUMPK_DIR/vendor/lwip/src/include" \
-c "$cfile" \
-o "$ofile"
NIM_OBJS="$NIM_OBJS $ofile"
@ -312,7 +310,6 @@ zig cc \
-fno-builtin \
-O2 \
-I"$RUMPK_DIR/core/include" \
-I"$RUMPK_DIR/core/net" \
-I"$RUMPK_DIR/libs/membrane/include" \
-I"$RUMPK_DIR/vendor/lwip/src/include" \
-c "$RUMPK_DIR/libs/membrane/sys_arch.c" \
@ -351,7 +348,6 @@ for cfile in "$BUILD_DIR/membrane_nimcache"/*.c; do
-I/usr/lib/nim \
-I"$RUMPK_DIR/core" \
-I"$RUMPK_DIR/libs/membrane" \
-I"$RUMPK_DIR/core/net" \
-I"$RUMPK_DIR/libs/membrane/include" \
-I"$RUMPK_DIR/vendor/lwip/src/include" \
-c "$cfile" \

View File

@ -7,10 +7,12 @@
| File | Purpose |
|------|---------|
| `kernel.nim` | Main entry point (`kmain`), fiber test |
| `kernel.nim` | Main Orchestrator (`kmain`) |
| `ion.nim` | ION Control Plane & Channel API |
| `fiber.nim` | Cooperative fiber abstraction |
| `ring.nim` | Lock-free Disruptor ring buffer |
| `panicoverride.nim` | Nim panic handler for freestanding |
| `watchdog.nim` | Autonomous Immune System (Healer) |
| `ring.nim` | Lock-free Sovereign ring buffers |
| `panicoverride.nim` | Freestanding panic handler |
## Architecture Independence

View File

@ -1,31 +0,0 @@
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
# RUMPK CORE // BUS
# The Global Message Bus for Nexus Channels.
#
# This registry allows Fibers to discover Channels by SipHash ID.
{.push stackTrace: off, lineTrace: off.}
import channel
const MAX_CHANNELS = 32
type
Bus* = object
channels*: array[MAX_CHANNELS, ptr Channel[64]] # Fixed size for now
count*: int
var global_bus*: Bus
proc register*(chan: ptr Channel[64]) =
if global_bus.count < MAX_CHANNELS:
global_bus.channels[global_bus.count] = chan
inc global_bus.count
proc findChannel*(id: ChannelID): ptr Channel[64] =
for i in 0..<global_bus.count:
if global_bus.channels[i].id == id:
return global_bus.channels[i]
return nil
{.pop.}

View File

@ -25,7 +25,7 @@ type
size*: uint64
Channel*[N: static[int]] = object
## A named pipe carrying Typed Messages
## A typed channel carrying Messages
id*: ChannelID
name*: cstring
buffer*: RingBuffer[Message, N]

View File

@ -1,39 +0,0 @@
# Markus Maiwald (Architect) | Voxis Forge (AI)
# RUMPK CORE // CRYPTO
# Wrapper for Monocypher
{.push stackTrace: off, lineTrace: off.}
# Monocypher ABI
# int crypto_eddsa_check(const uint8_t sig[64], const uint8_t pub_key[32], const uint8_t *msg, size_t msg_size);
# Returns 0 on success, -1 on failure.
proc crypto_eddsa_check(sig: ptr uint8,
pub_key: ptr uint8,
msg: pointer,
msg_size: csize_t): cint
{.importc: "crypto_eddsa_check", header: "monocypher.h".}
# The Root of Trust (Hardcoded Public Key for now)
# Enforce 16-byte alignment because Monocypher v4 uses SIMD ldp/stp (Q registers)
# Using 'let' to ensure it resides in initialized data section.
let ROOT_PUB_KEY* {.align: 16.}: array[32, uint8] = [
0x19'u8, 0xD3, 0xD9, 0x19, 0x47, 0x5D, 0xEE, 0xD4,
0x69, 0x6B, 0x5D, 0x13, 0x01, 0x81, 0x51, 0xD1,
0xAF, 0x88, 0xB2, 0xBD, 0x3B, 0xCF, 0xF0, 0x48,
0xB4, 0x50, 0x31, 0xC1, 0xF3, 0x6D, 0x18, 0x58
]
proc verify_npl_signature*(sig: array[64, uint8], body_ptr: pointer,
body_len: uint64): bool =
# signature 'sig' is passed by value (copied on stack)
# AArch64 stack is 16-byte aligned, so sig should be fine if we ensure it.
var sig_aligned {.align: 16.} = sig
let s_ptr = unsafeAddr sig_aligned[0]
let p_ptr = unsafeAddr ROOT_PUB_KEY[0]
let check_res = crypto_eddsa_check(s_ptr, p_ptr, body_ptr, cast[csize_t](body_len))
return check_res == 0
{.pop.}

View File

@ -183,11 +183,5 @@ int atoi(const char *nptr) {
return res;
}
int errno = 0;
/* LwIP sys_now implementation */
extern unsigned int get_ticks(void);
unsigned int sys_now(void) {
return get_ticks();
}

View File

@ -7,8 +7,8 @@ export memory
type
CmdType* = enum
CMD_NONE = 0
CMD_NET_STOP = 1
CMD_NET_START = 2
CMD_ION_STOP = 1
CMD_ION_START = 2
CMD_DROP_ALL = 3
CmdPacket* = object

View File

@ -1,121 +0,0 @@
# ION Soft-Switch
# Sovereign Dispatch Logic
import memory
import ../ring
import ../net # For LwIP fallback
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
type
FlowType* = enum
FLOW_LWIP # The Unix Path
FLOW_DIRECT # The ION Path
# A Subscription to the Bus
NetFlow* = object
port*: uint16
ring*: ptr RingBuffer[IonPacket, 256] # Direct injection ring
fType*: FlowType
var
# The Lookup Table (Simple Array for Phase 7)
# Index = Port Number.
flow_table: array[65536, ptr NetFlow]
proc ion_register*(port: uint16, flow: ptr NetFlow) =
flow_table[port] = flow
proc parse_dest_port(data: ptr UncheckedArray[byte]): uint16 =
# Ethernet Type at 12. IP Protocol at 23. Dest Port at 36.
if data[12] == 0x08 and data[13] == 0x00:
# IPv4
let proto = data[23]
if proto == 17: # UDP
let dport = (uint16(data[36]) shl 8) or uint16(data[37])
return dport
return 0
proc dispatch_packet(data: ptr UncheckedArray[byte], len: int, id: uint16) =
let dest_port = parse_dest_port(data)
let flow = if dest_port != 0: flow_table[dest_port] else: nil
if dest_port == 8080:
var msg = "[ION SW] 8080 Hit! RingPtr="
console_write(addr msg[0], csize_t(msg.len))
# Simple address check (first 8 bytes of ptr)
if flow != nil:
var hex_str = "ADR\n"
console_write(addr hex_str[0], 4)
var pkt: IonPacket
pkt.id = id
pkt.len = uint16(len)
pkt.data = data
if flow != nil and flow.fType == FLOW_DIRECT:
if flow.ring[].push(pkt):
var msg = "[ION SW] Pushed to Ring!\n"
console_write(addr msg[0], csize_t(msg.len))
else:
var msg = "[ION SW] Ring FULL!\n"
console_write(addr msg[0], csize_t(msg.len))
ion_free_raw(id)
else:
discard net_ingest_packet(cast[ptr byte](pkt.data), int(pkt.len))
ion_free_raw(id)
proc ion_ingress*(id: uint16, len: uint16) {.exportc.} =
## The Hot Path. Called by VirtIO Interrupt/Poller.
## Takes a Slab ID that has been filled by NIC or local TX.
const VIRTIO_NET_HDR_SIZE = 10
let slab_base = ion_get_virt(id)
if len <= VIRTIO_NET_HDR_SIZE:
# Packet too small (just header or less)
ion_free_raw(id)
return
# Adjust for Headroom (Zero-Copy Pointer Math)
# eth_frame points to the Ethernet Header, skipping VirtIO Header
let eth_frame = cast[ptr UncheckedArray[byte]](cast[uint](slab_base) + VIRTIO_NET_HDR_SIZE)
let eth_len = int(len) - VIRTIO_NET_HDR_SIZE
# DEBUG: Print RX packet info (Full Eth Header)
var prefix = "[ION] RX: "
console_write(addr prefix[0], csize_t(prefix.len))
const hexDigits = "0123456789ABCDEF"
for i in 0..<14:
let b = eth_frame[i]
var hex: array[3, char]
hex[0] = hexDigits[int(b shr 4)]
hex[1] = hexDigits[int(b and 0xF)]
hex[2] = if i == 5 or i == 11: '|' else: ' '
if i == 13: hex[2] = '\n'
console_write(addr hex[0], 3)
dispatch_packet(eth_frame, eth_len, id)
proc ion_egress*(pkt: IonPacket) {.exportc.} =
## The Fast Path TX (Standard Interface)
if not ion_tx_push(pkt):
# Backpressure / Ring Full -> Drop
var msg = "[ION SW] TX Ring FULL! Dropping.\n"
console_write(addr msg[0], csize_t(msg.len))
ion_free(pkt)
proc ion_egress_to_port*(port: uint16, pkt: IonPacket) {.exportc.} =
## Route a packet to a specific ION Port.
## Port 0 is reserved for Kernel Console.
if port == 0:
when defined(is_kernel):
console_write(pkt.data, csize_t(pkt.len))
ion_free(pkt)
else:
# In the Membrane, Port 0 egresses to the Bus
ion_egress(pkt)
else:
# Future: Internal routing via flow_table
ion_egress(pkt)

View File

@ -1,5 +1,5 @@
# ION Memory Manager
# The "Slab Allocator" for Zero-Copy Networking
# The "Slab Allocator" for Zero-Copy IO
import ../ring
@ -33,6 +33,7 @@ var global_pool: PacketPool
proc ion_pool_init*() {.exportc.} =
## Initialize the DMA Pool with REAL Physical Address
dbg("[ION] Initializing Pool...")
# 1. Get the VIRTUAL address of the static buffer
let virt_addr = cast[uint64](addr global_pool.buffer[0])
@ -40,18 +41,17 @@ proc ion_pool_init*() {.exportc.} =
# 2. Translate to PHYSICAL (Identity Mapped for Phase 7)
global_pool.base_phys = virt_addr
dbg("[ION] Pool Phys Base: " & $global_pool.base_phys) # Basic int print, need hex for full confirmation but this proves non-zero
dbg("[ION] Ring Init...")
global_pool.free_ring.init()
# Fill the free ring with all indices [0..1023]
# Fill the free ring with all indices [0..1023]
dbg("[ION] Filling Slabs...")
var count = 0
for i in 0 ..< POOL_COUNT:
if global_pool.free_ring.push(uint16(i)):
inc count
dbg("[ION] Pushed " & $count & " slabs to ring.")
dbg("[ION] Pool Ready.")
proc ion_alloc*(): IonPacket {.exportc.} =
## O(1) Allocation. Returns an empty packet struct.

View File

@ -7,7 +7,7 @@ import fiber
import ion
var net_paused*: bool = false
var ion_paused*: bool = false
var pause_start*: uint64 = 0
@ -15,12 +15,12 @@ var pause_start*: uint64 = 0
# Fiber Management (Forward Declared)
# =========================================================
var fiber_net: FiberObject
var fiber_ion: FiberObject
var fiber_nexshell: FiberObject
var fiber_subject: FiberObject
var fiber_watchdog: FiberObject
# POSIX-like exports for Zig NPLs
# Exports for Zig NPLs
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
proc write*(fd: cint, p: pointer, len: csize_t): csize_t {.exportc, cdecl.} =
console_write(p, len)
@ -37,14 +37,14 @@ proc kprintln*(s: cstring) {.exportc, cdecl.} =
kprint(s); kprint("\n")
proc rumpk_yield_internal() {.cdecl, exportc.} =
if current_fiber == addr fiber_net:
if current_fiber == addr fiber_ion:
switch(addr fiber_nexshell)
elif current_fiber == addr fiber_nexshell:
switch(addr fiber_subject)
elif current_fiber == addr fiber_subject:
switch(addr fiber_watchdog)
else:
switch(addr fiber_net)
switch(addr fiber_ion)
proc fiber_yield*() {.exportc, cdecl.} =
rumpk_yield_internal()
@ -74,7 +74,7 @@ var chan_cmd*: SovereignChannel[CmdPacket]
# HAL/NPL Entry points
proc rumpk_halt() {.importc, cdecl, noreturn.}
proc virtio_net_init() {.importc, cdecl.}
proc hal_io_init() {.importc, cdecl.}
proc nexshell_main() {.importc, cdecl.}
proc launch_subject() {.importc, cdecl.}
@ -94,7 +94,7 @@ proc nimPanic(msg: cstring) {.exportc: "panic", cdecl, noreturn.} =
# Fiber Entries
# =========================================================
var stack_net: array[32768, uint8]
var stack_ion: array[32768, uint8]
var stack_nexshell: array[32768, uint8]
var stack_subject: array[65536, uint8]
var stack_watchdog: array[4096, uint8]
@ -105,9 +105,9 @@ proc subject_fiber_entry() {.cdecl.} =
# Include Watchdog Logic (Access to Kernel Globals)
include watchdog
proc net_fiber_entry() {.cdecl.} =
kprint("[Net] Fiber 1 Reporting for Duty.")
if net_paused: kprintln(" (PAUSED)") else: kprintln("")
proc ion_fiber_entry() {.cdecl.} =
kprint("[ION] Fiber 1 Reporting for Duty.")
if ion_paused: kprintln(" (PAUSED)") else: kprintln("")
var pkt: IonPacket
var cmd: CmdPacket
@ -115,21 +115,21 @@ proc net_fiber_entry() {.cdecl.} =
while true:
# 1. Process Commands
if chan_cmd.recv(cmd):
if cmd.kind == uint32(CMD_NET_STOP):
kprintln("[Net] STOP received. Suspending IO.")
net_paused = true
if cmd.kind == uint32(CMD_ION_STOP):
kprintln("[ION] STOP received. Suspending IO.")
ion_paused = true
pause_start = cpu_ticks()
elif cmd.kind == uint32(CMD_NET_START):
kprintln("[Net] START received. Resuming IO.")
net_paused = false
elif cmd.kind == uint32(CMD_ION_START):
kprintln("[ION] START received. Resuming IO.")
ion_paused = false
# 2. Process Data (if not paused)
if not net_paused:
if not ion_paused:
if chan_tx.recv(pkt):
kprintln("[Net] Packet intercepted. Generating Telemetry...")
kprintln("[ION] Packet intercepted. Generating Telemetry...")
var alert = IonPacket(id: 777, len: 42)
chan_event.send(alert)
kprintln("[Net] Event dispatched.")
kprintln("[ION] Event dispatched.")
fiber_yield()
@ -147,7 +147,7 @@ proc kmain() {.exportc, cdecl.} =
# 1. Hardware & Memory
kprintln("[Kernel] Initializing Memory Substrate...")
ion_pool_init()
virtio_net_init()
hal_io_init()
# 2. Channel Infrastructure
kprintln("[Kernel] Mapping Sovereign Channels...")
@ -183,8 +183,8 @@ proc kmain() {.exportc, cdecl.} =
# 4. Deployment
kprintln("[Kernel] Spawning System Fibers...")
# 1. NETWORK FIBER (The Valve)
init_fiber(addr fiber_net, net_fiber_entry, addr stack_net[0], sizeof(stack_net))
# 1. ION FIBER (The Valve)
init_fiber(addr fiber_ion, ion_fiber_entry, addr stack_ion[0], sizeof(stack_ion))
# 2. NEXSHELL FIBER (The Brain)
init_fiber(addr fiber_nexshell, nexshell_main, addr stack_nexshell[0], sizeof(stack_nexshell))
@ -199,6 +199,6 @@ proc kmain() {.exportc, cdecl.} =
kprintln("[Kernel] All Systems Go. Entering Autonomous Loop.")
# Handover to Scheduler (The Heartbeat)
switch(addr fiber_net)
switch(addr fiber_ion)
{.pop.}

View File

@ -1,225 +0,0 @@
# Rumpk LwIP Bridge
# FFI wrapper for LwIP static library
import ring
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
const
MAX_PACKET_SIZE = 1536
RING_SIZE = 256
type
LwipErr* = int8
const
ERR_OK* = 0
ERR_MEM* = -1
ERR_BUF* = -2
ERR_TIMEOUT* = -3
ERR_RTE* = -4
ERR_INPROGRESS* = -5
ERR_VAL* = -6
ERR_WOULDBLOCK* = -7
ERR_USE* = -8
ERR_ALREADY* = -9
ERR_ISCONN* = -10
ERR_CONN* = -11
ERR_IF* = -12
ERR_ABRT* = -13
ERR_RST* = -14
ERR_CLSD* = -15
ERR_ARG* = -16
type
PbufLayer* = cint
PbufType* = cint
Pbuf* {.importc: "struct pbuf", header: "lwip/pbuf.h",
incompleteStruct.} = object
next*: ptr Pbuf
payload*: pointer
tot_len*: uint16
len*: uint16
IpAddr* {.importc: "ip4_addr_t", header: "lwip/ip_addr.h".} = object
addr_val* {.importc: "addr".}: uint32
NetIf* {.importc: "struct netif", header: "lwip/netif.h",
incompleteStruct.} = object
next*: ptr NetIf
ip_addr*, netmask*, gw*: IpAddr
var
PBUF_RAW* {.importc: "PBUF_RAW", header: "lwip/pbuf.h", nodecl.}: cint
PBUF_RAM* {.importc: "PBUF_RAM", header: "lwip/pbuf.h", nodecl.}: cint
PBUF_POOL* {.importc: "PBUF_POOL", header: "lwip/pbuf.h", nodecl.}: cint
type
NetPacket* = object
len*: int
data*: array[MAX_PACKET_SIZE, byte]
var netRing*: RingBuffer[NetPacket, RING_SIZE]
var rumpk_netif*: NetIf
var ip, mask, gw: IpAddr
# FFI Procedures
proc lwip_init*() {.importc: "lwip_init", header: "lwip/init.h".}
proc netif_add*(netif: ptr NetIf; ipaddr, netmask, gw: ptr IpAddr; state: pointer;
init: proc(netif: ptr NetIf): LwipErr {.cdecl.};
input: proc(p: ptr Pbuf; netif: ptr NetIf): LwipErr {.cdecl.}): ptr NetIf {.importc: "netif_add",
header: "lwip/netif.h".}
proc netif_set_up*(netif: ptr NetIf) {.importc: "netif_set_up",
header: "lwip/netif.h".}
proc netif_set_link_up*(netif: ptr NetIf) {.importc: "netif_set_link_up",
header: "lwip/netif.h".}
proc netif_set_default*(netif: ptr NetIf) {.importc: "netif_set_default",
header: "lwip/netif.h".}
proc sys_check_timeouts() {.importc: "sys_check_timeouts",
header: "lwip/timeouts.h".}
proc pbuf_alloc*(layer: PbufLayer; length: uint16;
ptype: PbufType): ptr Pbuf {.importc: "pbuf_alloc", header: "lwip/pbuf.h".}
proc pbuf_free*(p: ptr Pbuf): uint8 {.importc: "pbuf_free",
header: "lwip/pbuf.h".}
proc ethernet_input*(p: ptr Pbuf; netif: ptr NetIf): LwipErr {.importc: "ethernet_input",
header: "netif/ethernet.h".}
# Sovereign Integration (HAL)
proc virtio_net_poll() {.importc: "virtio_net_poll", cdecl.}
proc virtio_net_send(data: pointer; len: csize_t) {.importc: "virtio_net_send", cdecl.}
# Architecture Agnostic IP Packing
func htonl(x: uint32): uint32 =
when cpuEndian == littleEndian:
(x shr 24) or ((x shr 8) and 0xff00) or ((x shl 8) and 0xff0000) or (x shl 24)
else: x
func packIp(a, b, c, d: uint8): uint32 =
uint32(a) shl 24 or uint32(b) shl 16 or uint32(c) shl 8 or uint32(d)
proc link_output(netif: ptr NetIf; p: ptr Pbuf): LwipErr {.cdecl.} =
## Callback from LwIP when a packet needs to be sent
if p != nil:
# Phase 7: We send the whole packet in one go.
virtio_net_send(p.payload, csize_t(p.tot_len))
return ERR_OK
return ERR_VAL
proc net_driver_init*(netif: ptr NetIf): LwipErr {.cdecl.} =
# Driver initialization hook
{.emit: """
((struct netif*)`netif`)->mtu = 1500;
((struct netif*)`netif`)->hwaddr_len = 6;
((struct netif*)`netif`)->hwaddr[0] = 0x52;
((struct netif*)`netif`)->hwaddr[1] = 0x54;
((struct netif*)`netif`)->hwaddr[2] = 0x00;
((struct netif*)`netif`)->hwaddr[3] = 0x12;
((struct netif*)`netif`)->hwaddr[4] = 0x34;
((struct netif*)`netif`)->hwaddr[5] = 0x56;
// NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_ETHERNET
((struct netif*)`netif`)->flags = 0x02 | 0x08 | 0x10 | 0x40;
// Wire Tx output
((struct netif*)`netif`)->linkoutput = `link_output`;
""".}
return ERR_OK
proc net_init*() =
## Initialize the networking subsystem
netRing.init()
lwip_init()
# QEMU User Networking Defaults (10.0.2.15)
ip.addr_val = htonl(packIp(10, 0, 2, 15))
mask.addr_val = htonl(packIp(255, 255, 255, 0))
gw.addr_val = htonl(packIp(10, 0, 2, 2))
# Register the Interface
discard netif_add(addr rumpk_netif, addr ip, addr mask, addr gw,
nil, net_driver_init,
cast[proc(p: ptr Pbuf;
netif: ptr NetIf): LwipErr {.cdecl.}](ethernet_input))
# Bring it UP
netif_set_up(addr rumpk_netif)
netif_set_link_up(addr rumpk_netif)
netif_set_default(addr rumpk_netif)
# Force Gratuitous ARP to announce our MAC to the network/SLIRP
proc etharp_gratuitous(netif: ptr NetIf) {.importc: "etharp_gratuitous",
header: "netif/etharp.h".}
etharp_gratuitous(addr rumpk_netif)
proc net_ingest_packet*(data: ptr byte; len: int): bool {.exportc.} =
## Ingest a raw ethernet frame from the hardware
var pkt: NetPacket
if len > MAX_PACKET_SIZE: return false
pkt.len = len
copyMem(addr pkt.data[0], data, len)
return netRing.push(pkt)
proc fiber_yield() =
# Don't use WFI - it blocks without interrupts configured
# Use simple spin-loop for now
for i in 0..100:
{.emit: "asm volatile(\"nop\");".}
proc net_loop_cycle*(netif: ptr NetIf) =
## One cycle of the networking logic (Poll + Drain + LwIP)
# 1. Poll Hardware
virtio_net_poll()
# 2. Drain the Ring
var work_done = false
while not netRing.isEmpty:
let (ok, pkt) = netRing.pop()
if ok:
work_done = true
let p = pbuf_alloc(PBUF_RAW, uint16(pkt.len), PBUF_POOL)
if p != nil:
copyMem(p.payload, unsafeAddr pkt.data[0], pkt.len)
let err = ethernet_input(p, netif)
if err != ERR_OK:
var msg = "[Net] ethernet_input failed\n"
console_write(addr msg[0], csize_t(msg.len))
discard pbuf_free(p)
else:
var msg = "[Net] pbuf_alloc FAILED (OOM?)\n"
console_write(addr msg[0], csize_t(msg.len))
# 3. LwIP Maintenance
sys_check_timeouts()
# 4. Periodic Activity (Every 5000 loops)
const PERIOD = 5000
var counter {.global.} = 0
counter += 1
if counter >= PERIOD:
counter = 0
# Send UDP Heartbeat to Gateway
var frame: array[64, byte]
# (Simplified frame construction for clarity)
for i in 0..63: frame[i] = 0
frame[0] = 0x52; frame[1] = 0x55; frame[2] = 0x0A; frame[3] = 0x00; frame[
4] = 0x02; frame[5] = 0x02 # Dst
frame[6] = 0x52; frame[7] = 0x54; frame[8] = 0x00; frame[9] = 0x12; frame[
10] = 0x34; frame[11] = 0x56 # Src
frame[12] = 0x08; frame[13] = 0x00 # IPv4
frame[14] = 0x45; frame[23] = 17 # UDP
frame[26] = 10; frame[27] = 0; frame[28] = 2; frame[29] = 15 # Src IP
frame[30] = 10; frame[31] = 0; frame[32] = 2; frame[33] = 2 # Dst IP
frame[34] = 0x1F; frame[35] = 0x90; frame[36] = 0x1F; frame[37] = 0x90 # Ports 8080
frame[42] = ord('H').byte; frame[43] = ord('I').byte
virtio_net_send(addr frame[0], 64)
# 5. Yield / Governor
if not work_done:
fiber_yield()

View File

@ -1,39 +0,0 @@
#ifndef LWIP_HDR_CC_H
#define LWIP_HDR_CC_H
#include <stdint.h>
#include <stddef.h>
// 1. Basic Types
typedef uint8_t u8_t;
typedef int8_t s8_t;
typedef uint16_t u16_t;
typedef int16_t s16_t;
typedef uint32_t u32_t;
typedef int32_t s32_t;
typedef uintptr_t mem_ptr_t;
typedef int sys_prot_t;
// 2. Format specifiers
#define U16_F "hu"
#define S16_F "hd"
#define X16_F "hx"
#define U32_F "u"
#define S32_F "d"
#define X32_F "x"
#define X8_F "02x"
#define SZT_F "zu"
// 3. Byte order
#define BYTE_ORDER LITTLE_ENDIAN
// 4. Compiler hints
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END
#define PACK_STRUCT_STRUCT __attribute__((packed))
#define PACK_STRUCT_FIELD(x) x
// 5. Diagnostics
void printf(const char *format, ...);
#endif

View File

@ -1,5 +0,0 @@
#ifndef LWIP_HDR_PERF_H
#define LWIP_HDR_PERF_H
#define LWIP_PERF_START
#define LWIP_PERF_STOP(x)
#endif

View File

@ -1,38 +0,0 @@
#ifndef LWIP_HDR_LWIPOPTS_H
#define LWIP_HDR_LWIPOPTS_H
// 1. The Unikernel Mode (No OS threads)
#define NO_SYS 1
#define LWIP_TIMERS 1 // We must call sys_check_timeouts() manually
// 1.1 Disable Sequential/Socket APIs
#define LWIP_NETCONN 0
#define LWIP_SOCKET 0
#define LWIP_STATS 0
#define SYS_LIGHTWEIGHT_PROT 0
#define LWIP_ETHERNET 1
// 2. Memory Strategy (Static Slabs - No Heap)
#define MEM_LIBC_MALLOC 0
#define MEMP_MEM_MALLOC 0
#define MEM_ALIGNMENT 64 // Cache Line Alignment (Critical for Disruptor)
// 3. Performance Tuning (Sovereign Scale)
#define TCP_MSS 1460
#define TCP_WND (8 * TCP_MSS)
#define LWIP_TCP_KEEPALIVE 1
// 4. Checksum Offload (Let Hardware do it if VirtIO supports it)
// For now, software checksums to be safe on QEMU
#define CHECKSUM_GEN_IP 1
#define CHECKSUM_GEN_TCP 1
// 6. Freestanding overrides
#define LWIP_NO_INTTYPES_H 1
// 5. Debugging (The HUD Needs Logs)
#define LWIP_DEBUG 1
#define LWIP_PLATFORM_DIAG(x) do { printf x; } while(0)
#define LWIP_PLATFORM_ASSERT(x) do { printf("ASSERT: %s\n", x); } while(0)
#endif

View File

@ -1,123 +0,0 @@
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
# RUMPK CORE // NPL FORMAT
# The Contract of Execution.
{.push stackTrace: off, lineTrace: off.}
import crypto
# =========================================================
# Constants
# =========================================================
const NPL_MAGIC*: array[4, uint8] = [0x7F'u8, 0x4E'u8, 0x50'u8, 0x4C'u8]
const NPL_VERSION* = 1'u8
const ARCH_ARM64* = 0xAA'u8
const ARCH_X86_64* = 0xEE'u8
const ARCH_RISCV64* = 0x55'u8
const NPL_HEADER_SIZE* = 128
# =========================================================
# Types
# =========================================================
type
NPLHeader* {.packed.} = object
magic*: array[4, uint8]
version*: uint8
arch*: uint8
flags*: uint16
reserved0*: array[8, uint8] # Alignment padding for signature
signature*: array[64, uint8]
body_size*: uint64
reserved1*: array[40, uint8] # Remaining padding
PayloadEntry* = proc() {.cdecl.}
# Global last error (avoids struct return issues)
var nplLastError*: cstring = nil
# =========================================================
# Architecture Detection
# =========================================================
proc currentArch*(): uint8 =
when defined(arm64) or defined(aarch64):
return ARCH_ARM64
elif defined(amd64) or defined(x86_64):
return ARCH_X86_64
elif defined(riscv64):
return ARCH_RISCV64
else:
return 0x00'u8
# =========================================================
# NPL Loader (returns nil on failure, sets nplLastError)
# =========================================================
proc loadNpl*(rawPtr: pointer, maxLen: uint64): PayloadEntry =
nplLastError = nil
if rawPtr == nil:
nplLastError = "null pointer"
return nil
let header = cast[ptr NPLHeader](rawPtr)
# Check Magic
if header.magic[0] != NPL_MAGIC[0] or
header.magic[1] != NPL_MAGIC[1] or
header.magic[2] != NPL_MAGIC[2] or
header.magic[3] != NPL_MAGIC[3]:
nplLastError = "bad magic"
return nil
# Check Version
if header.version != NPL_VERSION:
nplLastError = "bad version"
return nil
# Check Architecture
if header.arch != currentArch():
nplLastError = "bad arch"
return nil
# Check Bounds
let totalSize = NPL_HEADER_SIZE.uint64 + header.body_size
if totalSize > maxLen:
nplLastError = "truncated"
return nil
# Get body pointer
let bodyPtr = cast[pointer](cast[uint64](rawPtr) + NPL_HEADER_SIZE.uint64)
# Verify Signature (REAL CRYPTO)
if not verify_npl_signature(header.signature, bodyPtr, header.body_size):
nplLastError = "signature fail"
return nil
# Cast body to function pointer
return cast[PayloadEntry](bodyPtr)
# =========================================================
# Helper: Build Test Payload
# =========================================================
proc buildTestPayload*(buffer: ptr array[256, uint8], arch: uint8,
codeBytes: openArray[uint8]) =
# Clear buffer
for i in 0..<256:
buffer[i] = 0
let header = cast[ptr NPLHeader](buffer)
header.magic = NPL_MAGIC
header.version = NPL_VERSION
header.arch = arch
header.flags = 1
header.body_size = codeBytes.len.uint64
# Copy code to body
for i, b in codeBytes:
buffer[NPL_HEADER_SIZE + i] = b
{.pop.}

View File

@ -12,21 +12,20 @@ proc watchdog_loop() {.cdecl.} =
kprintln("[Watchdog] Immune System Online.")
while true:
# Check if network is stuck in PAUSE state
if net_paused:
# Check if IO is stuck in PAUSE state
if ion_paused:
let now = cpu_ticks()
# If paused and time exceeds threshold
# Note: pause_start needs to be set when pausing!
if (pause_start > 0) and (now > pause_start) and (now - pause_start >
MAX_PAUSE_TICKS):
# HEAL
kprint("[IMMUNE] Network paused too long. Forcing RESUME.\n")
net_paused = false
kprint("[IMMUNE] IO paused too long. Forcing RESUME.\n")
ion_paused = false
pause_start = 0
# Send CMD_NET_START to the Control Loop
var cmd = CmdPacket(kind: uint32(ion.CmdType.CMD_NET_START), arg: 0)
# Send CMD_ION_START to the Control Loop
var cmd = CmdPacket(kind: uint32(ion.CmdType.CMD_ION_START), arg: 0)
chan_cmd.send(cmd)
# Cooperative Multitasking: Must yield!

View File

@ -1,5 +1,5 @@
// HAL ABI - The Contract between L0 (Zig) and L1 (Nim)
// This struct is the "socket" for future language integration
// This struct is the "contract" for future language integration
pub const HAL = extern struct {
/// Write to console/serial

View File

@ -14,6 +14,8 @@ SECTIONS
}
.data : {
. = ALIGN(8);
PROVIDE(__global_pointer$ = . + 0x800);
*(.data .data.*)
*(.sdata .sdata.*)
}

View File

@ -1,12 +1,13 @@
/* MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
RUMPK HAL // RISC-V 64 CONTEXT SWITCH
RUMPK HAL // RISC-V 64 CONTEXT SWITCH (Boundaries Protected)
RISC-V LP64 ABI Callee-Saved:
RISC-V LP64 ABI Saved Registers + Bounds:
- ra (return address)
- gp (global pointer)
- tp (thread pointer)
- s0-s11 (12 saved registers)
- fp (frame pointer, alias for s0)
Frame: 14 regs * 8 = 112 bytes (16-byte aligned)
Frame: 16 regs * 8 = 128 bytes (16-byte aligned)
*/
.global cpu_switch_to
@ -17,24 +18,25 @@
# a1 = next_sp
cpu_switch_to:
# 1. Allocate Stack (112 bytes)
addi sp, sp, -112
# 1. Allocate Stack (128 bytes)
addi sp, sp, -128
# 2. Save Context (ra, s0-s11, fp)
# 2. Save Context
sd ra, 0(sp)
sd s0, 8(sp)
sd s1, 16(sp)
sd s2, 24(sp)
sd s3, 32(sp)
sd s4, 40(sp)
sd s5, 48(sp)
sd s6, 56(sp)
sd s7, 64(sp)
sd s8, 72(sp)
sd s9, 80(sp)
sd s10, 88(sp)
sd s11, 96(sp)
# fp is alias for s0, already saved
sd gp, 8(sp)
sd tp, 16(sp)
sd s0, 24(sp)
sd s1, 32(sp)
sd s2, 40(sp)
sd s3, 48(sp)
sd s4, 56(sp)
sd s5, 64(sp)
sd s6, 72(sp)
sd s7, 80(sp)
sd s8, 88(sp)
sd s9, 96(sp)
sd s10, 104(sp)
sd s11, 112(sp)
# 3. Save Old SP
sd sp, 0(a0)
@ -44,18 +46,49 @@ cpu_switch_to:
# 5. Restore Context
ld ra, 0(sp)
ld s0, 8(sp)
ld s1, 16(sp)
ld s2, 24(sp)
ld s3, 32(sp)
ld s4, 40(sp)
ld s5, 48(sp)
ld s6, 56(sp)
ld s7, 64(sp)
ld s8, 72(sp)
ld s9, 80(sp)
ld s10, 88(sp)
ld s11, 96(sp)
ld gp, 8(sp)
ld tp, 16(sp)
ld s0, 24(sp)
ld s1, 32(sp)
ld s2, 40(sp)
ld s3, 48(sp)
ld s4, 56(sp)
ld s5, 64(sp)
ld s6, 72(sp)
ld s7, 80(sp)
ld s8, 88(sp)
ld s9, 96(sp)
ld s10, 104(sp)
ld s11, 112(sp)
addi sp, sp, 112
addi sp, sp, 128
ret
/*
THE YIELD GUARD
Protects Kernel GP during subject-to-kernel yield calls.
*/
.global rumpk_yield_guard
.type rumpk_yield_guard, @function
rumpk_yield_guard:
# 1. Save Subject State
addi sp, sp, -16
sd gp, 0(sp)
sd ra, 8(sp)
# 2. Restore Kernel Global Pointer (Static Relocation)
.option push
.option norelax
la gp, __global_pointer$
.option pop
# 3. Call Nim Internal Logic
# (rumpk_yield_internal is a Nim cdecl proc)
call rumpk_yield_internal
# 4. Restore Subject State
ld gp, 0(sp)
ld ra, 8(sp)
addi sp, sp, 16
ret

View File

@ -59,6 +59,27 @@ pub fn write_bytes(bytes: []const u8) void {
}
}
pub fn read_byte() ?u8 {
switch (builtin.cpu.arch) {
.aarch64 => {
const dr: *volatile u32 = @ptrFromInt(PL011_BASE + PL011_DR);
const fr: *volatile u32 = @ptrFromInt(PL011_BASE + PL011_FR);
if ((fr.* & (1 << 4)) == 0) { // RXFE (Receive FIFO Empty) is bit 4, so if 0, it's NOT empty
return @truncate(dr.*);
}
},
.riscv64 => {
const thr: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_THR);
const lsr: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_LSR);
if ((lsr.* & 0x01) != 0) { // Data Ready
return thr.*;
}
},
else => {},
}
return null;
}
pub fn puts(s: []const u8) void {
write_bytes(s);
}

View File

@ -66,7 +66,7 @@ export fn virtio_net_send(data: [*]const u8, len: usize) void {
}
}
export fn virtio_net_init() void {
export fn hal_io_init() void {
if (VirtioNetDriver.probe()) |*driver| {
var d = driver.*;
if (d.init_device()) {

View File

@ -1,20 +1,48 @@
#include <stddef.h>
#include <stdint.h>
// Basic memory stubs (Very dangerous, just for canary)
static uint8_t app_heap[64 * 1024];
static size_t heap_ptr = 0;
// Basic memory stubs
extern void* malloc(size_t size);
extern void free(void* ptr);
void* malloc(size_t size) {
if (heap_ptr + size > sizeof(app_heap)) return NULL;
void* p = &app_heap[heap_ptr];
heap_ptr += (size + 7) & ~7; // Align 8
// Forward declare memset (defined below)
void* memset(void* s, int c, size_t n);
void* realloc(void* ptr, size_t size) {
// naive realloc: alloc new, no copy (dangerous if used), return new
// For Phase 8 we assume simple allocs.
// If we want real realloc, we need copy.
void* new_ptr = malloc(size);
// copy? we don't know old size using standard malloc API without tracking.
// ION slab is 2048.
return new_ptr;
}
void* calloc(size_t nmemb, size_t size) {
void* p = malloc(nmemb * size);
if (p) memset(p, 0, nmemb * size);
return p;
}
void free(void* ptr) { (void)ptr; }
void* realloc(void* ptr, size_t size) { return malloc(size); }
void* calloc(size_t nmemb, size_t size) { return malloc(nmemb * size); }
// LwIP Panic Handler (for Membrane stack)
extern void console_write(const void* p, size_t len);
void nexus_lwip_panic(const char* msg) {
const char* prefix = "\n[LwIP/Membrane] ASSERT FAIL: ";
console_write(prefix, 30);
// Print the message (assuming null-terminated)
const char* p = msg;
size_t len = 0;
while (p[len]) len++;
console_write(msg, len);
const char* suffix = "\n";
console_write(suffix, 1);
// Halt
while(1) {}
}
// String stubs
size_t strlen(const char* s) {

View File

@ -2,21 +2,20 @@ import ../../core/ion/memory
import ../../core/ring
# Fixed address for the SysTable (provided by Carrier)
const SYS_TABLE_ADDR = 0x801FFF00'u64
const SYS_TABLE_ADDR = 0x83000000'u64
type
SysTable = object
s_yield*: pointer
s_alloc*: proc(): IonPacket {.cdecl.}
s_free*: proc(pkt: IonPacket) {.cdecl.}
s_tx*: proc(pkt: IonPacket): bool {.cdecl.}
magic*: uint32
s_rx*: pointer
s_tx*: pointer
s_event*: pointer
# The Ring where the Kernel (Switch) pushes packets for this app
var membrane_rx_ring_static: RingBuffer[IonPacket, 256]
var membrane_rx_ring_ptr*: ptr RingBuffer[IonPacket, 256]
proc ion_user_init*() =
proc ion_user_init*() {.exportc.} =
when defined(is_membrane):
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
membrane_rx_ring_ptr = cast[ptr RingBuffer[IonPacket, 256]](sys.s_rx)
@ -24,14 +23,11 @@ proc ion_user_init*() =
membrane_rx_ring_static.init()
membrane_rx_ring_ptr = addr membrane_rx_ring_static
proc ion_user_alloc*(out_pkt: ptr IonPacket): bool =
proc ion_user_alloc*(out_pkt: ptr IonPacket): bool {.exportc.} =
## Allocate a slab for the application to write into.
when defined(is_membrane):
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
let pkt = sys.s_alloc()
if pkt.data == nil: return false
out_pkt[] = pkt
return true
# TODO: Implement allocation via Command Ring or shared pool
return false
else:
var pkt = ion_alloc()
if pkt.data == nil:
@ -39,23 +35,24 @@ proc ion_user_alloc*(out_pkt: ptr IonPacket): bool =
out_pkt[] = pkt
return true
proc ion_user_free*(pkt: IonPacket) =
proc ion_user_free*(pkt: IonPacket) {.exportc.} =
## Return a slab to the pool.
when defined(is_membrane):
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
sys.s_free(pkt)
# TODO: Implement free via Command Ring
discard
else:
ion_free(pkt)
proc ion_user_tx*(pkt: IonPacket): bool =
proc ion_user_tx*(pkt: IonPacket): bool {.exportc.} =
## Push a packet to the Transmission Ring.
when defined(is_membrane):
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
return sys.s_tx(pkt)
let tx = cast[ptr RingBuffer[IonPacket, 256]](sys.s_tx)
return tx[].push(pkt)
else:
return ion_tx_push(pkt)
proc ion_user_rx*(out_pkt: ptr IonPacket): bool =
proc ion_user_rx*(out_pkt: ptr IonPacket): bool {.exportc.} =
## Pop a packet from the Application's RX Ring.
if membrane_rx_ring_ptr == nil: return false
if membrane_rx_ring_ptr[].isEmpty: return false

View File

@ -1,7 +1,44 @@
import socket
import ../../core/ion/memory
import ion_client
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
# --- Heap Allocator (Slab Backed) ---
const HEADER_SIZE = 32
proc malloc*(size: csize_t): pointer {.exportc, cdecl.} =
if size > (2048 - HEADER_SIZE): return nil
var pkt: IonPacket
if not ion_user_alloc(addr pkt): return nil
if pkt.data == nil: return nil
# Store metadata at the start of the slab
var header_ptr = cast[ptr IonPacket](pkt.data)
header_ptr[] = pkt
# Return pointer after header
return cast[pointer](cast[uint](pkt.data) + uint(HEADER_SIZE))
proc free*(p: pointer) {.exportc, cdecl.} =
if p == nil: return
# Recover Metadata
let slab_addr = cast[uint](p) - uint(HEADER_SIZE)
let header_ptr = cast[ptr IonPacket](slab_addr)
# Free using the stored packet (contains correct ID)
ion_user_free(header_ptr[])
proc sleep*(seconds: uint32) {.exportc, cdecl.} =
# Busy loop sleep
var i: int = 0
let limit = int(seconds) * 50_000_000
while i < limit:
i += 1
# Basic SockAddr struct match (IPv4)
type
SockAddrIn = object

View File

@ -206,3 +206,14 @@ proc glue_connect*(sock: ptr NexusSock; ip: ptr IpAddr; port: uint16): int =
sock.state = SYN_SENT
return 0
return -1
# The Yield Mechanism (Cooperative Multitasking)
proc fiber_yield*() {.exportc, cdecl.} =
## Yield control back to the Kernel's networking fiber.
## This allows VirtIO polling and packet processing to occur.
when defined(is_membrane):
# Use the Kernel-provided yield function pointer
type YieldFunc = proc() {.cdecl.}
let yield_ptr = cast[YieldFunc](0x83000FF0'u64)
if yield_ptr != nil:
yield_ptr()

View File

@ -9,7 +9,8 @@ var socket_table: array[MAX_SOCKETS, ptr NexusSock]
proc new_socket*(): int =
## Allocate a new NexusSocket and return a fake FD.
for i in 0 ..< MAX_SOCKETS:
## Reserve FDs 0, 1, 2 for stdio compatibility.
for i in 3 ..< MAX_SOCKETS:
if socket_table[i] == nil:
var s = create(NexusSock)
s.fd = i

28
libs/membrane/sys_arch.c Normal file
View File

@ -0,0 +1,28 @@
#include "lwip/opt.h"
#include "lwip/arch.h"
#include "lwip/sys.h"
// External references to console
extern void console_write(const void* p, unsigned long len);
// Simple counter for monotonic time
static volatile u32_t lwip_ticks_ms = 0;
// 1. Initialization (Membrane version - minimal)
void sys_init(void) {
// Silent init for Membrane
}
// 2. The Time Source
u32_t sys_now(void) {
lwip_ticks_ms++;
return lwip_ticks_ms;
}
// 3. Panic handler is in clib.c (nexus_lwip_panic)
// 4. Critical Sections (Stubbed)
#if SYS_LIGHTWEIGHT_PROT
sys_prot_t sys_arch_protect(void) { return 0; }
void sys_arch_unprotect(sys_prot_t pval) { (void)pval; }
#endif

View File

@ -60,13 +60,13 @@ export fn main() c_int {
return 1;
}
// 1. Send CMD_NET_STOP (Poison)
print("[SABOTEUR] Injecting POISON (CMD_NET_STOP)...\n");
// 1. Send CMD_ION_STOP (Poison)
print("[SABOTEUR] Injecting POISON (CMD_ION_STOP)...\n");
{
const cmd_ring = sys.s_cmd;
const head = @atomicLoad(u32, &cmd_ring.head, .monotonic);
// CMD_NET_STOP = 1
// CMD_ION_STOP = 1
const pkt = CmdPacket{ .kind = 1, .arg = 0 };
cmd_ring.data[head & cmd_ring.mask] = pkt;
@ -74,7 +74,7 @@ export fn main() c_int {
print("[SABOTEUR] POISON injected.\n");
}
print("[SABOTEUR] Network poisoned. Entering infinite loop to block CPU.\n");
print("[SABOTEUR] IO poisoned. Entering infinite loop to block CPU.\n");
print("[SABOTEUR] (This simulates a stuck NPL preventing yields)\n");
// 2. Hang

131
src/npl/system/nexshell.zig Normal file
View File

@ -0,0 +1,131 @@
const std = @import("std");
// NEXUS IMMUNE SYSTEM (NPL) - THE VOICE & COMMAND PLANE
// Markus Maiwald (Architect) | Voxis Forge (AI)
const ION_BASE = 0x83000000;
const IonPacket = extern struct {
data: u64,
phys: u64,
len: u16,
id: u16,
};
const CmdPacket = extern struct {
kind: u32,
arg: u32,
};
fn RingBuffer(comptime T: type) type {
return extern struct {
head: u32,
tail: u32,
mask: u32,
data: [256]T,
};
}
const SysTable = extern struct {
magic: u32,
s_rx: *RingBuffer(IonPacket),
s_tx: *RingBuffer(IonPacket),
s_event: *RingBuffer(IonPacket),
s_cmd: *RingBuffer(CmdPacket),
};
const CMD_ION_STOP = 1;
const CMD_ION_START = 2;
// The Main Loop for the NexShell Fiber
export fn nexshell_main() void {
const sys = @as(*SysTable, @ptrFromInt(ION_BASE));
print("\n╔═══════════════════════════════════════╗\n");
print("║ NEXSHELL IMMUNE SYSTEM ACTIVE ║\n");
print("║ Command Plane: READY ║\n");
print("╚═══════════════════════════════════════╝\n");
const event_ring = sys.s_event;
const cmd_ring = sys.s_cmd;
var input_buffer: [64]u8 = undefined;
var input_idx: usize = 0;
while (true) {
// 1. Process Telemetry Events
const head = @atomicLoad(u32, &event_ring.head, .acquire);
const tail = @atomicLoad(u32, &event_ring.tail, .monotonic);
if (head != tail) {
const pkt = event_ring.data[tail & event_ring.mask];
print("\n[NexShell] ALERT | EventID: ");
if (pkt.id == 777) {
print("777 (SECURITY_HEARTBEAT)\n");
} else {
print("GENERIC\n");
}
@atomicStore(u32, &event_ring.tail, tail + 1, .release);
}
// 2. Process User Input (Non-blocking)
const c = console_read();
if (c != -1) {
const byte = @as(u8, @intCast(c));
if (byte == '\r' or byte == '\n') {
print("\n");
process_command(input_buffer[0..input_idx], cmd_ring);
input_idx = 0;
} else if (byte == 0x7F or byte == 0x08) {
if (input_idx > 0) {
input_idx -= 1;
print("\x08 \x08"); // Backspace
}
} else if (input_idx < 63) {
input_buffer[input_idx] = byte;
input_idx += 1;
const bs = [1]u8{byte};
print(&bs);
}
}
fiber_yield();
}
}
fn process_command(cmd_text: []const u8, cmd_ring: *RingBuffer(CmdPacket)) void {
if (std.mem.eql(u8, cmd_text, "io stop") or std.mem.eql(u8, cmd_text, "ion stop")) {
print("[NexShell] Pushing CMD_ION_STOP...\n");
push_cmd(cmd_ring, CMD_ION_STOP, 0);
} else if (std.mem.eql(u8, cmd_text, "io start") or std.mem.eql(u8, cmd_text, "ion start")) {
print("[NexShell] Pushing CMD_ION_START...\n");
push_cmd(cmd_ring, CMD_ION_START, 0);
} else if (cmd_text.len > 0) {
print("[NexShell] Unknown Command: ");
print(cmd_text);
print("\n");
}
}
fn push_cmd(ring: *RingBuffer(CmdPacket), kind: u32, arg: u32) void {
const head = @atomicLoad(u32, &ring.head, .acquire);
const tail = @atomicLoad(u32, &ring.tail, .monotonic);
const next = (head + 1) & ring.mask;
if (next == tail) {
print("[NexShell] CMD RING FULL!\n");
return;
}
ring.data[head & ring.mask] = .{ .kind = kind, .arg = arg };
@atomicStore(u32, &ring.head, next, .release);
}
// OS Shims
extern fn write(fd: c_int, buf: [*]const u8, count: usize) isize;
extern fn console_read() c_int;
extern fn fiber_yield() void;
fn print(text: []const u8) void {
_ = write(1, text.ptr, text.len);
}