Fix riscv64 boot crash: add missing kernel stack trampoline
kernel_main on riscv64 ran directly on EDK2's UEFI boot-time stack, with no dedicated stack switch — amd64 has always had a kernel_entry.S trampoline for exactly this reason (its own comment: "the FORTH interpreter + DOE experiment loop can easily exceed that depth"). aarch64 happens to get away without one because its firmware's default stack is apparently larger, but that was never a guarantee. On riscv64 the VM bootstrap's call depth (27 word-registration modules -> physics/SSM init -> Tripod capsule birth) overflowed that small stack, corrupting a return address and producing a wild jump / page fault right after vm_init_with_host() returned — reproduced consistently across the 2026-08-01 DoE campaign logs. - src/starkernel/arch/riscv64/kernel_entry.S (new): RISC-V stack-switch trampoline mirroring amd64's, giving the kernel a dedicated 2 MiB BSS stack before anything deep runs. - kernel_main.c: riscv64 now builds kernel_main_impl (invoked via the trampoline) instead of kernel_main directly, same pattern as amd64. - Makefile.starkernel: wires the new file into the riscv64 build. - uefi_loader.c: RAW_LOG() was silently a no-op on every non-amd64 arch; added a real raw-UART writer for riscv64 (QEMU virt's uart8250 at MMIO 0x10000000) so existing loader diagnostics actually produce output. Verified: all three architectures boot clean to [Hera] ok> in the required order (amd64, aarch64, riscv64); logs and DoE CSVs from these runs included. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
a852db2209
commit
736627510b
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* kernel_entry.S — kernel stack setup and entry trampoline (riscv64)
|
||||
*
|
||||
* UEFI hands control to kernel_main() running on EDK2's own boot-time stack.
|
||||
* Unlike amd64 (see arch/amd64/kernel_entry.S, which has carried this same
|
||||
* trampoline since early on), riscv64 previously called straight into
|
||||
* kernel_main_impl with no stack switch at all. The VM bootstrap's call
|
||||
* depth (27 chained word-registration modules, physics/SSM init, capsule
|
||||
* birth, Tripod fleet spawn) overflowed EDK2's riscv64 boot stack partway
|
||||
* through vm_init_with_host()'s return, corrupting the return address and
|
||||
* producing a wild jump shortly after — observed as a load/instruction
|
||||
* page fault (scause 0xd or 0xc) whose exact address drifted between
|
||||
* builds while the crash always landed in this same call region. amd64
|
||||
* never had this problem because kernel_entry.S already switches to a
|
||||
* dedicated 2 MiB BSS stack before anything deep runs; aarch64 apparently
|
||||
* gets away with EDK2's default boot stack being large enough, but that's
|
||||
* incidental, not a guarantee.
|
||||
*
|
||||
* kernel_main is the symbol the UEFI loader calls (extern in uefi_loader.c).
|
||||
* kernel_main_impl is defined in kernel_main.c and contains all the C code.
|
||||
*
|
||||
* Calling convention: RISC-V LP64D — boot_info pointer arrives in a0 and is
|
||||
* passed unchanged to kernel_main_impl via the tail-call.
|
||||
*/
|
||||
|
||||
#include "starkernel/boot_info_offsets.h"
|
||||
|
||||
/* 2 MiB kernel stack in BSS — fallback when no dynamic stack requested */
|
||||
.section .bss
|
||||
.align 4
|
||||
.global g_kernel_stack
|
||||
g_kernel_stack:
|
||||
.space 0x200000
|
||||
g_kernel_stack_top:
|
||||
.global g_kernel_stack_top
|
||||
|
||||
.section .text
|
||||
.extern kernel_main_impl
|
||||
|
||||
/*
|
||||
* kernel_main — stack-switch trampoline, then tail-call kernel_main_impl.
|
||||
*
|
||||
* a0 = BootInfo* (RISC-V LP64D ABI — first argument register)
|
||||
*
|
||||
* Stack selection (checked in order):
|
||||
* 1. boot_info->kernel_stack_base != 0 → use loader-allocated stack
|
||||
* (top = base + size, aligned down to 16)
|
||||
* 2. Otherwise → fall back to g_kernel_stack (2 MiB BSS)
|
||||
*
|
||||
* Never returns; kernel_main_impl runs the REPL forever or panics.
|
||||
*/
|
||||
.global kernel_main
|
||||
kernel_main:
|
||||
ld t0, BOOT_INFO_KERNEL_STACK_BASE_OFFSET(a0)
|
||||
bnez t0, .Ldynamic_stack
|
||||
|
||||
/* BSS fallback */
|
||||
la t0, g_kernel_stack_top
|
||||
j .Lstack_ready
|
||||
|
||||
.Ldynamic_stack:
|
||||
ld t1, BOOT_INFO_KERNEL_STACK_SIZE_OFFSET(a0)
|
||||
add t0, t0, t1 /* top = base + size (stack grows down) */
|
||||
|
||||
.Lstack_ready:
|
||||
andi t0, t0, -16 /* 16-byte alignment (RISC-V psABI requirement) */
|
||||
mv sp, t0
|
||||
mv s0, zero /* terminate frame-pointer chain */
|
||||
tail kernel_main_impl /* a0 (boot_info) already in place */
|
||||
Reference in New Issue
Block a user