fix(rumpk): enable user stack access and repair boot process
- Enabled SUM (Supervisor Access to User Memory) in riscv_init to allow kernel loader to write to user stacks. - Removed dangerous 'csrc sstatus' in kload_phys that revoked access. - Aligned global fiber stacks to 4096 bytes to prevent unmapped page faults at stack boundaries. - Restored 'boot.o' linking to fix silent boot failure. - Implemented 'fiber_can_run_on_channels' stub to satisfy Membrane linking. - Defined kernel stack in header.zig to fix '__stack_top' undefined symbol. - Resolved duplicate symbols in overrides.c and nexshell.
This commit is contained in:
parent
7207282236
commit
011e0b699e
|
|
@ -48,11 +48,17 @@ export const multiboot2_header linksection(".multiboot2") = Multiboot2Header{
|
|||
|
||||
extern fn riscv_init() noreturn;
|
||||
|
||||
// 1MB Kernel Stack
|
||||
const STACK_SIZE = 0x100000;
|
||||
export var kernel_stack: [STACK_SIZE]u8 align(16) linksection(".bss.stack") = undefined;
|
||||
|
||||
export fn _start() callconv(.naked) noreturn {
|
||||
// Clear BSS, set up stack, then jump to RISC-V Init
|
||||
asm volatile (
|
||||
\\ // Set up stack
|
||||
\\ la sp, __stack_top
|
||||
\\ la sp, kernel_stack
|
||||
\\ li t0, %[stack_size]
|
||||
\\ add sp, sp, t0
|
||||
\\
|
||||
\\ // Clear BSS
|
||||
\\ la t0, __bss_start
|
||||
|
|
@ -69,5 +75,7 @@ export fn _start() callconv(.naked) noreturn {
|
|||
\\ // Should never return
|
||||
\\ wfi
|
||||
\\ j 2b
|
||||
:
|
||||
: [stack_size] "i" (STACK_SIZE),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ SECTIONS
|
|||
.stack (NOLOAD) : {
|
||||
. = ALIGN(16);
|
||||
. += 0x100000; /* 1MB Stack */
|
||||
__stack_top = .;
|
||||
PROVIDE(__stack_top = .);
|
||||
}
|
||||
|
||||
/DISCARD/ : {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ var initrd_end {.importc: "_initrd_end" .}: byte
|
|||
# Globals
|
||||
var
|
||||
fiber_ion, fiber_subject, fiber_child, fiber_compositor, fiber_nexshell, fiber_netswitch: FiberObject
|
||||
stack_ion, stack_subject, stack_child, stack_compositor, stack_nexshell, stack_netswitch: array[MAX_FIBER_STACK, byte]
|
||||
stack_ion {.align: 4096.}, stack_subject {.align: 4096.}, stack_child {.align: 4096.}, stack_compositor {.align: 4096.}, stack_nexshell {.align: 4096.}, stack_netswitch {.align: 4096.}: array[MAX_FIBER_STACK, byte]
|
||||
subject_loading_path: array[64, char] = [ '/', 's', 'y', 's', 'r', 'o', '/', 'b', 'i', 'n', '/', 'm', 'k', 's', 'h', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' ]
|
||||
matrix_enabled: bool = false
|
||||
active_fibers_arr: array[16, ptr FiberObject]
|
||||
|
|
@ -165,7 +165,7 @@ proc kload_phys(path: cstring, phys_offset: uint64): uint64 =
|
|||
kprint(" - Zeroing BSS: VA="); kprint_hex(bss_start); kprint(" Len="); kprint_hex(bss_len); kprintln("")
|
||||
k_zero_mem(cast[pointer](bss_start), bss_len)
|
||||
|
||||
{.emit: """asm volatile ("li t1, 0x40000; csrc sstatus, t1" : : : "t1");""" .}
|
||||
# {.emit: """asm volatile ("li t1, 0x40000; csrc sstatus, t1" : : : "t1");""" .}
|
||||
|
||||
# ⚡ ARCH-SYNC: Flush I-Cache after loading new code
|
||||
{.emit: """asm volatile ("fence.i" : : : "memory");""" .}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ double floor(double x) {
|
|||
}
|
||||
double fmod(double x, double y) { return 0.0; } // Stub
|
||||
|
||||
/* atomic overrides commented out to prefer stubs.zig
|
||||
// ----------------------------------------------------------------------------
|
||||
// Atomic Overrides (To avoid libcompiler_rt atomics.o which uses medlow)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -116,6 +117,7 @@ void sovereign_atomic_fetch_min_16(void *ptr, void *val, void *ret, int model) {
|
|||
bool sovereign_atomic_is_lock_free(size_t size, void *ptr) {
|
||||
return true; // We are single core or spinlocked elsewhere
|
||||
}
|
||||
*/
|
||||
|
||||
// ===================================
|
||||
// Compiler-RT Stubs (128-bit Math)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
proc main() =
|
||||
discard
|
||||
|
||||
when isMainModule:
|
||||
main()
|
||||
|
|
@ -106,3 +106,7 @@ export fn hal_cmd_pop(handle: u64, out_pkt: *CmdPacket) bool {
|
|||
// uart.print("[HAL] Popping CMD from "); uart.print_hex(handle); uart.print("\n");
|
||||
return popGeneric(CmdPacket, ring, out_pkt);
|
||||
}
|
||||
// Stub for term.nim compatibility
|
||||
export fn fiber_can_run_on_channels() bool {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ export fn riscv_init() callconv(.naked) noreturn {
|
|||
\\ li t1, 0x58 // 'X'
|
||||
\\ sb t1, 0(t0) // Write to THR
|
||||
|
||||
// 1.1 Enable FPU (sstatus.FS = Initial [01]) and Vectors (sstatus.VS = Initial [01])
|
||||
\\ li t0, 0x2200 // FS=bit 13, VS=bit 9
|
||||
// 1.1 Enable FPU (FS), Vectors (VS), and SUM (Supervisor User Memory Access)
|
||||
\\ li t0, 0x42200 // SUM=bit 18, FS=bit 13, VS=bit 9
|
||||
\\ csrs sstatus, t0
|
||||
|
||||
// 1.2 Initialize Global Pointer
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
const data = @embedFile("initrd.tar");
|
||||
|
||||
export var _initrd_payload: [data.len]u8 align(4096) linksection(".initrd") = data.*;
|
||||
Binary file not shown.
|
|
@ -0,0 +1,93 @@
|
|||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
|
||||
//! Rumpk Layer 0: UART Input Logic (Kernel Only)
|
||||
//!
|
||||
//! Separated from uart.zig to avoid polluting userland stubs with kernel dependencies.
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const uart = @import("uart.zig");
|
||||
|
||||
// Input Ring Buffer (256 bytes, power of 2 for fast masking)
|
||||
const INPUT_BUFFER_SIZE = 256;
|
||||
var input_buffer: [INPUT_BUFFER_SIZE]u8 = undefined;
|
||||
var input_head = std.atomic.Value(u32).init(0); // Write position
|
||||
var input_tail = std.atomic.Value(u32).init(0); // Read position
|
||||
|
||||
pub fn poll_input() void {
|
||||
// Only Kernel uses this
|
||||
const Kernel = struct {
|
||||
extern fn ion_push_stdin(ptr: [*]const u8, len: usize) void;
|
||||
};
|
||||
|
||||
switch (builtin.cpu.arch) {
|
||||
.riscv64 => {
|
||||
const thr: *volatile u8 = @ptrFromInt(uart.NS16550A_BASE + uart.NS16550A_THR);
|
||||
const lsr: *volatile u8 = @ptrFromInt(uart.NS16550A_BASE + uart.NS16550A_LSR);
|
||||
|
||||
// Read all available bytes from UART FIFO (Limit 128 to prevent stall)
|
||||
var loop_limit: usize = 0;
|
||||
while ((lsr.* & 0x01) != 0 and loop_limit < 128) { // Data Ready
|
||||
loop_limit += 1;
|
||||
const byte = thr.*;
|
||||
const byte_arr = [1]u8{byte};
|
||||
|
||||
// Forward to Kernel Input Channel
|
||||
Kernel.ion_push_stdin(&byte_arr, 1);
|
||||
|
||||
// Add to ring buffer if not full
|
||||
const head_val = input_head.load(.monotonic);
|
||||
const tail_val = input_tail.load(.monotonic);
|
||||
const next_head = (head_val + 1) % INPUT_BUFFER_SIZE;
|
||||
|
||||
if (next_head != tail_val) {
|
||||
input_buffer[head_val] = byte;
|
||||
input_head.store(next_head, .monotonic);
|
||||
}
|
||||
}
|
||||
},
|
||||
.aarch64 => {
|
||||
const dr: *volatile u32 = @ptrFromInt(uart.PL011_BASE + uart.PL011_DR);
|
||||
const fr: *volatile u32 = @ptrFromInt(uart.PL011_BASE + uart.PL011_FR);
|
||||
|
||||
while ((fr.* & (1 << 4)) == 0) { // RXFE (Receive FIFO Empty) is bit 4
|
||||
const byte: u8 = @truncate(dr.*);
|
||||
const byte_arr = [1]u8{byte};
|
||||
Kernel.ion_push_stdin(&byte_arr, 1);
|
||||
|
||||
const head_val = input_head.load(.monotonic);
|
||||
const tail_val = input_tail.load(.monotonic);
|
||||
const next_head = (head_val + 1) % INPUT_BUFFER_SIZE;
|
||||
|
||||
if (next_head != tail_val) {
|
||||
input_buffer[head_val] = byte;
|
||||
input_head.store(next_head, .monotonic);
|
||||
}
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
export fn uart_poll_input() void {
|
||||
poll_input();
|
||||
}
|
||||
|
||||
pub fn read_byte() ?u8 {
|
||||
// First, poll UART to refill buffer
|
||||
poll_input();
|
||||
|
||||
// Then read from buffer
|
||||
const head_val = input_head.load(.monotonic);
|
||||
const tail_val = input_tail.load(.monotonic);
|
||||
|
||||
if (tail_val != head_val) {
|
||||
const byte = input_buffer[tail_val];
|
||||
input_tail.store((tail_val + 1) % INPUT_BUFFER_SIZE, .monotonic);
|
||||
return byte;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue