summaryrefslogtreecommitdiff
path: root/lib/sbi_trap.c
diff options
context:
space:
mode:
authorAnup Patel <[email protected]>2018-12-11 19:24:06 +0530
committerAnup Patel <[email protected]>2018-12-11 19:24:06 +0530
commit9e8ff05cb61f157fb0bcb6b0071d7b6dc0763faa (patch)
treeb9513a86b3b36e569cb46387846fee9c5544f566 /lib/sbi_trap.c
Initial commit.
Signed-off-by: Anup Patel <[email protected]>
Diffstat (limited to 'lib/sbi_trap.c')
-rw-r--r--lib/sbi_trap.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/sbi_trap.c b/lib/sbi_trap.c
new file mode 100644
index 00000000..f9c70a63
--- /dev/null
+++ b/lib/sbi_trap.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ * Anup Patel <[email protected]>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_illegal_insn.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_ipi.h>
+#include <sbi/sbi_timer.h>
+#include <sbi/sbi_trap.h>
+
+static void __attribute__((noreturn)) sbi_trap_error(const char *msg,
+ int rc, u32 hartid,
+ ulong mcause,
+ struct sbi_trap_regs *regs)
+{
+ sbi_printf("%s: hart%d: %s (error %d)\n",
+ __func__, hartid, msg, rc);
+ sbi_printf("%s: hart%d: mcause=0x%lx mepc=0x%lx mstatus=0x%lx\n",
+ __func__, hartid, mcause, regs->mepc, regs->mstatus);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "ra", regs->ra, "sp", regs->sp);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "gp", regs->gp, "tp", regs->tp);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "s0", regs->s0, "s1", regs->s1);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "a0", regs->a0, "a1", regs->a1);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "a2", regs->a2, "a3", regs->a3);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "a4", regs->a4, "a5", regs->a5);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "a6", regs->a6, "a7", regs->a7);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "s2", regs->s2, "s3", regs->s3);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "s4", regs->s4, "s5", regs->s5);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "s6", regs->s6, "s7", regs->s7);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "s8", regs->s8, "s9", regs->s9);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "s10", regs->s10, "s11", regs->s11);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "t0", regs->t0, "t1", regs->t1);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "t2", regs->t2, "t3", regs->t3);
+ sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
+ __func__, hartid, "t4", regs->t4, "t5", regs->t5);
+ sbi_printf("%s: hart%d: %s=0x%lx\n",
+ __func__, hartid, "t6", regs->t6);
+
+ sbi_hart_hang();
+}
+
+void sbi_trap_handler(struct sbi_trap_regs *regs,
+ struct sbi_scratch *scratch)
+{
+ int rc;
+ const char *msg;
+ u32 hartid = csr_read(mhartid);
+ ulong mcause = csr_read(mcause);
+
+ if (mcause & (1UL << (__riscv_xlen - 1))) {
+ mcause &= ~(1UL << (__riscv_xlen - 1));
+ switch (mcause) {
+ case IRQ_M_TIMER:
+ sbi_timer_process(scratch, hartid);
+ break;
+ case IRQ_M_SOFT:
+ sbi_ipi_process(scratch, hartid);
+ break;
+ default:
+ sbi_trap_error("unhandled external interrupt",
+ SBI_ENOTSUPP, hartid, mcause, regs);
+ break;
+ };
+ return;
+ }
+
+ rc = SBI_ENOTSUPP;
+ msg = "trap handler failed";
+ switch (mcause) {
+ case CAUSE_ILLEGAL_INSTRUCTION:
+ rc = sbi_illegal_insn_handler(hartid, mcause, regs, scratch);
+ msg = "illegal instruction handler failed";
+ break;
+ case CAUSE_SUPERVISOR_ECALL:
+ case CAUSE_HYPERVISOR_ECALL:
+ rc = sbi_ecall_handler(hartid, mcause, regs, scratch);
+ msg = "ecall handler failed";
+ break;
+ default:
+ break;
+ };
+
+ if (rc) {
+ sbi_trap_error(msg, rc, hartid, mcause, regs);
+ }
+}