diff options
-rw-r--r-- | src/arch/riscv/Makefile.mk | 2 | ||||
-rw-r--r-- | src/arch/riscv/include/arch/exception.h | 2 | ||||
-rw-r--r-- | src/arch/riscv/ramdetect.c | 61 | ||||
-rw-r--r-- | src/arch/riscv/trap_handler.c | 30 | ||||
-rw-r--r-- | src/arch/riscv/trap_util.S | 7 | ||||
-rw-r--r-- | src/lib/ramdetect.c | 9 | ||||
-rw-r--r-- | src/mainboard/emulation/qemu-riscv/Kconfig | 5 |
7 files changed, 93 insertions, 23 deletions
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 <arch/exception.h> +#include <types.h> +#include <console/console.h> +#include <device/mmio.h> +#include <ramdetect.h> +#include <arch/smp/spinlock.h> +#include <vm.h> + +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 diff --git a/src/lib/ramdetect.c b/src/lib/ramdetect.c index 9a29d0fe94..cef3d57234 100644 --- a/src/lib/ramdetect.c +++ b/src/lib/ramdetect.c @@ -11,15 +11,12 @@ int __weak probe_mb(const uintptr_t dram_start, const uintptr_t size) { uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t); - static const uint32_t patterns[] = { - 0x55aa55aa, - 0x12345678 - }; - void *ptr = (void *) addr; + static const uint32_t patterns[] = {0x55aa55aa, 0x12345678}; + void *ptr = (void *)addr; size_t i; /* Don't accidentally clobber oneself. */ - if (OVERLAP(addr, addr + sizeof(uint32_t), (uintptr_t)_program, (uintptr_t) _eprogram)) + if (OVERLAP(addr, addr + sizeof(uint32_t), (uintptr_t)_program, (uintptr_t)_eprogram)) return 1; uint32_t old = read32(ptr); diff --git a/src/mainboard/emulation/qemu-riscv/Kconfig b/src/mainboard/emulation/qemu-riscv/Kconfig index d915d6826e..af4416d0c1 100644 --- a/src/mainboard/emulation/qemu-riscv/Kconfig +++ b/src/mainboard/emulation/qemu-riscv/Kconfig @@ -45,7 +45,10 @@ config MAX_CPUS config DRAM_SIZE_MB int - default 32768 + default 16383 + help + Qemu maps MMIO at ALIGN_UP(top_of_mem, 16 * GiB) + To avoid confusing the dram probing algorithm, avoid large dram sizes (16G - 1m) config OPENSBI_PLATFORM string |