summaryrefslogtreecommitdiff
path: root/src/arch/riscv/payload.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/riscv/payload.c')
-rw-r--r--src/arch/riscv/payload.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/arch/riscv/payload.c b/src/arch/riscv/payload.c
index 903e8a6ab6..297d30d2a5 100644
--- a/src/arch/riscv/payload.c
+++ b/src/arch/riscv/payload.c
@@ -15,18 +15,44 @@
* GNU General Public License for more details.
*/
+#include <program_loading.h>
#include <stdint.h>
#include <arch/boot.h>
#include <arch/encoding.h>
+#include <arch/smp/atomic.h>
#include <console/console.h>
#include <vm.h>
+/* Run OpenSBI and let OpenSBI hand over control to the payload */
+void run_payload_opensbi(struct prog *prog, void *fdt, struct prog *opensbi, int payload_mode)
+{
+ int hart_id = read_csr(mhartid);
+ uintptr_t status = read_csr(mstatus);
+ status = INSERT_FIELD(status, MSTATUS_MPIE, 0);
+
+ /*
+ * In case of OpenSBI we always run it in M-Mode.
+ * OpenSBI will switch to payload_mode when done.
+ */
+
+ status = INSERT_FIELD(status, MSTATUS_MPP, PRV_M);
+ /* Trap vector base address point to the payload */
+ write_csr(mtvec, prog_entry(opensbi));
+ /* disable M-Mode interrupt */
+ write_csr(mie, 0);
+ write_csr(mstatus, status);
+
+ run_opensbi(hart_id, fdt, prog_entry(opensbi), prog_entry(prog), payload_mode);
+}
+
+/* Runs the payload without OpenSBI integration */
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 = INSERT_FIELD(status, MSTATUS_MPIE, 0);
+
switch (payload_mode) {
case RISCV_PAYLOAD_MODE_U:
status = INSERT_FIELD(status, MSTATUS_MPP, PRV_U);