cbfs: Remove remnants of ext-win-*
[coreboot2.git] / src / arch / riscv / trap_handler.c
blob6a151a6e419e4bea8092141a12375366b43f6dc9
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * Early initialization code for riscv
4 */
6 #include <arch/encoding.h>
7 #include <arch/exception.h>
8 #include <console/console.h>
9 #include <vm.h>
10 #include <mcall.h>
11 #include <sbi.h>
12 #include <types.h>
14 static const char *const exception_names[] = {
15 "Instruction address misaligned",
16 "Instruction access fault",
17 "Illegal instruction",
18 "Breakpoint",
19 "Load address misaligned",
20 "Load access fault",
21 "Store address misaligned",
22 "Store access fault",
23 "Environment call from U-mode",
24 "Environment call from S-mode",
25 "Reserved (10)",
26 "Environment call from M-mode",
27 "Instruction page fault",
28 "Load page fault",
29 "Reserved (14)",
30 "Store page fault",
33 static const char *mstatus_to_previous_mode(uintptr_t ms)
35 switch (ms & MSTATUS_MPP) {
36 case 0x00000000:
37 return "user";
38 case 0x00000800:
39 return "supervisor";
40 case 0x00001000:
41 return "hypervisor";
42 case 0x00001800:
43 return "machine";
46 return "unknown";
49 static void print_trap_information(const struct trapframe *tf)
51 const char *previous_mode;
52 bool mprv = !!(tf->status & MSTATUS_MPRV);
53 int hart_id = read_csr(mhartid);
55 /* Leave some space around the trap message */
56 printk(BIOS_DEBUG, "\n");
58 if (tf->cause < ARRAY_SIZE(exception_names))
59 printk(BIOS_DEBUG, "Exception: %s\n", exception_names[tf->cause]);
60 else
61 printk(BIOS_DEBUG, "Trap: Unknown cause %p\n", (void *)tf->cause);
63 previous_mode = mstatus_to_previous_mode(read_csr(mstatus));
64 printk(BIOS_DEBUG, "Hart ID: %d\n", hart_id);
65 printk(BIOS_DEBUG, "Previous mode: %s%s\n", previous_mode, mprv ? " (MPRV)" : "");
66 printk(BIOS_DEBUG, "Bad instruction pc: %p\n", (void *)tf->epc);
67 printk(BIOS_DEBUG, "Bad address: %p\n", (void *)tf->badvaddr);
68 printk(BIOS_DEBUG, "Stored ra: %p\n", (void *)tf->gpr[1]);
69 printk(BIOS_DEBUG, "Stored sp: %p\n", (void *)tf->gpr[2]);
72 static void interrupt_handler(struct trapframe *tf)
74 uint64_t cause = tf->cause & ~0x8000000000000000ULL;
76 switch (cause) {
77 case IRQ_M_TIMER:
79 * Set interrupt pending for supervisor mode and disable timer
80 * interrupt in machine mode.
81 * To receive another timer interrupt just set timecmp and
82 * enable machine mode timer interrupt again.
85 clear_csr(mie, MIP_MTIP);
86 set_csr(mip, MIP_STIP);
88 break;
89 case IRQ_M_SOFT:
90 if (HLS()->ipi_pending & IPI_SOFT) {
91 set_csr(mip, MIP_SSIP);
92 } else if (HLS()->ipi_pending & IPI_FENCE_I) {
93 asm volatile("fence.i");
94 } else if (HLS()->ipi_pending & IPI_SFENCE_VMA) {
95 asm volatile("sfence.vma");
96 } else if (HLS()->ipi_pending & IPI_SFENCE_VMA_ASID) {
97 asm volatile("sfence.vma");
98 } else if (HLS()->ipi_pending & IPI_SHUTDOWN) {
99 while (HLS()->ipi_pending & IPI_SHUTDOWN)
100 asm volatile("wfi");
102 break;
103 default:
104 printk(BIOS_EMERG, "======================================\n");
105 printk(BIOS_EMERG, "coreboot: Unknown machine interrupt: 0x%llx\n", cause);
106 printk(BIOS_EMERG, "======================================\n");
107 print_trap_information(tf);
108 break;
112 void trap_handler(struct trapframe *tf)
114 if (tf->cause & 0x8000000000000000ULL) {
115 interrupt_handler(tf);
116 return;
119 switch (tf->cause) {
120 case CAUSE_FETCH_ACCESS:
121 case CAUSE_ILLEGAL_INSTRUCTION:
122 case CAUSE_BREAKPOINT:
123 case CAUSE_LOAD_ACCESS:
124 case CAUSE_STORE_ACCESS:
125 case CAUSE_USER_ECALL:
126 case CAUSE_HYPERVISOR_ECALL:
127 case CAUSE_MACHINE_ECALL:
128 print_trap_information(tf);
129 break;
130 case CAUSE_SUPERVISOR_ECALL:
131 handle_sbi(tf);
132 return;
133 case CAUSE_MISALIGNED_FETCH:
134 case CAUSE_MISALIGNED_LOAD:
135 case CAUSE_MISALIGNED_STORE:
136 print_trap_information(tf);
137 return;
138 default:
139 printk(BIOS_EMERG, "================================\n");
140 printk(BIOS_EMERG, "coreboot: can not handle a trap:\n");
141 printk(BIOS_EMERG, "================================\n");
142 print_trap_information(tf);
143 break;
146 die("Can't recover from trap. Halting.\n");
149 /* This function used to redirect trap to s-mode. */
150 void redirect_trap(void)
152 write_csr(stval, read_csr(mtval));
153 write_csr(sepc, read_csr(mepc));
154 write_csr(scause, read_csr(mcause));
155 write_csr(mepc, read_csr(stvec));
157 uintptr_t status = read_csr(mstatus);
158 uintptr_t mpp = EXTRACT_FIELD(status, MSTATUS_MPP);
159 status = INSERT_FIELD(status, MSTATUS_MPP, 1);
160 status = INSERT_FIELD(status, MSTATUS_SPP, mpp & 1);
161 write_csr(mstatus, status);