summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/riscv/Makefile.inc2
-rw-r--r--src/arch/riscv/boot.c31
-rw-r--r--src/arch/riscv/bootblock.S1
-rw-r--r--src/arch/riscv/include/arch/boot.h8
-rw-r--r--src/arch/riscv/include/arch/stages.h3
-rw-r--r--src/arch/riscv/include/mcall.h8
-rw-r--r--src/arch/riscv/mcall.c3
-rw-r--r--src/arch/riscv/payload.S35
-rw-r--r--src/arch/riscv/payload.c51
-rw-r--r--src/arch/riscv/stages.c11
10 files changed, 94 insertions, 59 deletions
diff --git a/src/arch/riscv/Makefile.inc b/src/arch/riscv/Makefile.inc
index e4c8468ef0..9d91f0cefe 100644
--- a/src/arch/riscv/Makefile.inc
+++ b/src/arch/riscv/Makefile.inc
@@ -137,7 +137,7 @@ ramstage-y += misc.c
ramstage-y += smp.c
ramstage-y += boot.c
ramstage-y += tables.c
-ramstage-y += payload.S
+ramstage-y += payload.c
ramstage-$(ARCH_RISCV_PMP) += pmp.c
ramstage-y += \
$(top)/src/lib/memchr.c \
diff --git a/src/arch/riscv/boot.c b/src/arch/riscv/boot.c
index 3d8d5d623e..29064b1dc1 100644
--- a/src/arch/riscv/boot.c
+++ b/src/arch/riscv/boot.c
@@ -19,6 +19,7 @@
#include <arch/encoding.h>
#include <console/console.h>
#include <arch/smp/smp.h>
+#include <mcall.h>
/*
* A pointer to the Flattened Device Tree passed to coreboot by the boot ROM.
@@ -26,27 +27,29 @@
*
* This pointer is only used in ramstage!
*/
-const void *rom_fdt;
static void do_arch_prog_run(struct prog *prog)
{
- void (*doit)(void *) = prog_entry(prog);
- void riscvpayload(const void *fdt, void *payload);
+ void (*doit)(int hart_id, void *fdt);
+ int hart_id;
+ void *fdt = prog_entry_arg(prog);
+
+ /*
+ * If prog_entry_arg is not set (e.g. by fit_payload), use fdt from HLS
+ * instead.
+ */
+ if (fdt == NULL)
+ fdt = HLS()->fdt;
if (ENV_RAMSTAGE && prog_type(prog) == PROG_PAYLOAD) {
- /*
- * FIXME: This is wrong and will crash. Linux can't (in early
- * boot) access memory that's before its own loading address.
- * We need to copy the FDT to a place where Linux can access it.
- */
- const void *fdt = rom_fdt;
-
- printk(BIOS_SPEW, "FDT is at %p\n", fdt);
- printk(BIOS_SPEW, "OK, let's go\n");
- riscvpayload(fdt, doit);
+ run_payload(prog, fdt, RISCV_PAYLOAD_MODE_S);
+ return;
}
- doit(prog_entry_arg(prog));
+ doit = prog_entry(prog);
+ hart_id = HLS()->hart_id;
+
+ doit(hart_id, fdt);
}
void arch_prog_run(struct prog *prog)
diff --git a/src/arch/riscv/bootblock.S b/src/arch/riscv/bootblock.S
index 7f84215dac..d4b8be7c2a 100644
--- a/src/arch/riscv/bootblock.S
+++ b/src/arch/riscv/bootblock.S
@@ -50,6 +50,7 @@ _start:
# initialize hart-local storage
csrr a0, mhartid
+ csrrw a1, mscratch, zero
call hls_init
li a0, CONFIG_RISCV_WORKING_HARTID
diff --git a/src/arch/riscv/include/arch/boot.h b/src/arch/riscv/include/arch/boot.h
index 24c1bedebf..34a507edec 100644
--- a/src/arch/riscv/include/arch/boot.h
+++ b/src/arch/riscv/include/arch/boot.h
@@ -16,6 +16,12 @@
#ifndef ARCH_RISCV_INCLUDE_ARCH_BOOT_H
#define ARCH_RISCV_INCLUDE_ARCH_BOOT_H
-extern const void *rom_fdt;
+#include <program_loading.h>
+
+#define RISCV_PAYLOAD_MODE_U 0
+#define RISCV_PAYLOAD_MODE_S 1
+#define RISCV_PAYLOAD_MODE_M 3
+
+void run_payload(struct prog *prog, void *fdt, int payload_mode);
#endif
diff --git a/src/arch/riscv/include/arch/stages.h b/src/arch/riscv/include/arch/stages.h
index 90bd60b9a6..138298fd03 100644
--- a/src/arch/riscv/include/arch/stages.h
+++ b/src/arch/riscv/include/arch/stages.h
@@ -18,6 +18,7 @@
#include <main_decl.h>
-void stage_entry(void) __attribute__((section(".text.stage_entry")));
+void stage_entry(int hart_id, void *fdt)
+ __attribute__((section(".text.stage_entry")));
#endif
diff --git a/src/arch/riscv/include/mcall.h b/src/arch/riscv/include/mcall.h
index 29df736d1b..cd1ed6dc18 100644
--- a/src/arch/riscv/include/mcall.h
+++ b/src/arch/riscv/include/mcall.h
@@ -52,9 +52,14 @@ typedef struct {
int ipi_pending;
uint64_t *timecmp;
uint64_t *time;
+ void *fdt;
struct blocker entry;
} hls_t;
+_Static_assert(
+ sizeof(hls_t) == HLS_SIZE,
+ "HLS_SIZE must equal to sizeof(hls_t)");
+
#define MACHINE_STACK_TOP() ({ \
/* coverity[uninit_use] : FALSE */ \
register uintptr_t sp asm ("sp"); \
@@ -66,7 +71,8 @@ typedef struct {
#define MACHINE_STACK_SIZE RISCV_PGSIZE
-void hls_init(uint32_t hart_id); // need to call this before launching linux
+// need to call this before launching linux
+void hls_init(uint32_t hart_id, void *fdt);
/* This function is used to initialize HLS()->time/HLS()->timecmp */
void mtime_init(void);
diff --git a/src/arch/riscv/mcall.c b/src/arch/riscv/mcall.c
index 47cdd88d4d..eaef6442c5 100644
--- a/src/arch/riscv/mcall.c
+++ b/src/arch/riscv/mcall.c
@@ -34,10 +34,11 @@
int mcalldebug; // set this interactively for copious debug.
-void hls_init(uint32_t hart_id)
+void hls_init(uint32_t hart_id, void *fdt)
{
printk(BIOS_SPEW, "hart %d: HLS is %p\n", hart_id, HLS());
memset(HLS(), 0, sizeof(*HLS()));
+ HLS()->fdt = fdt;
HLS()->hart_id = hart_id;
mtime_init();
diff --git a/src/arch/riscv/payload.S b/src/arch/riscv/payload.S
deleted file mode 100644
index 1b8cb96110..0000000000
--- a/src/arch/riscv/payload.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2016 Google Inc
- * Copyright (C) 2018 Jonathan Neuschäfer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-// "return" to a payload. a0: FDT, a1: entry point
- .global riscvpayload
-riscvpayload:
- /* Load the entry point */
- mv t0, a1
- csrw mepc, t0
- csrr t0, mstatus
-
- /* Set mstatus.MPP (the previous privilege mode) to supervisor mode */
- li t1, ~(3<<11)
- and t0, t0, t1
- li t2, (1<<11)
- or t0, t0, t2
- csrw mstatus, t0
-
- /* Pass the right arguments and jump! */
- mv a1, a0
- csrr a0, mhartid
- mret
diff --git a/src/arch/riscv/payload.c b/src/arch/riscv/payload.c
new file mode 100644
index 0000000000..8a07ff879f
--- /dev/null
+++ b/src/arch/riscv/payload.c
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Google Inc
+ * Copyright (C) 2018 HardenedLinux
+ * Copyright (C) 2018 Jonathan Neuschäfer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdint.h>
+#include <arch/boot.h>
+#include <arch/encoding.h>
+#include <console/console.h>
+
+void run_payload(struct prog *prog, void *fdt, int payload_mode)
+{
+ void (*doit)(int hart_id, void *fdt) = prog_entry(prog);
+ int hart_id = read_csr(mhartid);
+ uintptr_t status = read_csr(mstatus);
+ status &= ~MSTATUS_MPIE;
+ status &= ~MSTATUS_MPP;
+ switch (payload_mode) {
+ case RISCV_PAYLOAD_MODE_U:
+ break;
+ case RISCV_PAYLOAD_MODE_S:
+ status |= MSTATUS_SPP;
+ break;
+ case RISCV_PAYLOAD_MODE_M:
+ doit(hart_id, fdt);
+ return;
+ default:
+ die("wrong privilege level for payload");
+ break;
+ }
+ write_csr(mstatus, status);
+ write_csr(mepc, doit);
+ asm volatile(
+ "mv a0, %0\n\t"
+ "mv a1, %0\n\t"
+ "mret" ::"r"(hart_id),
+ "r"(fdt)
+ : "a0", "a1");
+}
diff --git a/src/arch/riscv/stages.c b/src/arch/riscv/stages.c
index 5e7fa4f75b..07b898f853 100644
--- a/src/arch/riscv/stages.c
+++ b/src/arch/riscv/stages.c
@@ -28,18 +28,19 @@
#include <arch/encoding.h>
#include <arch/stages.h>
#include <arch/smp/smp.h>
+#include <rules.h>
+#include <mcall.h>
-void stage_entry(void)
+void stage_entry(int hart_id, void *fdt)
{
- smp_pause(CONFIG_RISCV_WORKING_HARTID);
-
/*
* Save the FDT pointer before entering ramstage, because mscratch
* might be overwritten in the trap handler, and there is code in
* ramstage that generates misaligned access faults.
*/
- if (ENV_RAMSTAGE)
- rom_fdt = (const void *)read_csr(mscratch);
+ HLS()->hart_id = hart_id;
+ HLS()->fdt = fdt;
+ smp_pause(CONFIG_RISCV_WORKING_HARTID);
main();
}