rumpk/hal/entry_riscv.zig

254 lines
6.0 KiB
Zig

// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
// RUMPK HAL // RISC-V ENTRY - SOVEREIGN TRAP ARCHITECTURE
const std = @import("std");
const uart = @import("uart.zig");
const virtio_net = @import("virtio_net.zig");
// =========================================================
// Entry Point (Naked)
// =========================================================
export fn _start() callconv(.naked) noreturn {
asm volatile (
// 1. Disable Interrupts
\\ csrw sie, zero
\\ csrw satp, zero
// 1.1 Enable FPU (sstatus.FS = Initial [01])
\\ li t0, 0x2000
\\ csrs sstatus, t0
// 1.2 Initialize Global Pointer
\\ .option push
\\ .option norelax
\\ la gp, __global_pointer$
\\ .option pop
// 2. Set up Stack
\\ la sp, stack_bytes
\\ li t0, 65536
\\ add sp, sp, t0
// 2.1 Install Trap Handler (Direct Mode)
\\ la t0, trap_entry
\\ csrw stvec, t0
// 3. Jump to Zig Entry
\\ call zig_entry
\\ 1: wfi
\\ j 1b
);
unreachable;
}
// Trap Frame Layout (Packed on stack)
const TrapFrame = extern struct {
ra: usize,
gp: usize,
tp: usize,
t0: usize,
t1: usize,
t2: usize,
s0: usize,
s1: usize,
a0: usize,
a1: usize,
a2: usize,
a3: usize,
a4: usize,
a5: usize,
a6: usize,
a7: usize,
s2: usize,
s3: usize,
s4: usize,
s5: usize,
s6: usize,
s7: usize,
s8: usize,
s9: usize,
s10: usize,
s11: usize,
t3: usize,
t4: usize,
t5: usize,
t6: usize,
sepc: usize,
sstatus: usize,
scause: usize,
stval: usize,
};
// Full Context Save Trap Entry
export fn trap_entry() callconv(.naked) void {
asm volatile (
// Allocate stack (36 words * 8 bytes = 288 bytes)
\\ addi sp, sp, -288
// Save GPRs
\\ sd ra, 0(sp)
\\ sd gp, 8(sp)
\\ sd tp, 16(sp)
\\ sd t0, 24(sp)
\\ sd t1, 32(sp)
\\ sd t2, 40(sp)
\\ sd s0, 48(sp)
\\ sd s1, 56(sp)
\\ sd a0, 64(sp)
\\ sd a1, 72(sp)
\\ sd a2, 80(sp)
\\ sd a3, 88(sp)
\\ sd a4, 96(sp)
\\ sd a5, 104(sp)
\\ sd a6, 112(sp)
\\ sd a7, 120(sp)
\\ sd s2, 128(sp)
\\ sd s3, 136(sp)
\\ sd s4, 144(sp)
\\ sd s5, 152(sp)
\\ sd s6, 160(sp)
\\ sd s7, 168(sp)
\\ sd s8, 176(sp)
\\ sd s9, 184(sp)
\\ sd s10, 192(sp)
\\ sd s11, 200(sp)
\\ sd t3, 208(sp)
\\ sd t4, 216(sp)
\\ sd t5, 224(sp)
\\ sd t6, 232(sp)
// Save CSRs
\\ csrr t0, sepc
\\ sd t0, 240(sp)
\\ csrr t1, sstatus
\\ sd t1, 248(sp)
\\ csrr t2, scause
\\ sd t2, 256(sp)
\\ csrr t3, stval
\\ sd t3, 264(sp)
// Call Handler (Arg0 = Frame Pointer)
\\ mv a0, sp
\\ call rss_trap_handler
// Restore CSRs (sepc might be modified by syscall handler to skip ecall)
\\ ld t0, 240(sp)
\\ csrw sepc, t0
// We restore sstatus to preserve interrupt state if needed, though usually fixed in kernel
\\ ld t1, 248(sp)
\\ csrw sstatus, t1
// Restore GPRs
\\ ld ra, 0(sp)
\\ ld gp, 8(sp)
\\ ld tp, 16(sp)
\\ ld t0, 24(sp)
\\ ld t1, 32(sp)
\\ ld t2, 40(sp)
\\ ld s0, 48(sp)
\\ ld s1, 56(sp)
\\ ld a0, 64(sp)
\\ ld a1, 72(sp)
\\ ld a2, 80(sp)
\\ ld a3, 88(sp)
\\ ld a4, 96(sp)
\\ ld a5, 104(sp)
\\ ld a6, 112(sp)
\\ ld a7, 120(sp)
\\ ld s2, 128(sp)
\\ ld s3, 136(sp)
\\ ld s4, 144(sp)
\\ ld s5, 152(sp)
\\ ld s6, 160(sp)
\\ ld s7, 168(sp)
\\ ld s8, 176(sp)
\\ ld s9, 184(sp)
\\ ld s10, 192(sp)
\\ ld s11, 200(sp)
\\ ld t3, 208(sp)
\\ ld t4, 216(sp)
\\ ld t5, 224(sp)
\\ ld t6, 232(sp)
// Deallocate stack
\\ addi sp, sp, 288
\\ sret
);
}
// L1 Kernel Logic
extern fn k_handle_syscall(nr: usize, a0: usize, a1: usize, a2: usize) usize;
extern fn k_handle_exception(scause: usize, sepc: usize, stval: usize) void;
export fn rss_trap_handler(frame: *TrapFrame) void {
const scause = frame.scause;
// 8: ECALL from U-mode
// 9: ECALL from S-mode
if (scause == 8 or scause == 9) {
// Advance PC to skip 'ecall' instruction (4 bytes)
frame.sepc += 4;
// Dispatch Syscall
const res = k_handle_syscall(frame.a7, frame.a0, frame.a1, frame.a2);
// Write result back to a0
frame.a0 = res;
return;
}
// Delegate all other exceptions to the Kernel Immune System
// It will decide whether to segregate (worker) or halt (system)
// Note: k_handle_exception handles flow control (yield/halt) and does not return
k_handle_exception(scause, frame.sepc, frame.stval);
// Safety halt if kernel returns (should be unreachable)
while (true) {}
}
export var stack_bytes: [64 * 1024]u8 align(16) = undefined;
const hud = @import("hud.zig");
extern fn kmain() void;
extern fn NimMain() void;
export fn zig_entry() void {
uart.init_riscv();
uart.print("[Rumpk L0] zig_entry reached\n");
uart.print("[Rumpk RISC-V] Handing off to Nim L1...\n");
_ = virtio_net;
NimMain();
kmain();
rumpk_halt();
}
export fn console_write(ptr: [*]const u8, len: usize) void {
uart.write_bytes(ptr[0..len]);
}
export fn console_read() c_int {
if (uart.read_byte()) |b| {
return @as(c_int, b);
}
return -1;
}
const virtio_block = @import("virtio_block.zig");
export fn hal_io_init() void {
uart.init();
virtio_net.init();
virtio_block.init();
}
export fn rumpk_halt() noreturn {
uart.print("[Rumpk RISC-V] Halting.\n");
while (true) {
asm volatile ("wfi");
}
}
var mock_ticks: u64 = 0;
export fn rumpk_timer_now_ns() u64 {
mock_ticks += 100000;
return mock_ticks;
}