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
@@ -180,6 +180,47 @@ static void raw_serial_puts(const char *s)
|
||||
}
|
||||
}
|
||||
#define RAW_LOG(str) raw_serial_puts(str)
|
||||
|
||||
#elif defined(__riscv) || defined(ARCH_RISCV64)
|
||||
|
||||
/*
|
||||
* QEMU's riscv "virt" machine exposes a 16550-compatible UART (OpenSBI
|
||||
* reports "Platform Console Device: uart8250") as byte-addressed MMIO at
|
||||
* 0x10000000 (matches Domain0 Region03 in the OpenSBI boot banner). This
|
||||
* writes directly to the UART registers, exactly like the amd64
|
||||
* raw_serial_* helpers above, so RAW_LOG() actually produces output on
|
||||
* riscv64 instead of silently no-op'ing (previously the case for every
|
||||
* arch except amd64).
|
||||
*/
|
||||
#define UART_MMIO_BASE 0x10000000UL
|
||||
|
||||
static inline void raw_mmio_outb(uint64_t addr, uint8_t val)
|
||||
{
|
||||
*(volatile uint8_t *)addr = val;
|
||||
}
|
||||
|
||||
static inline uint8_t raw_mmio_inb(uint64_t addr)
|
||||
{
|
||||
return *(volatile uint8_t *)addr;
|
||||
}
|
||||
|
||||
static void raw_serial_putc(char c)
|
||||
{
|
||||
while ((raw_mmio_inb(UART_MMIO_BASE + 5) & 0x20) == 0) { }
|
||||
raw_mmio_outb(UART_MMIO_BASE + 0, (uint8_t)c);
|
||||
}
|
||||
|
||||
static void raw_serial_puts(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
char c = *s++;
|
||||
if (c == '\n') raw_serial_putc('\r');
|
||||
raw_serial_putc(c);
|
||||
}
|
||||
}
|
||||
#define RAW_LOG(str) raw_serial_puts(str)
|
||||
|
||||
#else
|
||||
#define RAW_LOG(str) ((void)0)
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user