ron minnich submitted this change.

View Change

Approvals: build bot (Jenkins): Verified ron minnich: Looks good to me, approved Arthur Heymans: Looks good to me, approved
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 <philipp@hug.cx>
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/36486
Reviewed-by: ron minnich <rminnich@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
---
M src/arch/riscv/Makefile.mk
M src/arch/riscv/include/arch/exception.h
A src/arch/riscv/ramdetect.c
M src/arch/riscv/trap_handler.c
M src/arch/riscv/trap_util.S
M src/lib/ramdetect.c
M src/mainboard/emulation/qemu-riscv/Kconfig
7 files changed, 93 insertions(+), 23 deletions(-)

diff --git a/src/arch/riscv/Makefile.mk b/src/arch/riscv/Makefile.mk
index 1267195..0dbfd2a 100644
--- a/src/arch/riscv/Makefile.mk
+++ b/src/arch/riscv/Makefile.mk
@@ -97,6 +97,7 @@
ifeq ($(CONFIG_ARCH_ROMSTAGE_RISCV),y)

romstage-$(CONFIG_SEPARATE_ROMSTAGE) += romstage.S
+romstage-y += ramdetect.c

# Build the romstage

@@ -120,6 +121,7 @@

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 208cc81..9339437 100644
--- a/src/arch/riscv/include/arch/exception.h
+++ b/src/arch/riscv/include/arch/exception.h
@@ -26,7 +26,7 @@
}

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 0000000..3382435
--- /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 fbc6ae4..4cbccc5 100644
--- a/src/arch/riscv/trap_handler.c
+++ b/src/arch/riscv/trap_handler.c
@@ -33,10 +33,14 @@
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 @@
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 @@
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 c5691c5..d7b1250 100644
--- a/src/arch/riscv/trap_util.S
+++ b/src/arch/riscv/trap_util.S
@@ -121,7 +121,12 @@

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 9a29d0f..cef3d57 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 d915d68..af4416d 100644
--- a/src/mainboard/emulation/qemu-riscv/Kconfig
+++ b/src/mainboard/emulation/qemu-riscv/Kconfig
@@ -45,7 +45,10 @@

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

To view, visit change 36486. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: main
Gerrit-Change-Id: I25860f688c7546714f6fdbce8c8f96da6400813c
Gerrit-Change-Number: 36486
Gerrit-PatchSet: 18
Gerrit-Owner: Philipp Hug <philipp@hug.cx>
Gerrit-Reviewer: Arthur Heymans <arthur@aheymans.xyz>
Gerrit-Reviewer: Marc Karasek <marckarasek@gmail.com>
Gerrit-Reviewer: Martin L Roth <gaumless@gmail.com>
Gerrit-Reviewer: Maximilian Brune <maximilian.brune@9elements.com>
Gerrit-Reviewer: Philipp Hug <philipp@hug.cx>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-Reviewer: ron minnich <rminnich@gmail.com>
Gerrit-CC: Arthur Heymans <arthur.heymans@9elements.com>
Gerrit-CC: Felix Singer <service+coreboot-gerrit@felixsinger.de>
Gerrit-CC: Patrick Rudolph <patrick.rudolph@9elements.com>
Gerrit-CC: Paul Menzel <paulepanter@mailbox.org>
Gerrit-CC: ron minnich
Gerrit-MessageType: merged