From b1e6654d86fff0016651ede345846f4437a2569c Mon Sep 17 00:00:00 2001 From: Xiang Wang Date: Fri, 14 Jun 2019 16:45:54 +0800 Subject: riscv: use mret to invoke M-mode payload and disable interrupts Fixes a logic error that sets MPIE, but didn't use mret to return to the payload. This left MIE set to an undefined value. Now all modes are handled the same way: - Trap vector base address point to the payload - Disable Interrupt - Return to payload using mret TEST=Run an M-mode payload Change-Id: Iaab595f916949c57104ec00f8b06ea047fe76bba Signed-off-by: Xiang Wang Reviewed-on: https://review.coreboot.org/c/coreboot/+/33462 Reviewed-by: Philipp Hug Reviewed-by: Patrick Rudolph Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/arch/riscv/payload.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'src/arch') diff --git a/src/arch/riscv/payload.c b/src/arch/riscv/payload.c index f3ed5a44a6..903e8a6ab6 100644 --- a/src/arch/riscv/payload.c +++ b/src/arch/riscv/payload.c @@ -19,23 +19,38 @@ #include #include #include +#include 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; + status = INSERT_FIELD(status, MSTATUS_MPIE, 0); switch (payload_mode) { case RISCV_PAYLOAD_MODE_U: + status = INSERT_FIELD(status, MSTATUS_MPP, PRV_U); + /* Trap vector base address point to the payload */ + write_csr(utvec, doit); + /* disable U-Mode interrupt */ + write_csr(uie, 0); break; case RISCV_PAYLOAD_MODE_S: - status |= MSTATUS_SPP; + status = INSERT_FIELD(status, MSTATUS_MPP, PRV_S); + /* Trap vector base address point to the payload */ + write_csr(stvec, doit); + /* disable S-Mode interrupt */ + write_csr(sie, 0); + /* disable MMU */ + write_csr(satp, 0); break; case RISCV_PAYLOAD_MODE_M: - doit(hart_id, fdt); - return; + status = INSERT_FIELD(status, MSTATUS_MPP, PRV_M); + /* Trap vector base address point to the payload */ + write_csr(mtvec, doit); + /* disable M-Mode interrupt */ + write_csr(mie, 0); + break; default: die("wrong privilege level for payload"); break; -- cgit v1.2.3