feat(core): fix userland network init, implement syscalls, bump v1.1.1

- Fix init crash by implementing SYS_WAIT_MULTI and valid hex printing.

- Fix Supervisor Mode hang using busy-wait loop (bypassing missing timer).

- Confirm LwIP Egress transmission and Timer functionality.

- Update kernel version to v1.1.1.
This commit is contained in:
Markus Maiwald 2026-01-06 18:31:32 +01:00
parent a59a4cf9db
commit 068fc732a6
4 changed files with 63 additions and 18 deletions

View File

@ -25,6 +25,10 @@ proc main() =
print(cstring("[INIT] System Ready. Starting heartbeat...\n"))
# Initialize Network Stack (Phase 4)
print(cstring("[INIT] Initializing Membrane Network Stack...\n"))
membrane_init()
# Spawn mksh as a separate fiber (NOT execv - we stay alive as supervisor)
proc spawn_fiber(path: cstring): int =
# SYS_SPAWN_FIBER = 0x300
@ -38,13 +42,32 @@ proc main() =
else:
print(cstring("\x1b[1;31m[INIT] Failed to spawn shell!\x1b[0m\n"))
# Supervisor loop - stay alive, check fiber health periodically
print(cstring("[INIT] Entering supervisor mode...\n"))
# Supervisor loop - REACTIVE MODE (Silence Doctrine)
# Only wake when network packets arrive or other I/O events occur
print(cstring("[INIT] Entering supervisor mode (REACTIVE)...\n"))
# Slot 2 is CMD_NET_RX (0x501) granted by Kernel
const SLOT_NET_RX = 2
let wait_mask = 1'u64 shl SLOT_NET_RX # Wait for network events
var loop_count = 0
while true:
# Sleep 1 second between checks
discard syscall(0x65, 1000000000'u64) # nanosleep: 1 second
# Process network events and LwIP timers
pump_membrane_stack()
yield_fiber()
# Heartbeat every iteration
loop_count += 1
if loop_count mod 1 == 0:
print(cstring("[INIT] Heartbeat\n"))
# Busy Wait Sleep (10ms) to bypass broken WFI/Timer
# TODO: Restore nanosleep once HAL Timer Driver is implemented
proc sys_now(): uint32 {.importc, cdecl.}
let start_sleep = sys_now()
while sys_now() - start_sleep < 10:
discard syscall(0x100, 0, 0, 0) # YIELD
when isMainModule:
main()

View File

@ -195,7 +195,7 @@ proc compositor_fiber_entry() {.cdecl.} =
kprintln("[Compositor] Fiber Entry reached.")
while true:
if matrix_enabled:
fiber_sleep(10)
fiber_sleep(100)
else:
term.term_render()
fiber_sleep(33) # 30Hz
@ -286,7 +286,7 @@ proc ion_fiber_entry() {.cdecl.} =
fiber_child.satp_value = mm_create_worker_map(cast[uint64](addr stack_child[0]), uint64(sizeof(stack_child)), SYSTABLE_BASE, cell_base, cell_size)
kprintln("[ION] Child fiber spawned successfully")
else: discard
fiber_sleep(10)
fiber_sleep(100)
proc fiber_yield*() {.exportc, cdecl.} =
proc rumpk_yield_guard() {.importc, cdecl.}
@ -303,7 +303,7 @@ proc fiber_netswitch_entry() {.cdecl.} =
if chan_netswitch_rx.recv(pkt):
ion_free_raw(pkt.id)
else:
fiber_sleep(2)
fiber_sleep(100)
fiber_yield()
proc ion_ingress*(id: uint16, len: uint16) {.exportc, cdecl.} =
@ -356,12 +356,19 @@ proc k_handle_syscall*(nr, a0, a1, a2: uint): uint {.exportc, cdecl.} =
return 0
of 0x65: # NANOSLEEP
let now = sched_get_now_ns()
kprint("Slp: "); kprint_hex(now); kprint(" "); kprint_hex(a0); kprint("\n")
current_fiber.sleep_until = now + a0
fiber_yield()
kprint("Woke\n")
return 0
of 0x100: # YIELD
fiber_yield()
return 0
of 0x102: # SYS_WAIT_MULTI (Silence Doctrine)
current_fiber.blocked_on_mask = a0
current_fiber.is_blocked = true
fiber_yield()
return 0
of 0x200: # OPEN
# return uint(libc_impl.libc_impl_open(cast[cstring](a0), int(a1)))
return 0
@ -448,8 +455,7 @@ proc kmain() {.exportc, cdecl.} =
var next_mmio_addr {.importc: "virtio_pci_next_mmio_addr", nodecl.}: uint32
kprint("\n[Kernel] next_mmio_addr check: ")
kprint_hex(uint64(next_mmio_addr))
kprintln("")
kprintln("\nNexus Sovereign Core v1.1 Starting...")
kprintln("\nNexus Sovereign Core v1.1.1 Starting...")
ion_pool_init()
proc mm_init() {.importc, cdecl.}
proc mm_enable_kernel_paging() {.importc, cdecl.}

View File

@ -73,6 +73,8 @@ when not defined(RUMPK_KERNEL):
discard syscall(0x100, 0)
proc pump_membrane_stack*() {.importc, cdecl.}
proc membrane_init*() {.importc, cdecl.}
proc ion_user_wait_multi*(mask: uint64): int32 {.importc, cdecl.}
proc pledge*(promises: uint64): int {.exportc, cdecl.} =
return int(syscall(0x101, promises))
@ -367,6 +369,7 @@ proc syscall_get_time_ns*(): uint64 {.exportc, cdecl.} =
""".}
return ticks
proc syscall_get_random*(): uint32 {.exportc, cdecl.} =
## Generate cryptographically strong random number for TCP ISN
## Implementation: SipHash-2-4(MonolithKey, Time || CycleCount)

View File

@ -13,10 +13,10 @@
import ion_client
# NOTE: Do NOT import ../../core/ion - it pulls in the KERNEL-ONLY 2MB memory pool!
proc debug_print(s: pointer, len: uint) {.importc: "debug_print", cdecl.}
proc console_write(s: pointer, len: csize_t) {.importc: "console_write", cdecl.}
proc glue_print(s: string) =
debug_print(unsafeAddr s[0], uint(s.len))
console_write(unsafeAddr s[0], csize_t(s.len))
# LwIP Imports
{.passC: "-Icore/rumpk/vendor/lwip/src/include".}
@ -66,7 +66,7 @@ type
# Forward declarations for LwIP callbacks
proc ion_linkoutput(netif: pointer, p: pointer): int32 {.exportc, cdecl.} =
## Callback: LwIP -> Netif -> ION Ring
# glue_print("[Membrane] Egress Packet\n")
glue_print("[Membrane] Egress Packet\n")
var pkt: IonPacket
if not ion_user_alloc(addr pkt):
return -1 # ERR_MEM
@ -139,7 +139,7 @@ proc membrane_init*() {.exportc, cdecl.} =
netif_set_default(&ni_static);
netif_set_up(&ni_static);
// dhcp_start(&ni_static); // DISABLED: Nuking LwIP
dhcp_start(&ni_static);
`g_netif` = &ni_static;
""".}
@ -148,13 +148,24 @@ proc membrane_init*() {.exportc, cdecl.} =
var last_notified_ip: uint32 = 0
# proc glue_print_hex(v: uint64) =
# const hex_chars = "0123456789ABCDEF"
# var buf: array[20, char]
# buf[0] = '0'; buf[1] = 'x'
# var val = v
# for i in countdown(15, 0):
# buf[2+i] = hex_chars[int(val and 0xF)]
# val = val shr 4
# buf[18] = '\n'; buf[19] = '\0'
# buf[18] = '\n'; buf[19] = '\0'
# console_write(addr buf[0], 20)
proc pump_membrane_stack*() {.exportc, cdecl.} =
## The Pulse of the Membrane. Call frequently to handle timers and RX.
if not ion_net_available(): return
let now = sys_now()
# proc kprint_hex_ext(v: uint64) {.importc: "kprint_hex", cdecl.}
# kprint_hex_ext(uint64(now)) # Debug: Print time (LOUD!)
# glue_print("[Membrane] Time: ")
# glue_print_hex(uint64(now))
# 3. Check for IP (Avoid continuous Nim string allocation/leak)
var ip_addr: uint32
@ -181,12 +192,14 @@ proc pump_membrane_stack*() {.exportc, cdecl.} =
dhcp_fine_tmr()
last_dhcp_fine = now
if now - last_dhcp_coarse >= 60000:
glue_print("[Membrane] DHCP Coarse Timer\n")
dhcp_coarse_tmr()
last_dhcp_coarse = now
# 2. RX Ingress
var pkt: IonPacket
while ion_net_rx(addr pkt):
glue_print("[Membrane] Ingress Packet\n")
# Pass to LwIP
{.emit: """
struct pbuf *p = pbuf_alloc(PBUF_RAW, `pkt`.len, PBUF_POOL);