138 lines
3.9 KiB
Nim
138 lines
3.9 KiB
Nim
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
|
# RUMPK CORE // FIBER (Unified Multi-Arch)
|
|
# The atom of execution.
|
|
#
|
|
# Supported Architectures:
|
|
# - aarch64 (ARM64): VisionFive 2, RPi, AWS Graviton
|
|
# - amd64 (x86_64): Standard servers, trading systems
|
|
# - riscv64 (RISC-V): Sovereign compute, satellites
|
|
|
|
{.push stackTrace: off, lineTrace: off.}
|
|
|
|
# =========================================================
|
|
# Architecture-Specific Constants
|
|
# =========================================================
|
|
|
|
when defined(amd64) or defined(x86_64):
|
|
const CONTEXT_SIZE = 56
|
|
const RET_ADDR_INDEX = 6 # RIP at [sp + 48]
|
|
const ARCH_NAME = "x86_64"
|
|
|
|
elif defined(arm64) or defined(aarch64):
|
|
const CONTEXT_SIZE = 96
|
|
const RET_ADDR_INDEX = 11 # x30 (LR) at [sp + 88]
|
|
const ARCH_NAME = "aarch64"
|
|
|
|
elif defined(riscv64):
|
|
const CONTEXT_SIZE = 112
|
|
const RET_ADDR_INDEX = 0 # ra at [sp + 0]
|
|
const ARCH_NAME = "riscv64"
|
|
|
|
else:
|
|
{.error: "Unsupported architecture for Rumpk fibers".}
|
|
|
|
# =========================================================
|
|
# Types
|
|
# =========================================================
|
|
|
|
type
|
|
FiberState* = object
|
|
sp*: uint64 # The Stack Pointer (Must be first field!)
|
|
entry*: proc() {.cdecl.} # Entry point for this fiber
|
|
|
|
Fiber* = ptr FiberObject
|
|
FiberObject* = object
|
|
id*: uint64
|
|
name*: cstring
|
|
state*: FiberState
|
|
stack*: ptr UncheckedArray[uint8]
|
|
stack_size*: int
|
|
|
|
# =========================================================
|
|
# Imports
|
|
# =========================================================
|
|
|
|
# Import the Assembly Magic (same symbol name, different implementation per arch)
|
|
proc cpu_switch_to(prev_sp_ptr: ptr uint64, next_sp: uint64) {.importc, cdecl.}
|
|
|
|
# Import console for debugging
|
|
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
|
|
|
|
proc debug(s: string) =
|
|
if s.len > 0:
|
|
console_write(unsafeAddr s[0], csize_t(s.len))
|
|
|
|
# =========================================================
|
|
# Constants
|
|
# =========================================================
|
|
|
|
const STACK_SIZE* = 4096
|
|
|
|
# =========================================================
|
|
# Fiber State
|
|
# =========================================================
|
|
|
|
var main_fiber: FiberObject
|
|
var current_fiber*: Fiber = addr main_fiber
|
|
|
|
# =========================================================
|
|
# Trampoline (Entry point for new fibers)
|
|
# =========================================================
|
|
|
|
proc fiber_trampoline() {.cdecl, exportc, noreturn.} =
|
|
let f = current_fiber
|
|
|
|
if f.state.entry != nil:
|
|
f.state.entry()
|
|
|
|
# If the fiber returns, halt
|
|
when defined(amd64) or defined(x86_64):
|
|
while true:
|
|
{.emit: "asm volatile(\"hlt\");".}
|
|
elif defined(arm64) or defined(aarch64):
|
|
while true:
|
|
{.emit: "asm volatile(\"wfi\");".}
|
|
elif defined(riscv64):
|
|
while true:
|
|
{.emit: "asm volatile(\"wfi\");".}
|
|
|
|
# =========================================================
|
|
# Fiber Initialization (Arch-Specific)
|
|
# =========================================================
|
|
|
|
proc init_fiber*(f: Fiber, entry: proc() {.cdecl.}, stack_base: pointer) =
|
|
f.state.entry = entry
|
|
|
|
# Start at top of stack
|
|
var sp = cast[uint64](stack_base) + STACK_SIZE
|
|
|
|
# 1. Align to 16 bytes (Universal requirement)
|
|
sp = sp and not 15'u64
|
|
|
|
# 2. Reserve space for the context frame
|
|
sp = sp - CONTEXT_SIZE
|
|
|
|
# 3. Setup the Context (zero all, set return address)
|
|
var stack_ptr = cast[ptr UncheckedArray[uint64]](sp)
|
|
|
|
# Zero out the frame
|
|
let num_regs = CONTEXT_SIZE div 8
|
|
for i in 0..<num_regs:
|
|
stack_ptr[i] = 0
|
|
|
|
# Set return address to trampoline
|
|
stack_ptr[RET_ADDR_INDEX] = cast[uint64](fiber_trampoline)
|
|
|
|
f.state.sp = sp
|
|
|
|
# =========================================================
|
|
# Context Switch
|
|
# =========================================================
|
|
|
|
proc switch*(next: Fiber) =
|
|
let prev = current_fiber
|
|
current_fiber = next
|
|
cpu_switch_to(addr prev.state.sp, next.state.sp)
|
|
|
|
{.pop.}
|