lib: Better naming of unpriv APIs for wider use

The unpriv APIs can be useful to external firmware and out-of-tree
platform support code.

This patch adds "sbi_" prefix to unpriv load/store APIs and rename
struct riscv_unpriv to struct sbi_trap_info everywhere. We also
place struct sbi_trap_info in sbi/sbi_trap.h so that we can use
it for sbi_trap_redirect() as well.

Overall, this patch will make naming of unpriv APIs consistent
with other OpenSBI APIs.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
This commit is contained in:
Anup Patel 2019-11-17 14:16:24 +05:30 committed by Anup Patel
parent b1d8c988bc
commit 0e1322bacb
10 changed files with 145 additions and 106 deletions

View File

@ -10,7 +10,6 @@
#ifndef __SBI_IPI_H__ #ifndef __SBI_IPI_H__
#define __SBI_IPI_H__ #define __SBI_IPI_H__
#include <sbi/riscv_unpriv.h>
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
/* clang-format off */ /* clang-format off */
@ -24,12 +23,14 @@
/* clang-format on */ /* clang-format on */
struct sbi_scratch; struct sbi_scratch;
struct sbi_trap_info;
struct sbi_ipi_data { struct sbi_ipi_data {
unsigned long ipi_type; unsigned long ipi_type;
}; };
int sbi_ipi_send_many(struct sbi_scratch *scratch, struct unpriv_trap *uptrap, int sbi_ipi_send_many(struct sbi_scratch *scratch,
struct sbi_trap_info *uptrap,
ulong *pmask, u32 event, void *data); ulong *pmask, u32 event, void *data);
void sbi_ipi_clear_smode(struct sbi_scratch *scratch); void sbi_ipi_clear_smode(struct sbi_scratch *scratch);

View File

@ -170,12 +170,24 @@ struct sbi_trap_regs {
unsigned long mstatusH; unsigned long mstatusH;
} __packed; } __packed;
/** Representation of trap details */
struct sbi_trap_info {
/** epc Trap program counter */
unsigned long epc;
/** cause Trap exception cause */
unsigned long cause;
/** tval Trap value */
unsigned long tval;
};
struct sbi_scratch; struct sbi_scratch;
int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch, int sbi_trap_redirect(struct sbi_trap_regs *regs,
ulong epc, ulong cause, ulong tval); struct sbi_trap_info *trap,
struct sbi_scratch *scratch);
void sbi_trap_handler(struct sbi_trap_regs *regs, struct sbi_scratch *scratch); void sbi_trap_handler(struct sbi_trap_regs *regs,
struct sbi_scratch *scratch);
#endif #endif

View File

@ -7,27 +7,23 @@
* Anup Patel <anup.patel@wdc.com> * Anup Patel <anup.patel@wdc.com>
*/ */
#ifndef __RISCV_UNPRIV_H__ #ifndef __SBI_UNPRIV_H__
#define __RISCV_UNPRIV_H__ #define __SBI_UNPRIV_H__
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
struct sbi_scratch; struct sbi_scratch;
struct sbi_trap_info;
struct unpriv_trap { #define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type) \
unsigned long cause; type sbi_load_##type(const type *addr, \
unsigned long tval; struct sbi_scratch *scratch, \
}; struct sbi_trap_info *trap);
#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type) \ #define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type) \
type load_##type(const type *addr, \ void sbi_store_##type(type *addr, type val, \
struct sbi_scratch *scratch, \ struct sbi_scratch *scratch, \
struct unpriv_trap *trap); struct sbi_trap_info *trap);
#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type) \
void store_##type(type *addr, type val, \
struct sbi_scratch *scratch, \
struct unpriv_trap *trap);
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8)
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16)
@ -42,7 +38,7 @@ DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u64)
DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64) DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64)
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong)
ulong get_insn(ulong mepc, struct sbi_scratch *scratch, ulong sbi_get_insn(ulong mepc, struct sbi_scratch *scratch,
struct unpriv_trap *trap); struct sbi_trap_info *trap);
#endif #endif

View File

@ -11,7 +11,6 @@ libsbi-objs-y += riscv_asm.o
libsbi-objs-y += riscv_atomic.o libsbi-objs-y += riscv_atomic.o
libsbi-objs-y += riscv_hardfp.o libsbi-objs-y += riscv_hardfp.o
libsbi-objs-y += riscv_locks.o libsbi-objs-y += riscv_locks.o
libsbi-objs-y += riscv_unpriv.o
libsbi-objs-y += sbi_console.o libsbi-objs-y += sbi_console.o
libsbi-objs-y += sbi_ecall.o libsbi-objs-y += sbi_ecall.o
@ -28,3 +27,4 @@ libsbi-objs-y += sbi_timer.o
libsbi-objs-y += sbi_tlb.o libsbi-objs-y += sbi_tlb.o
libsbi-objs-y += sbi_trap.o libsbi-objs-y += sbi_trap.o
libsbi-objs-y += sbi_string.o libsbi-objs-y += sbi_string.o
libsbi-objs-y += sbi_unpriv.o

View File

@ -118,7 +118,7 @@ int sbi_ecall_0_1_handler(struct sbi_scratch *scratch, unsigned long extid,
int ret = 0; int ret = 0;
struct sbi_tlb_info tlb_info; struct sbi_tlb_info tlb_info;
u32 source_hart = sbi_current_hartid(); u32 source_hart = sbi_current_hartid();
struct unpriv_trap uptrap = {0}; struct sbi_trap_info uptrap = {0};
switch (extid) { switch (extid) {
case SBI_EXT_0_1_SET_TIMER: case SBI_EXT_0_1_SET_TIMER:
@ -190,9 +190,8 @@ int sbi_ecall_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs,
int ret = 0; int ret = 0;
unsigned long extension_id = regs->a7; unsigned long extension_id = regs->a7;
unsigned long func_id = regs->a6; unsigned long func_id = regs->a6;
struct sbi_trap_info trap = {0};
unsigned long out_val; unsigned long out_val;
unsigned long out_tval;
unsigned long out_tcause;
bool is_0_1_spec = 0; bool is_0_1_spec = 0;
unsigned long args[6]; unsigned long args[6];
@ -206,24 +205,24 @@ int sbi_ecall_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs,
if (extension_id >= SBI_EXT_0_1_SET_TIMER && if (extension_id >= SBI_EXT_0_1_SET_TIMER &&
extension_id <= SBI_EXT_0_1_SHUTDOWN) { extension_id <= SBI_EXT_0_1_SHUTDOWN) {
ret = sbi_ecall_0_1_handler(scratch, extension_id, args, ret = sbi_ecall_0_1_handler(scratch, extension_id, args,
&out_tval, &out_tcause); &trap.tval, &trap.cause);
is_0_1_spec = 1; is_0_1_spec = 1;
} else if (extension_id == SBI_EXT_BASE) } else if (extension_id == SBI_EXT_BASE)
ret = sbi_ecall_base_handler(scratch, extension_id, func_id, ret = sbi_ecall_base_handler(scratch, extension_id, func_id,
args, &out_val, args, &out_val,
&out_tval, &out_tcause); &trap.tval, &trap.cause);
else if (extension_id >= SBI_EXT_VENDOR_START && else if (extension_id >= SBI_EXT_VENDOR_START &&
extension_id <= SBI_EXT_VENDOR_END) { extension_id <= SBI_EXT_VENDOR_END) {
ret = sbi_ecall_vendor_ext_handler(scratch, extension_id, ret = sbi_ecall_vendor_ext_handler(scratch, extension_id,
func_id, args, &out_val, func_id, args, &out_val,
&out_tval, &out_tcause); &trap.tval, &trap.cause);
} else { } else {
ret = SBI_ENOTSUPP; ret = SBI_ENOTSUPP;
} }
if (ret == SBI_ETRAP) { if (ret == SBI_ETRAP) {
sbi_trap_redirect(regs, scratch, regs->mepc, trap.epc = regs->mepc;
out_tcause, out_tval); sbi_trap_redirect(regs, &trap, scratch);
} else { } else {
/* This function should return non-zero value only in case of /* This function should return non-zero value only in case of
* fatal error. However, there is no good way to distinguish * fatal error. However, there is no good way to distinguish

View File

@ -9,12 +9,12 @@
#include <sbi/riscv_asm.h> #include <sbi/riscv_asm.h>
#include <sbi/riscv_encoding.h> #include <sbi/riscv_encoding.h>
#include <sbi/riscv_unpriv.h>
#include <sbi/sbi_bits.h> #include <sbi/sbi_bits.h>
#include <sbi/sbi_emulate_csr.h> #include <sbi/sbi_emulate_csr.h>
#include <sbi/sbi_error.h> #include <sbi/sbi_error.h>
#include <sbi/sbi_illegal_insn.h> #include <sbi/sbi_illegal_insn.h>
#include <sbi/sbi_trap.h> #include <sbi/sbi_trap.h>
#include <sbi/sbi_unpriv.h>
typedef int (*illegal_insn_func)(ulong insn, u32 hartid, ulong mcause, typedef int (*illegal_insn_func)(ulong insn, u32 hartid, ulong mcause,
struct sbi_trap_regs *regs, struct sbi_trap_regs *regs,
@ -24,7 +24,13 @@ static int truly_illegal_insn(ulong insn, u32 hartid, ulong mcause,
struct sbi_trap_regs *regs, struct sbi_trap_regs *regs,
struct sbi_scratch *scratch) struct sbi_scratch *scratch)
{ {
return sbi_trap_redirect(regs, scratch, regs->mepc, mcause, insn); struct sbi_trap_info trap;
trap.epc = regs->mepc;
trap.cause = mcause;
trap.tval = insn;
return sbi_trap_redirect(regs, &trap, scratch);
} }
static int system_opcode_insn(ulong insn, u32 hartid, ulong mcause, static int system_opcode_insn(ulong insn, u32 hartid, ulong mcause,
@ -46,8 +52,8 @@ static int system_opcode_insn(ulong insn, u32 hartid, ulong mcause,
if ((regs->mstatus & MSTATUS_MPV) && if ((regs->mstatus & MSTATUS_MPV) &&
#endif #endif
(insn & INSN_MASK_WFI) == INSN_MATCH_WFI) (insn & INSN_MASK_WFI) == INSN_MATCH_WFI)
return sbi_trap_redirect(regs, scratch, return truly_illegal_insn(insn, hartid, mcause,
regs->mepc, mcause, insn); regs, scratch);
if (sbi_emulate_csr_read(csr_num, hartid, regs, scratch, &csr_val)) if (sbi_emulate_csr_read(csr_num, hartid, regs, scratch, &csr_val))
return truly_illegal_insn(insn, hartid, mcause, return truly_illegal_insn(insn, hartid, mcause,
@ -130,14 +136,16 @@ int sbi_illegal_insn_handler(u32 hartid, ulong mcause,
struct sbi_scratch *scratch) struct sbi_scratch *scratch)
{ {
ulong insn = csr_read(CSR_MTVAL); ulong insn = csr_read(CSR_MTVAL);
struct unpriv_trap uptrap; struct sbi_trap_info uptrap;
if (unlikely((insn & 3) != 3)) { if (unlikely((insn & 3) != 3)) {
if (insn == 0) { if (insn == 0) {
insn = get_insn(regs->mepc, scratch, &uptrap); insn = sbi_get_insn(regs->mepc, scratch, &uptrap);
if (uptrap.cause) if (uptrap.cause) {
return sbi_trap_redirect(regs, scratch, uptrap.epc = regs->mepc;
regs->mepc, uptrap.cause, uptrap.tval); return sbi_trap_redirect(regs, &uptrap,
scratch);
}
} }
if ((insn & 3) != 3) if ((insn & 3) != 3)
return truly_illegal_insn(insn, hartid, mcause, regs, return truly_illegal_insn(insn, hartid, mcause, regs,

View File

@ -11,12 +11,13 @@
#include <sbi/riscv_asm.h> #include <sbi/riscv_asm.h>
#include <sbi/riscv_atomic.h> #include <sbi/riscv_atomic.h>
#include <sbi/riscv_barrier.h> #include <sbi/riscv_barrier.h>
#include <sbi/riscv_unpriv.h>
#include <sbi/sbi_error.h> #include <sbi/sbi_error.h>
#include <sbi/sbi_hart.h> #include <sbi/sbi_hart.h>
#include <sbi/sbi_ipi.h> #include <sbi/sbi_ipi.h>
#include <sbi/sbi_platform.h> #include <sbi/sbi_platform.h>
#include <sbi/sbi_tlb.h> #include <sbi/sbi_tlb.h>
#include <sbi/sbi_trap.h>
#include <sbi/sbi_unpriv.h>
static unsigned long ipi_data_off; static unsigned long ipi_data_off;
@ -57,7 +58,8 @@ static int sbi_ipi_send(struct sbi_scratch *scratch, u32 hartid, u32 event,
return 0; return 0;
} }
int sbi_ipi_send_many(struct sbi_scratch *scratch, struct unpriv_trap *uptrap, int sbi_ipi_send_many(struct sbi_scratch *scratch,
struct sbi_trap_info *uptrap,
ulong *pmask, u32 event, void *data) ulong *pmask, u32 event, void *data)
{ {
ulong i, m; ulong i, m;
@ -65,7 +67,7 @@ int sbi_ipi_send_many(struct sbi_scratch *scratch, struct unpriv_trap *uptrap,
u32 hartid = sbi_current_hartid(); u32 hartid = sbi_current_hartid();
if (pmask) { if (pmask) {
mask &= load_ulong(pmask, scratch, uptrap); mask &= sbi_load_ulong(pmask, scratch, uptrap);
if (uptrap->cause) if (uptrap->cause)
return SBI_ETRAP; return SBI_ETRAP;
} }

View File

@ -9,11 +9,11 @@
#include <sbi/riscv_asm.h> #include <sbi/riscv_asm.h>
#include <sbi/riscv_encoding.h> #include <sbi/riscv_encoding.h>
#include <sbi/riscv_unpriv.h>
#include <sbi/riscv_fp.h> #include <sbi/riscv_fp.h>
#include <sbi/sbi_error.h> #include <sbi/sbi_error.h>
#include <sbi/sbi_misaligned_ldst.h> #include <sbi/sbi_misaligned_ldst.h>
#include <sbi/sbi_trap.h> #include <sbi/sbi_trap.h>
#include <sbi/sbi_unpriv.h>
union reg_data { union reg_data {
u8 data_bytes[8]; u8 data_bytes[8];
@ -26,14 +26,15 @@ int sbi_misaligned_load_handler(u32 hartid, ulong mcause,
struct sbi_scratch *scratch) struct sbi_scratch *scratch)
{ {
union reg_data val; union reg_data val;
struct unpriv_trap uptrap; struct sbi_trap_info uptrap;
ulong addr = csr_read(CSR_MTVAL); ulong addr = csr_read(CSR_MTVAL);
int i, fp = 0, shift = 0, len = 0; int i, fp = 0, shift = 0, len = 0;
ulong insn = get_insn(regs->mepc, scratch, &uptrap); ulong insn = sbi_get_insn(regs->mepc, scratch, &uptrap);
if (uptrap.cause) if (uptrap.cause) {
return sbi_trap_redirect(regs, scratch, regs->mepc, uptrap.epc = regs->mepc;
uptrap.cause, uptrap.tval); return sbi_trap_redirect(regs, &uptrap, scratch);
}
if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) { if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
len = 4; len = 4;
@ -96,17 +97,21 @@ int sbi_misaligned_load_handler(u32 hartid, ulong mcause,
#endif #endif
#endif #endif
#endif #endif
} else } else {
return sbi_trap_redirect(regs, scratch, regs->mepc, uptrap.epc = regs->mepc;
mcause, addr); uptrap.cause = mcause;
uptrap.tval = addr;
return sbi_trap_redirect(regs, &uptrap, scratch);
}
val.data_u64 = 0; val.data_u64 = 0;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
val.data_bytes[i] = load_u8((void *)(addr + i), val.data_bytes[i] = sbi_load_u8((void *)(addr + i),
scratch, &uptrap); scratch, &uptrap);
if (uptrap.cause) if (uptrap.cause) {
return sbi_trap_redirect(regs, scratch, regs->mepc, uptrap.epc = regs->mepc;
uptrap.cause, uptrap.tval); return sbi_trap_redirect(regs, &uptrap, scratch);
}
} }
if (!fp) if (!fp)
@ -128,14 +133,15 @@ int sbi_misaligned_store_handler(u32 hartid, ulong mcause,
struct sbi_scratch *scratch) struct sbi_scratch *scratch)
{ {
union reg_data val; union reg_data val;
struct unpriv_trap uptrap; struct sbi_trap_info uptrap;
ulong addr = csr_read(CSR_MTVAL); ulong addr = csr_read(CSR_MTVAL);
int i, len = 0; int i, len = 0;
ulong insn = get_insn(regs->mepc, scratch, &uptrap); ulong insn = sbi_get_insn(regs->mepc, scratch, &uptrap);
if (uptrap.cause) if (uptrap.cause) {
return sbi_trap_redirect(regs, scratch, regs->mepc, uptrap.epc = regs->mepc;
uptrap.cause, uptrap.tval); return sbi_trap_redirect(regs, &uptrap, scratch);
}
val.data_ulong = GET_RS2(insn, regs); val.data_ulong = GET_RS2(insn, regs);
@ -189,16 +195,20 @@ int sbi_misaligned_store_handler(u32 hartid, ulong mcause,
#endif #endif
#endif #endif
#endif #endif
} else } else {
return sbi_trap_redirect(regs, scratch, regs->mepc, uptrap.epc = regs->mepc;
mcause, addr); uptrap.cause = mcause;
uptrap.tval = addr;
return sbi_trap_redirect(regs, &uptrap, scratch);
}
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
store_u8((void *)(addr + i), val.data_bytes[i], sbi_store_u8((void *)(addr + i), val.data_bytes[i],
scratch, &uptrap); scratch, &uptrap);
if (uptrap.cause) if (uptrap.cause) {
return sbi_trap_redirect(regs, scratch, regs->mepc, uptrap.epc = regs->mepc;
uptrap.cause, uptrap.tval); return sbi_trap_redirect(regs, &uptrap, scratch);
}
} }
regs->mepc += INSN_LEN(insn); regs->mepc += INSN_LEN(insn);

View File

@ -9,7 +9,6 @@
#include <sbi/riscv_asm.h> #include <sbi/riscv_asm.h>
#include <sbi/riscv_encoding.h> #include <sbi/riscv_encoding.h>
#include <sbi/riscv_unpriv.h>
#include <sbi/sbi_console.h> #include <sbi/sbi_console.h>
#include <sbi/sbi_ecall.h> #include <sbi/sbi_ecall.h>
#include <sbi/sbi_error.h> #include <sbi/sbi_error.h>
@ -69,15 +68,14 @@ static void __noreturn sbi_trap_error(const char *msg, int rc, u32 hartid,
* Redirect trap to lower privledge mode (S-mode or U-mode) * Redirect trap to lower privledge mode (S-mode or U-mode)
* *
* @param regs pointer to register state * @param regs pointer to register state
* @param trap pointer to trap details
* @param scratch pointer to sbi_scratch of current HART * @param scratch pointer to sbi_scratch of current HART
* @param epc error PC for lower privledge mode
* @param cause exception cause for lower privledge mode
* @param tval trap value for lower privledge mode
* *
* @return 0 on success and negative error code on failure * @return 0 on success and negative error code on failure
*/ */
int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch, int sbi_trap_redirect(struct sbi_trap_regs *regs,
ulong epc, ulong cause, ulong tval) struct sbi_trap_info *trap,
struct sbi_scratch *scratch)
{ {
ulong hstatus, vsstatus, prev_mode; ulong hstatus, vsstatus, prev_mode;
#if __riscv_xlen == 32 #if __riscv_xlen == 32
@ -97,7 +95,7 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch,
/* For certain exceptions from VS/VU-mode we redirect to VS-mode */ /* For certain exceptions from VS/VU-mode we redirect to VS-mode */
if (misa_extension('H') && prev_virt && !prev_stage2) { if (misa_extension('H') && prev_virt && !prev_stage2) {
switch (cause) { switch (trap->cause) {
case CAUSE_FETCH_PAGE_FAULT: case CAUSE_FETCH_PAGE_FAULT:
case CAUSE_LOAD_PAGE_FAULT: case CAUSE_LOAD_PAGE_FAULT:
case CAUSE_STORE_PAGE_FAULT: case CAUSE_STORE_PAGE_FAULT:
@ -137,9 +135,9 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch,
/* Update exception related CSRs */ /* Update exception related CSRs */
if (next_virt) { if (next_virt) {
/* Update VS-mode exception info */ /* Update VS-mode exception info */
csr_write(CSR_VSTVAL, tval); csr_write(CSR_VSTVAL, trap->tval);
csr_write(CSR_VSEPC, epc); csr_write(CSR_VSEPC, trap->epc);
csr_write(CSR_VSCAUSE, cause); csr_write(CSR_VSCAUSE, trap->cause);
/* Set MEPC to VS-mode exception vector base */ /* Set MEPC to VS-mode exception vector base */
regs->mepc = csr_read(CSR_VSTVEC); regs->mepc = csr_read(CSR_VSTVEC);
@ -168,9 +166,9 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch,
csr_write(CSR_VSSTATUS, vsstatus); csr_write(CSR_VSSTATUS, vsstatus);
} else { } else {
/* Update S-mode exception info */ /* Update S-mode exception info */
csr_write(CSR_STVAL, tval); csr_write(CSR_STVAL, trap->tval);
csr_write(CSR_SEPC, epc); csr_write(CSR_SEPC, trap->epc);
csr_write(CSR_SCAUSE, cause); csr_write(CSR_SCAUSE, trap->cause);
/* Set MEPC to S-mode exception vector base */ /* Set MEPC to S-mode exception vector base */
regs->mepc = csr_read(CSR_STVEC); regs->mepc = csr_read(CSR_STVEC);
@ -211,14 +209,15 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch,
* @param regs pointer to register state * @param regs pointer to register state
* @param scratch pointer to sbi_scratch of current HART * @param scratch pointer to sbi_scratch of current HART
*/ */
void sbi_trap_handler(struct sbi_trap_regs *regs, struct sbi_scratch *scratch) void sbi_trap_handler(struct sbi_trap_regs *regs,
struct sbi_scratch *scratch)
{ {
int rc = SBI_ENOTSUPP; int rc = SBI_ENOTSUPP;
const char *msg = "trap handler failed"; const char *msg = "trap handler failed";
u32 hartid = sbi_current_hartid(); u32 hartid = sbi_current_hartid();
ulong mcause = csr_read(CSR_MCAUSE); ulong mcause = csr_read(CSR_MCAUSE);
ulong mtval = csr_read(CSR_MTVAL); ulong mtval = csr_read(CSR_MTVAL);
struct unpriv_trap *uptrap; struct sbi_trap_info trap, *uptrap;
if (mcause & (1UL << (__riscv_xlen - 1))) { if (mcause & (1UL << (__riscv_xlen - 1))) {
mcause &= ~(1UL << (__riscv_xlen - 1)); mcause &= ~(1UL << (__riscv_xlen - 1));
@ -262,19 +261,24 @@ void sbi_trap_handler(struct sbi_trap_regs *regs, struct sbi_scratch *scratch)
uptrap = sbi_hart_get_trap_info(scratch); uptrap = sbi_hart_get_trap_info(scratch);
if ((regs->mstatus & MSTATUS_MPRV) && uptrap) { if ((regs->mstatus & MSTATUS_MPRV) && uptrap) {
rc = 0; rc = 0;
uptrap->epc = regs->mepc;
regs->mepc += 4; regs->mepc += 4;
uptrap->cause = mcause; uptrap->cause = mcause;
uptrap->tval = mtval; uptrap->tval = mtval;
} else { } else {
rc = sbi_trap_redirect(regs, scratch, regs->mepc, trap.epc = regs->mepc;
mcause, mtval); trap.cause = mcause;
trap.tval = mtval;
rc = sbi_trap_redirect(regs, &trap, scratch);
} }
msg = "page/access fault handler failed"; msg = "page/access fault handler failed";
break; break;
default: default:
/* If the trap came from S or U mode, redirect it there */ /* If the trap came from S or U mode, redirect it there */
rc = sbi_trap_redirect(regs, scratch, regs->mepc, trap.epc = regs->mepc;
mcause, mtval); trap.cause = mcause;
trap.tval = mtval;
rc = sbi_trap_redirect(regs, &trap, scratch);
break; break;
}; };

View File

@ -8,18 +8,20 @@
*/ */
#include <sbi/riscv_encoding.h> #include <sbi/riscv_encoding.h>
#include <sbi/riscv_unpriv.h>
#include <sbi/sbi_bits.h> #include <sbi/sbi_bits.h>
#include <sbi/sbi_hart.h> #include <sbi/sbi_hart.h>
#include <sbi/sbi_scratch.h> #include <sbi/sbi_scratch.h>
#include <sbi/sbi_trap.h>
#include <sbi/sbi_unpriv.h>
#define DEFINE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \ #define DEFINE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \
type load_##type(const type *addr, \ type sbi_load_##type(const type *addr, \
struct sbi_scratch *scratch, \ struct sbi_scratch *scratch, \
struct unpriv_trap *trap) \ struct sbi_trap_info *trap) \
{ \ { \
register ulong __mstatus asm("a2"); \ register ulong __mstatus asm("a2"); \
type val = 0; \ type val = 0; \
trap->epc = 0; \
trap->cause = 0; \ trap->cause = 0; \
trap->tval = 0; \ trap->tval = 0; \
sbi_hart_set_trap_info(scratch, trap); \ sbi_hart_set_trap_info(scratch, trap); \
@ -37,11 +39,12 @@
} }
#define DEFINE_UNPRIVILEGED_STORE_FUNCTION(type, insn) \ #define DEFINE_UNPRIVILEGED_STORE_FUNCTION(type, insn) \
void store_##type(type *addr, type val, \ void sbi_store_##type(type *addr, type val, \
struct sbi_scratch *scratch, \ struct sbi_scratch *scratch, \
struct unpriv_trap *trap) \ struct sbi_trap_info *trap) \
{ \ { \
register ulong __mstatus asm("a3"); \ register ulong __mstatus asm("a3"); \
trap->epc = 0; \
trap->cause = 0; \ trap->cause = 0; \
trap->tval = 0; \ trap->tval = 0; \
sbi_hart_set_trap_info(scratch, trap); \ sbi_hart_set_trap_info(scratch, trap); \
@ -74,41 +77,44 @@ DEFINE_UNPRIVILEGED_LOAD_FUNCTION(ulong, ld)
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(u32, lw) DEFINE_UNPRIVILEGED_LOAD_FUNCTION(u32, lw)
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(ulong, lw) DEFINE_UNPRIVILEGED_LOAD_FUNCTION(ulong, lw)
u64 load_u64(const u64 *addr, u64 sbi_load_u64(const u64 *addr,
struct sbi_scratch *scratch, struct unpriv_trap *trap) struct sbi_scratch *scratch,
struct sbi_trap_info *trap)
{ {
u64 ret = load_u32((u32 *)addr, scratch, trap); u64 ret = sbi_load_u32((u32 *)addr, scratch, trap);
if (trap->cause) if (trap->cause)
return 0; return 0;
ret |= ((u64)load_u32((u32 *)addr + 1, scratch, trap) << 32); ret |= ((u64)sbi_load_u32((u32 *)addr + 1, scratch, trap) << 32);
if (trap->cause) if (trap->cause)
return 0; return 0;
return ret; return ret;
} }
void store_u64(u64 *addr, u64 val, void sbi_store_u64(u64 *addr, u64 val,
struct sbi_scratch *scratch, struct unpriv_trap *trap) struct sbi_scratch *scratch,
struct sbi_trap_info *trap)
{ {
store_u32((u32 *)addr, val, scratch, trap); sbi_store_u32((u32 *)addr, val, scratch, trap);
if (trap->cause) if (trap->cause)
return; return;
store_u32((u32 *)addr + 1, val >> 32, scratch, trap); sbi_store_u32((u32 *)addr + 1, val >> 32, scratch, trap);
if (trap->cause) if (trap->cause)
return; return;
} }
#endif #endif
ulong get_insn(ulong mepc, struct sbi_scratch *scratch, ulong sbi_get_insn(ulong mepc, struct sbi_scratch *scratch,
struct unpriv_trap *trap) struct sbi_trap_info *trap)
{ {
ulong __mstatus = 0, val = 0; ulong __mstatus = 0, val = 0;
#ifdef __riscv_compressed #ifdef __riscv_compressed
ulong rvc_mask = 3, tmp; ulong rvc_mask = 3, tmp;
#endif #endif
trap->epc = 0;
trap->cause = 0; trap->cause = 0;
trap->tval = 0; trap->tval = 0;
sbi_hart_set_trap_info(scratch, trap); sbi_hart_set_trap_info(scratch, trap);
@ -147,6 +153,7 @@ ulong get_insn(ulong mepc, struct sbi_scratch *scratch,
#endif #endif
sbi_hart_set_trap_info(scratch, NULL); sbi_hart_set_trap_info(scratch, NULL);
switch (trap->cause) { switch (trap->cause) {
case CAUSE_LOAD_ACCESS: case CAUSE_LOAD_ACCESS:
trap->cause = CAUSE_FETCH_ACCESS; trap->cause = CAUSE_FETCH_ACCESS;