diff options
Diffstat (limited to 'src/arch/riscv/payload.c')
-rw-r--r-- | src/arch/riscv/payload.c | 26 |
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); |