From 8e365396d4274b8656fd5c3bd47e9e8953db7e59 Mon Sep 17 00:00:00 2001 From: Philipp Hug Date: Fri, 1 Mar 2024 10:59:56 +0000 Subject: riscv/mb/qemu: fix DRAM probing Current version of qemu raise an exception when accessing invalid memory. Modify the probing code to temporary redirect the exception handler like on ARM platform. Also move saving of the stack frame out to trap_util.S to have all at the same place for a future rewrite. TEST=boots to ramstage Change-Id: I25860f688c7546714f6fdbce8c8f96da6400813c Signed-off-by: Philipp Hug Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/36486 Reviewed-by: ron minnich Tested-by: build bot (Jenkins) --- src/arch/riscv/Makefile.mk | 2 ++ src/arch/riscv/include/arch/exception.h | 2 +- src/arch/riscv/ramdetect.c | 61 +++++++++++++++++++++++++++++++++ src/arch/riscv/trap_handler.c | 30 ++++++++-------- src/arch/riscv/trap_util.S | 7 +++- 5 files changed, 86 insertions(+), 16 deletions(-) create mode 100644 src/arch/riscv/ramdetect.c (limited to 'src/arch/riscv') diff --git a/src/arch/riscv/Makefile.mk b/src/arch/riscv/Makefile.mk index 1267195b21..0dbfd2a31e 100644 --- a/src/arch/riscv/Makefile.mk +++ b/src/arch/riscv/Makefile.mk @@ -97,6 +97,7 @@ endif #CONFIG_ARCH_BOOTBLOCK_RISCV ifeq ($(CONFIG_ARCH_ROMSTAGE_RISCV),y) romstage-$(CONFIG_SEPARATE_ROMSTAGE) += romstage.S +romstage-y += ramdetect.c # Build the romstage @@ -120,6 +121,7 @@ ifeq ($(CONFIG_ARCH_RAMSTAGE_RISCV),y) ramstage-y = ramstage-y += ramstage.S +ramstage-y += ramdetect.c ramstage-y += tables.c ramstage-y += payload.c ramstage-y += fit_payload.c diff --git a/src/arch/riscv/include/arch/exception.h b/src/arch/riscv/include/arch/exception.h index 208cc81e24..9339437019 100644 --- a/src/arch/riscv/include/arch/exception.h +++ b/src/arch/riscv/include/arch/exception.h @@ -26,7 +26,7 @@ static inline void exception_init(void) } void redirect_trap(void); -void trap_handler(trapframe *tf); +void default_trap_handler(trapframe *tf); void handle_supervisor_call(trapframe *tf); void handle_misaligned(trapframe *tf); diff --git a/src/arch/riscv/ramdetect.c b/src/arch/riscv/ramdetect.c new file mode 100644 index 0000000000..3382435cdf --- /dev/null +++ b/src/arch/riscv/ramdetect.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include +#include +#include +#include +#include + +static enum { + ABORT_CHECKER_NOT_TRIGGERED, + ABORT_CHECKER_TRIGGERED, +} abort_state = ABORT_CHECKER_NOT_TRIGGERED; + +extern void (*trap_handler)(trapframe *tf); + +static int get_instruction_len(uintptr_t addr) +{ + uint16_t ins = read16p(addr); + + /* + * 16-bit or 32-bit instructions supported + */ + if ((ins & 0x3) != 3) { + return 2; + } else if ((ins & 0x1f) != 0x1f) { + return 4; + } + + die("Not a 16bit or 32bit instruction 0x%x\n", ins); +} + +static void ramcheck_trap_handler(trapframe *tf) +{ + abort_state = ABORT_CHECKER_TRIGGERED; + + /* + * skip read instruction. + */ + int insn_size = get_instruction_len(tf->epc); + + write_csr(mepc, read_csr(mepc) + insn_size); +} + +int probe_mb(const uintptr_t dram_start, const uintptr_t size) +{ + uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t); + void *ptr = (void *)addr; + + abort_state = ABORT_CHECKER_NOT_TRIGGERED; + trap_handler = ramcheck_trap_handler; + barrier(); + read32(ptr); + trap_handler = default_trap_handler; + barrier(); + printk(BIOS_DEBUG, "%lx is %s DRAM\n", dram_start + size * MiB, + abort_state == ABORT_CHECKER_NOT_TRIGGERED ? "" : "not"); + + return abort_state == ABORT_CHECKER_NOT_TRIGGERED; +} diff --git a/src/arch/riscv/trap_handler.c b/src/arch/riscv/trap_handler.c index fbc6ae4c0e..4cbccc5892 100644 --- a/src/arch/riscv/trap_handler.c +++ b/src/arch/riscv/trap_handler.c @@ -33,10 +33,14 @@ static const char *const exception_names[] = { static const char *mstatus_to_previous_mode(uintptr_t ms) { switch (ms & MSTATUS_MPP) { - case 0x00000000: return "user"; - case 0x00000800: return "supervisor"; - case 0x00001000: return "hypervisor"; - case 0x00001800: return "machine"; + case 0x00000000: + return "user"; + case 0x00000800: + return "supervisor"; + case 0x00001000: + return "hypervisor"; + case 0x00001800: + return "machine"; } return "unknown"; @@ -52,16 +56,13 @@ static void print_trap_information(const trapframe *tf) printk(BIOS_DEBUG, "\n"); if (tf->cause < ARRAY_SIZE(exception_names)) - printk(BIOS_DEBUG, "Exception: %s\n", - exception_names[tf->cause]); + printk(BIOS_DEBUG, "Exception: %s\n", exception_names[tf->cause]); else - printk(BIOS_DEBUG, "Trap: Unknown cause %p\n", - (void *)tf->cause); + printk(BIOS_DEBUG, "Trap: Unknown cause %p\n", (void *)tf->cause); previous_mode = mstatus_to_previous_mode(read_csr(mstatus)); printk(BIOS_DEBUG, "Hart ID: %d\n", hart_id); - printk(BIOS_DEBUG, "Previous mode: %s%s\n", - previous_mode, mprv? " (MPRV)":""); + printk(BIOS_DEBUG, "Previous mode: %s%s\n", previous_mode, mprv ? " (MPRV)" : ""); printk(BIOS_DEBUG, "Bad instruction pc: %p\n", (void *)tf->epc); printk(BIOS_DEBUG, "Bad address: %p\n", (void *)tf->badvaddr); printk(BIOS_DEBUG, "Stored ra: %p\n", (void *)tf->gpr[1]); @@ -101,16 +102,17 @@ static void interrupt_handler(trapframe *tf) break; default: printk(BIOS_EMERG, "======================================\n"); - printk(BIOS_EMERG, "coreboot: Unknown machine interrupt: 0x%llx\n", - cause); + printk(BIOS_EMERG, "coreboot: Unknown machine interrupt: 0x%llx\n", cause); printk(BIOS_EMERG, "======================================\n"); print_trap_information(tf); break; } } -void trap_handler(trapframe *tf) + +void (*trap_handler)(trapframe *tf) = default_trap_handler; + +void default_trap_handler(trapframe *tf) { - write_csr(mscratch, tf); if (tf->cause & 0x8000000000000000ULL) { interrupt_handler(tf); return; diff --git a/src/arch/riscv/trap_util.S b/src/arch/riscv/trap_util.S index c5691c595f..d7b1250b7a 100644 --- a/src/arch/riscv/trap_util.S +++ b/src/arch/riscv/trap_util.S @@ -121,7 +121,12 @@ trap_entry: save_tf move a0,sp - jal trap_handler + + # store pointer to stack frame (moved out from trap_handler) + csrw mscratch, sp + + LOAD t0, trap_handler + jalr t0 trap_return: csrr a0, mscratch -- cgit v1.2.3