[PATCH 3/9] lib: sbi: Introduce trap context
Anup Patel
apatel at ventanamicro.com
Mon Mar 11 09:09:38 PDT 2024
Club pointers to struct sbi_trap_regs and struct sbi_trap_info a new
struct sbi_trap_context (aka trap context).
To track nested traps, the struct sbi_scratch points to the current
trap context and the trap context has pointer to pervious context of
previous trap.
Signed-off-by: Anup Patel <apatel at ventanamicro.com>
---
include/sbi/sbi_trap.h | 22 ++++++++++++++++++++++
lib/sbi/sbi_trap.c | 35 ++++++++++++++++++++++-------------
2 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
index 15ccd0b..513a82e 100644
--- a/include/sbi/sbi_trap.h
+++ b/include/sbi/sbi_trap.h
@@ -117,6 +117,7 @@
#ifndef __ASSEMBLER__
#include <sbi/sbi_types.h>
+#include <sbi/sbi_scratch.h>
/** Representation of register state at time of trap/interrupt */
struct sbi_trap_regs {
@@ -208,6 +209,16 @@ struct sbi_trap_info {
unsigned long gva;
};
+/** Representation of trap context saved on stack */
+struct sbi_trap_context {
+ /** Pointer to previous trap context */
+ struct sbi_trap_context *prev_context;
+ /** Pointer to register state */
+ struct sbi_trap_regs *regs;
+ /** Pointer to trap details */
+ const struct sbi_trap_info *trap;
+};
+
static inline unsigned long sbi_regs_gva(const struct sbi_trap_regs *regs)
{
/*
@@ -227,6 +238,17 @@ static inline unsigned long sbi_regs_gva(const struct sbi_trap_regs *regs)
int sbi_trap_redirect(struct sbi_trap_regs *regs,
const struct sbi_trap_info *trap);
+static inline struct sbi_trap_context *sbi_trap_get_context(struct sbi_scratch *scratch)
+{
+ return (scratch) ? (void *)scratch->trap_context : NULL;
+}
+
+static inline void sbi_trap_set_context(struct sbi_scratch *scratch,
+ struct sbi_trap_context *tcntx)
+{
+ scratch->trap_context = (unsigned long)tcntx;
+}
+
struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs);
#endif
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index e514066..dba267c 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -266,6 +266,8 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
const char *msg = "trap handler failed";
ulong mcause = csr_read(CSR_MCAUSE);
ulong mtval = csr_read(CSR_MTVAL), mtval2 = 0, mtinst = 0;
+ struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+ struct sbi_trap_context tcntx;
struct sbi_trap_info trap;
if (misa_extension('H')) {
@@ -273,25 +275,31 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
mtinst = csr_read(CSR_MTINST);
}
+ /* Original trap_info */
+ trap.epc = regs->mepc;
+ trap.cause = mcause;
+ trap.tval = mtval;
+ trap.tval2 = mtval2;
+ trap.tinst = mtinst;
+ trap.gva = sbi_regs_gva(regs);
+
+ /* Setup trap context */
+ tcntx.prev_context = sbi_trap_get_context(scratch);
+ tcntx.regs = regs;
+ tcntx.trap = &trap;
+
+ /* Update trap context pointer */
+ sbi_trap_set_context(scratch, &tcntx);
+
if (mcause & (1UL << (__riscv_xlen - 1))) {
if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
SBI_HART_EXT_SMAIA))
rc = sbi_trap_aia_irq(regs, mcause);
else
rc = sbi_trap_nonaia_irq(regs, mcause);
- if (rc) {
- msg = "unhandled local interrupt";
- goto trap_error;
- }
- return regs;
+ msg = "unhandled local interrupt";
+ goto trap_done;
}
- /* Original trap_info */
- trap.epc = regs->mepc;
- trap.cause = mcause;
- trap.tval = mtval;
- trap.tval2 = mtval2;
- trap.tinst = mtinst;
- trap.gva = sbi_regs_gva(regs);
switch (mcause) {
case CAUSE_ILLEGAL_INSTRUCTION:
@@ -330,8 +338,9 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
break;
}
-trap_error:
+trap_done:
if (rc)
sbi_trap_error(msg, rc, mcause, mtval, mtval2, mtinst, regs);
+ sbi_trap_set_context(scratch, tcntx.prev_context);
return regs;
}
--
2.34.1
More information about the opensbi
mailing list