forked from Mirrors/opensbi
		
	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:
		@@ -10,7 +10,6 @@
 | 
			
		||||
#ifndef __SBI_IPI_H__
 | 
			
		||||
#define __SBI_IPI_H__
 | 
			
		||||
 | 
			
		||||
#include <sbi/riscv_unpriv.h>
 | 
			
		||||
#include <sbi/sbi_types.h>
 | 
			
		||||
 | 
			
		||||
/* clang-format off */
 | 
			
		||||
@@ -24,12 +23,14 @@
 | 
			
		||||
/* clang-format on */
 | 
			
		||||
 | 
			
		||||
struct sbi_scratch;
 | 
			
		||||
struct sbi_trap_info;
 | 
			
		||||
 | 
			
		||||
struct sbi_ipi_data {
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
void sbi_ipi_clear_smode(struct sbi_scratch *scratch);
 | 
			
		||||
 
 | 
			
		||||
@@ -170,12 +170,24 @@ struct sbi_trap_regs {
 | 
			
		||||
	unsigned long mstatusH;
 | 
			
		||||
} __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;
 | 
			
		||||
 | 
			
		||||
int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch,
 | 
			
		||||
		      ulong epc, ulong cause, ulong tval);
 | 
			
		||||
int sbi_trap_redirect(struct sbi_trap_regs *regs,
 | 
			
		||||
		      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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,27 +7,23 @@
 | 
			
		||||
 *   Anup Patel <anup.patel@wdc.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __RISCV_UNPRIV_H__
 | 
			
		||||
#define __RISCV_UNPRIV_H__
 | 
			
		||||
#ifndef __SBI_UNPRIV_H__
 | 
			
		||||
#define __SBI_UNPRIV_H__
 | 
			
		||||
 | 
			
		||||
#include <sbi/sbi_types.h>
 | 
			
		||||
 | 
			
		||||
struct sbi_scratch;
 | 
			
		||||
struct sbi_trap_info;
 | 
			
		||||
 | 
			
		||||
struct unpriv_trap {
 | 
			
		||||
	unsigned long cause;
 | 
			
		||||
	unsigned long tval;
 | 
			
		||||
};
 | 
			
		||||
#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type)           \
 | 
			
		||||
	type sbi_load_##type(const type *addr,             \
 | 
			
		||||
			     struct sbi_scratch *scratch,  \
 | 
			
		||||
			     struct sbi_trap_info *trap);
 | 
			
		||||
 | 
			
		||||
#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type)       \
 | 
			
		||||
	type load_##type(const type *addr,             \
 | 
			
		||||
			 struct sbi_scratch *scratch,  \
 | 
			
		||||
			 struct unpriv_trap *trap);
 | 
			
		||||
 | 
			
		||||
#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type)      \
 | 
			
		||||
	void store_##type(type *addr, type val,        \
 | 
			
		||||
			  struct sbi_scratch *scratch, \
 | 
			
		||||
			  struct unpriv_trap *trap);
 | 
			
		||||
#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type)          \
 | 
			
		||||
	void sbi_store_##type(type *addr, type val,        \
 | 
			
		||||
			      struct sbi_scratch *scratch, \
 | 
			
		||||
			      struct sbi_trap_info *trap);
 | 
			
		||||
 | 
			
		||||
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8)
 | 
			
		||||
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16)
 | 
			
		||||
@@ -42,7 +38,7 @@ DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u64)
 | 
			
		||||
DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64)
 | 
			
		||||
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong)
 | 
			
		||||
 | 
			
		||||
ulong get_insn(ulong mepc, struct sbi_scratch *scratch,
 | 
			
		||||
	       struct unpriv_trap *trap);
 | 
			
		||||
ulong sbi_get_insn(ulong mepc, struct sbi_scratch *scratch,
 | 
			
		||||
		   struct sbi_trap_info *trap);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -11,7 +11,6 @@ libsbi-objs-y += riscv_asm.o
 | 
			
		||||
libsbi-objs-y += riscv_atomic.o
 | 
			
		||||
libsbi-objs-y += riscv_hardfp.o
 | 
			
		||||
libsbi-objs-y += riscv_locks.o
 | 
			
		||||
libsbi-objs-y += riscv_unpriv.o
 | 
			
		||||
 | 
			
		||||
libsbi-objs-y += sbi_console.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_trap.o
 | 
			
		||||
libsbi-objs-y += sbi_string.o
 | 
			
		||||
libsbi-objs-y += sbi_unpriv.o
 | 
			
		||||
 
 | 
			
		||||
@@ -118,7 +118,7 @@ int sbi_ecall_0_1_handler(struct sbi_scratch *scratch, unsigned long extid,
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	struct sbi_tlb_info tlb_info;
 | 
			
		||||
	u32 source_hart = sbi_current_hartid();
 | 
			
		||||
	struct unpriv_trap uptrap = {0};
 | 
			
		||||
	struct sbi_trap_info uptrap = {0};
 | 
			
		||||
 | 
			
		||||
	switch (extid) {
 | 
			
		||||
	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;
 | 
			
		||||
	unsigned long extension_id = regs->a7;
 | 
			
		||||
	unsigned long func_id = regs->a6;
 | 
			
		||||
	struct sbi_trap_info trap = {0};
 | 
			
		||||
	unsigned long out_val;
 | 
			
		||||
	unsigned long out_tval;
 | 
			
		||||
	unsigned long out_tcause;
 | 
			
		||||
	bool is_0_1_spec = 0;
 | 
			
		||||
	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 &&
 | 
			
		||||
	    extension_id <= SBI_EXT_0_1_SHUTDOWN) {
 | 
			
		||||
		ret = sbi_ecall_0_1_handler(scratch, extension_id, args,
 | 
			
		||||
					    &out_tval, &out_tcause);
 | 
			
		||||
					    &trap.tval, &trap.cause);
 | 
			
		||||
		is_0_1_spec = 1;
 | 
			
		||||
	} else if (extension_id == SBI_EXT_BASE)
 | 
			
		||||
		ret = sbi_ecall_base_handler(scratch, extension_id, func_id,
 | 
			
		||||
					     args, &out_val,
 | 
			
		||||
					     &out_tval, &out_tcause);
 | 
			
		||||
					     &trap.tval, &trap.cause);
 | 
			
		||||
	else if (extension_id >= SBI_EXT_VENDOR_START &&
 | 
			
		||||
		extension_id <= SBI_EXT_VENDOR_END) {
 | 
			
		||||
		ret = sbi_ecall_vendor_ext_handler(scratch, extension_id,
 | 
			
		||||
						   func_id, args, &out_val,
 | 
			
		||||
						   &out_tval, &out_tcause);
 | 
			
		||||
						   &trap.tval, &trap.cause);
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = SBI_ENOTSUPP;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ret == SBI_ETRAP) {
 | 
			
		||||
		sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
				  out_tcause, out_tval);
 | 
			
		||||
		trap.epc = regs->mepc;
 | 
			
		||||
		sbi_trap_redirect(regs, &trap, scratch);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* This function should return non-zero value only in case of
 | 
			
		||||
		 * fatal error. However, there is no good way to distinguish
 | 
			
		||||
 
 | 
			
		||||
@@ -9,12 +9,12 @@
 | 
			
		||||
 | 
			
		||||
#include <sbi/riscv_asm.h>
 | 
			
		||||
#include <sbi/riscv_encoding.h>
 | 
			
		||||
#include <sbi/riscv_unpriv.h>
 | 
			
		||||
#include <sbi/sbi_bits.h>
 | 
			
		||||
#include <sbi/sbi_emulate_csr.h>
 | 
			
		||||
#include <sbi/sbi_error.h>
 | 
			
		||||
#include <sbi/sbi_illegal_insn.h>
 | 
			
		||||
#include <sbi/sbi_trap.h>
 | 
			
		||||
#include <sbi/sbi_unpriv.h>
 | 
			
		||||
 | 
			
		||||
typedef int (*illegal_insn_func)(ulong insn, u32 hartid, ulong mcause,
 | 
			
		||||
				 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_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,
 | 
			
		||||
@@ -46,8 +52,8 @@ static int system_opcode_insn(ulong insn, u32 hartid, ulong mcause,
 | 
			
		||||
	if ((regs->mstatus & MSTATUS_MPV) &&
 | 
			
		||||
#endif
 | 
			
		||||
	    (insn & INSN_MASK_WFI) == INSN_MATCH_WFI)
 | 
			
		||||
		return sbi_trap_redirect(regs, scratch,
 | 
			
		||||
					 regs->mepc, mcause, insn);
 | 
			
		||||
		return truly_illegal_insn(insn, hartid, mcause,
 | 
			
		||||
					  regs, scratch);
 | 
			
		||||
 | 
			
		||||
	if (sbi_emulate_csr_read(csr_num, hartid, regs, scratch, &csr_val))
 | 
			
		||||
		return truly_illegal_insn(insn, hartid, mcause,
 | 
			
		||||
@@ -130,14 +136,16 @@ int sbi_illegal_insn_handler(u32 hartid, ulong mcause,
 | 
			
		||||
			     struct sbi_scratch *scratch)
 | 
			
		||||
{
 | 
			
		||||
	ulong insn = csr_read(CSR_MTVAL);
 | 
			
		||||
	struct unpriv_trap uptrap;
 | 
			
		||||
	struct sbi_trap_info uptrap;
 | 
			
		||||
 | 
			
		||||
	if (unlikely((insn & 3) != 3)) {
 | 
			
		||||
		if (insn == 0) {
 | 
			
		||||
			insn = get_insn(regs->mepc, scratch, &uptrap);
 | 
			
		||||
			if (uptrap.cause)
 | 
			
		||||
				return sbi_trap_redirect(regs, scratch,
 | 
			
		||||
					regs->mepc, uptrap.cause, uptrap.tval);
 | 
			
		||||
			insn = sbi_get_insn(regs->mepc, scratch, &uptrap);
 | 
			
		||||
			if (uptrap.cause) {
 | 
			
		||||
				uptrap.epc = regs->mepc;
 | 
			
		||||
				return sbi_trap_redirect(regs, &uptrap,
 | 
			
		||||
							 scratch);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if ((insn & 3) != 3)
 | 
			
		||||
			return truly_illegal_insn(insn, hartid, mcause, regs,
 | 
			
		||||
 
 | 
			
		||||
@@ -11,12 +11,13 @@
 | 
			
		||||
#include <sbi/riscv_asm.h>
 | 
			
		||||
#include <sbi/riscv_atomic.h>
 | 
			
		||||
#include <sbi/riscv_barrier.h>
 | 
			
		||||
#include <sbi/riscv_unpriv.h>
 | 
			
		||||
#include <sbi/sbi_error.h>
 | 
			
		||||
#include <sbi/sbi_hart.h>
 | 
			
		||||
#include <sbi/sbi_ipi.h>
 | 
			
		||||
#include <sbi/sbi_platform.h>
 | 
			
		||||
#include <sbi/sbi_tlb.h>
 | 
			
		||||
#include <sbi/sbi_trap.h>
 | 
			
		||||
#include <sbi/sbi_unpriv.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 i, m;
 | 
			
		||||
@@ -65,7 +67,7 @@ int sbi_ipi_send_many(struct sbi_scratch *scratch, struct unpriv_trap *uptrap,
 | 
			
		||||
	u32 hartid = sbi_current_hartid();
 | 
			
		||||
 | 
			
		||||
	if (pmask) {
 | 
			
		||||
		mask &= load_ulong(pmask, scratch, uptrap);
 | 
			
		||||
		mask &= sbi_load_ulong(pmask, scratch, uptrap);
 | 
			
		||||
		if (uptrap->cause)
 | 
			
		||||
			return SBI_ETRAP;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,11 +9,11 @@
 | 
			
		||||
 | 
			
		||||
#include <sbi/riscv_asm.h>
 | 
			
		||||
#include <sbi/riscv_encoding.h>
 | 
			
		||||
#include <sbi/riscv_unpriv.h>
 | 
			
		||||
#include <sbi/riscv_fp.h>
 | 
			
		||||
#include <sbi/sbi_error.h>
 | 
			
		||||
#include <sbi/sbi_misaligned_ldst.h>
 | 
			
		||||
#include <sbi/sbi_trap.h>
 | 
			
		||||
#include <sbi/sbi_unpriv.h>
 | 
			
		||||
 | 
			
		||||
union reg_data {
 | 
			
		||||
	u8 data_bytes[8];
 | 
			
		||||
@@ -26,14 +26,15 @@ int sbi_misaligned_load_handler(u32 hartid, ulong mcause,
 | 
			
		||||
				struct sbi_scratch *scratch)
 | 
			
		||||
{
 | 
			
		||||
	union reg_data val;
 | 
			
		||||
	struct unpriv_trap uptrap;
 | 
			
		||||
	struct sbi_trap_info uptrap;
 | 
			
		||||
	ulong addr = csr_read(CSR_MTVAL);
 | 
			
		||||
	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)
 | 
			
		||||
		return sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
					 uptrap.cause, uptrap.tval);
 | 
			
		||||
	if (uptrap.cause) {
 | 
			
		||||
		uptrap.epc = regs->mepc;
 | 
			
		||||
		return sbi_trap_redirect(regs, &uptrap, scratch);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
 | 
			
		||||
		len   = 4;
 | 
			
		||||
@@ -96,17 +97,21 @@ int sbi_misaligned_load_handler(u32 hartid, ulong mcause,
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
	} else
 | 
			
		||||
		return sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
					 mcause, addr);
 | 
			
		||||
	} else {
 | 
			
		||||
		uptrap.epc = regs->mepc;
 | 
			
		||||
		uptrap.cause = mcause;
 | 
			
		||||
		uptrap.tval = addr;
 | 
			
		||||
		return sbi_trap_redirect(regs, &uptrap, scratch);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	val.data_u64 = 0;
 | 
			
		||||
	for (i = 0; i < len; i++) {
 | 
			
		||||
		val.data_bytes[i] = load_u8((void *)(addr + i),
 | 
			
		||||
					    scratch, &uptrap);
 | 
			
		||||
		if (uptrap.cause)
 | 
			
		||||
			return sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
						 uptrap.cause, uptrap.tval);
 | 
			
		||||
		val.data_bytes[i] = sbi_load_u8((void *)(addr + i),
 | 
			
		||||
						scratch, &uptrap);
 | 
			
		||||
		if (uptrap.cause) {
 | 
			
		||||
			uptrap.epc = regs->mepc;
 | 
			
		||||
			return sbi_trap_redirect(regs, &uptrap, scratch);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!fp)
 | 
			
		||||
@@ -128,14 +133,15 @@ int sbi_misaligned_store_handler(u32 hartid, ulong mcause,
 | 
			
		||||
				 struct sbi_scratch *scratch)
 | 
			
		||||
{
 | 
			
		||||
	union reg_data val;
 | 
			
		||||
	struct unpriv_trap uptrap;
 | 
			
		||||
	struct sbi_trap_info uptrap;
 | 
			
		||||
	ulong addr = csr_read(CSR_MTVAL);
 | 
			
		||||
	int i, len = 0;
 | 
			
		||||
	ulong insn = get_insn(regs->mepc, scratch, &uptrap);
 | 
			
		||||
	ulong insn = sbi_get_insn(regs->mepc, scratch, &uptrap);
 | 
			
		||||
 | 
			
		||||
	if (uptrap.cause)
 | 
			
		||||
		return sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
					 uptrap.cause, uptrap.tval);
 | 
			
		||||
	if (uptrap.cause) {
 | 
			
		||||
		uptrap.epc = regs->mepc;
 | 
			
		||||
		return sbi_trap_redirect(regs, &uptrap, scratch);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	val.data_ulong = GET_RS2(insn, regs);
 | 
			
		||||
 | 
			
		||||
@@ -189,16 +195,20 @@ int sbi_misaligned_store_handler(u32 hartid, ulong mcause,
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
	} else
 | 
			
		||||
		return sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
					 mcause, addr);
 | 
			
		||||
	} else {
 | 
			
		||||
		uptrap.epc = regs->mepc;
 | 
			
		||||
		uptrap.cause = mcause;
 | 
			
		||||
		uptrap.tval = addr;
 | 
			
		||||
		return sbi_trap_redirect(regs, &uptrap, scratch);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < len; i++) {
 | 
			
		||||
		store_u8((void *)(addr + i), val.data_bytes[i],
 | 
			
		||||
			 scratch, &uptrap);
 | 
			
		||||
		if (uptrap.cause)
 | 
			
		||||
			return sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
						 uptrap.cause, uptrap.tval);
 | 
			
		||||
		sbi_store_u8((void *)(addr + i), val.data_bytes[i],
 | 
			
		||||
			     scratch, &uptrap);
 | 
			
		||||
		if (uptrap.cause) {
 | 
			
		||||
			uptrap.epc = regs->mepc;
 | 
			
		||||
			return sbi_trap_redirect(regs, &uptrap, scratch);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	regs->mepc += INSN_LEN(insn);
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
 | 
			
		||||
#include <sbi/riscv_asm.h>
 | 
			
		||||
#include <sbi/riscv_encoding.h>
 | 
			
		||||
#include <sbi/riscv_unpriv.h>
 | 
			
		||||
#include <sbi/sbi_console.h>
 | 
			
		||||
#include <sbi/sbi_ecall.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)
 | 
			
		||||
 *
 | 
			
		||||
 * @param regs pointer to register state
 | 
			
		||||
 * @param trap pointer to trap details
 | 
			
		||||
 * @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
 | 
			
		||||
 */
 | 
			
		||||
int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch,
 | 
			
		||||
		      ulong epc, ulong cause, ulong tval)
 | 
			
		||||
int sbi_trap_redirect(struct sbi_trap_regs *regs,
 | 
			
		||||
		      struct sbi_trap_info *trap,
 | 
			
		||||
		      struct sbi_scratch *scratch)
 | 
			
		||||
{
 | 
			
		||||
	ulong hstatus, vsstatus, prev_mode;
 | 
			
		||||
#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 */
 | 
			
		||||
	if (misa_extension('H') && prev_virt && !prev_stage2) {
 | 
			
		||||
		switch (cause) {
 | 
			
		||||
		switch (trap->cause) {
 | 
			
		||||
		case CAUSE_FETCH_PAGE_FAULT:
 | 
			
		||||
		case CAUSE_LOAD_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 */
 | 
			
		||||
	if (next_virt) {
 | 
			
		||||
		/* Update VS-mode exception info */
 | 
			
		||||
		csr_write(CSR_VSTVAL, tval);
 | 
			
		||||
		csr_write(CSR_VSEPC, epc);
 | 
			
		||||
		csr_write(CSR_VSCAUSE, cause);
 | 
			
		||||
		csr_write(CSR_VSTVAL, trap->tval);
 | 
			
		||||
		csr_write(CSR_VSEPC, trap->epc);
 | 
			
		||||
		csr_write(CSR_VSCAUSE, trap->cause);
 | 
			
		||||
 | 
			
		||||
		/* Set MEPC to VS-mode exception vector base */
 | 
			
		||||
		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);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Update S-mode exception info */
 | 
			
		||||
		csr_write(CSR_STVAL, tval);
 | 
			
		||||
		csr_write(CSR_SEPC, epc);
 | 
			
		||||
		csr_write(CSR_SCAUSE, cause);
 | 
			
		||||
		csr_write(CSR_STVAL, trap->tval);
 | 
			
		||||
		csr_write(CSR_SEPC, trap->epc);
 | 
			
		||||
		csr_write(CSR_SCAUSE, trap->cause);
 | 
			
		||||
 | 
			
		||||
		/* Set MEPC to S-mode exception vector base */
 | 
			
		||||
		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 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;
 | 
			
		||||
	const char *msg = "trap handler failed";
 | 
			
		||||
	u32 hartid = sbi_current_hartid();
 | 
			
		||||
	ulong mcause = csr_read(CSR_MCAUSE);
 | 
			
		||||
	ulong mtval = csr_read(CSR_MTVAL);
 | 
			
		||||
	struct unpriv_trap *uptrap;
 | 
			
		||||
	struct sbi_trap_info trap, *uptrap;
 | 
			
		||||
 | 
			
		||||
	if (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);
 | 
			
		||||
		if ((regs->mstatus & MSTATUS_MPRV) && uptrap) {
 | 
			
		||||
			rc = 0;
 | 
			
		||||
			uptrap->epc = regs->mepc;
 | 
			
		||||
			regs->mepc += 4;
 | 
			
		||||
			uptrap->cause = mcause;
 | 
			
		||||
			uptrap->tval = mtval;
 | 
			
		||||
		} else {
 | 
			
		||||
			rc = sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
					       mcause, mtval);
 | 
			
		||||
			trap.epc = regs->mepc;
 | 
			
		||||
			trap.cause = mcause;
 | 
			
		||||
			trap.tval = mtval;
 | 
			
		||||
			rc = sbi_trap_redirect(regs, &trap, scratch);
 | 
			
		||||
		}
 | 
			
		||||
		msg = "page/access fault handler failed";
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		/* If the trap came from S or U mode, redirect it there */
 | 
			
		||||
		rc = sbi_trap_redirect(regs, scratch, regs->mepc,
 | 
			
		||||
				       mcause, mtval);
 | 
			
		||||
		trap.epc = regs->mepc;
 | 
			
		||||
		trap.cause = mcause;
 | 
			
		||||
		trap.tval = mtval;
 | 
			
		||||
		rc = sbi_trap_redirect(regs, &trap, scratch);
 | 
			
		||||
		break;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,18 +8,20 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sbi/riscv_encoding.h>
 | 
			
		||||
#include <sbi/riscv_unpriv.h>
 | 
			
		||||
#include <sbi/sbi_bits.h>
 | 
			
		||||
#include <sbi/sbi_hart.h>
 | 
			
		||||
#include <sbi/sbi_scratch.h>
 | 
			
		||||
#include <sbi/sbi_trap.h>
 | 
			
		||||
#include <sbi/sbi_unpriv.h>
 | 
			
		||||
 | 
			
		||||
#define DEFINE_UNPRIVILEGED_LOAD_FUNCTION(type, insn)                         \
 | 
			
		||||
	type load_##type(const type *addr,                                    \
 | 
			
		||||
			struct sbi_scratch *scratch,                          \
 | 
			
		||||
			struct unpriv_trap *trap)                             \
 | 
			
		||||
	type sbi_load_##type(const type *addr,                                \
 | 
			
		||||
			     struct sbi_scratch *scratch,                     \
 | 
			
		||||
			     struct sbi_trap_info *trap)                      \
 | 
			
		||||
	{                                                                     \
 | 
			
		||||
		register ulong __mstatus asm("a2");                           \
 | 
			
		||||
		type val = 0;                                                 \
 | 
			
		||||
		trap->epc = 0;                                                \
 | 
			
		||||
		trap->cause = 0;                                              \
 | 
			
		||||
		trap->tval = 0;                                               \
 | 
			
		||||
		sbi_hart_set_trap_info(scratch, trap);                        \
 | 
			
		||||
@@ -37,11 +39,12 @@
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#define DEFINE_UNPRIVILEGED_STORE_FUNCTION(type, insn)                        \
 | 
			
		||||
	void store_##type(type *addr, type val,                               \
 | 
			
		||||
			struct sbi_scratch *scratch,                          \
 | 
			
		||||
			struct unpriv_trap *trap)                             \
 | 
			
		||||
	void sbi_store_##type(type *addr, type val,                           \
 | 
			
		||||
			      struct sbi_scratch *scratch,                    \
 | 
			
		||||
			      struct sbi_trap_info *trap)                     \
 | 
			
		||||
	{                                                                     \
 | 
			
		||||
		register ulong __mstatus asm("a3");                           \
 | 
			
		||||
		trap->epc = 0;                                                \
 | 
			
		||||
		trap->cause = 0;                                              \
 | 
			
		||||
		trap->tval = 0;                                               \
 | 
			
		||||
		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(ulong, lw)
 | 
			
		||||
 | 
			
		||||
u64 load_u64(const u64 *addr,
 | 
			
		||||
	     struct sbi_scratch *scratch, struct unpriv_trap *trap)
 | 
			
		||||
u64 sbi_load_u64(const u64 *addr,
 | 
			
		||||
		 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)
 | 
			
		||||
		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)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void store_u64(u64 *addr, u64 val,
 | 
			
		||||
	       struct sbi_scratch *scratch, struct unpriv_trap *trap)
 | 
			
		||||
void sbi_store_u64(u64 *addr, u64 val,
 | 
			
		||||
		   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)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	store_u32((u32 *)addr + 1, val >> 32, scratch, trap);
 | 
			
		||||
	sbi_store_u32((u32 *)addr + 1, val >> 32, scratch, trap);
 | 
			
		||||
	if (trap->cause)
 | 
			
		||||
		return;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ulong get_insn(ulong mepc, struct sbi_scratch *scratch,
 | 
			
		||||
	       struct unpriv_trap *trap)
 | 
			
		||||
ulong sbi_get_insn(ulong mepc, struct sbi_scratch *scratch,
 | 
			
		||||
		   struct sbi_trap_info *trap)
 | 
			
		||||
{
 | 
			
		||||
	ulong __mstatus = 0, val = 0;
 | 
			
		||||
#ifdef __riscv_compressed
 | 
			
		||||
	ulong rvc_mask = 3, tmp;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	trap->epc = 0;
 | 
			
		||||
	trap->cause = 0;
 | 
			
		||||
	trap->tval = 0;
 | 
			
		||||
	sbi_hart_set_trap_info(scratch, trap);
 | 
			
		||||
@@ -147,6 +153,7 @@ ulong get_insn(ulong mepc, struct sbi_scratch *scratch,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	sbi_hart_set_trap_info(scratch, NULL);
 | 
			
		||||
 | 
			
		||||
	switch (trap->cause) {
 | 
			
		||||
	case CAUSE_LOAD_ACCESS:
 | 
			
		||||
		trap->cause = CAUSE_FETCH_ACCESS;
 | 
			
		||||
		Reference in New Issue
	
	Block a user