arch/riscv: Improve and refactor trap handling diagnostics
Change-Id: I57032f958c88ea83a420e93b459df4f620799d84 Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net> Reviewed-on: https://review.coreboot.org/16016 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
38103bde75
commit
363526cfb8
|
@ -84,81 +84,91 @@ void handle_supervisor_call(trapframe *tf) {
|
||||||
asm volatile("j supervisor_call_return");
|
asm volatile("j supervisor_call_return");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *const exception_names[] = {
|
||||||
|
"Instruction address misaligned",
|
||||||
|
"Instruction access fault",
|
||||||
|
"Illegal instruction",
|
||||||
|
"Breakpoint",
|
||||||
|
"Load address misaligned",
|
||||||
|
"Load access fault",
|
||||||
|
"Store address misaligned",
|
||||||
|
"Store access fault",
|
||||||
|
"Environment call from U-mode",
|
||||||
|
"Environment call from S-mode",
|
||||||
|
"Environment call from H-mode",
|
||||||
|
"Environment call from M-mode"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mstatus_to_previous_mode(uintptr_t ms)
|
||||||
|
{
|
||||||
|
switch (ms & MSTATUS_MPP) {
|
||||||
|
case 0x00000000: return "user";
|
||||||
|
case 0x00000800: return "supervisor";
|
||||||
|
case 0x00001000: return "hypervisor";
|
||||||
|
case 0x00001800: return "machine";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_trap_information(const trapframe *tf)
|
||||||
|
{
|
||||||
|
const char *previous_mode;
|
||||||
|
bool mprv = !!(tf->status & MSTATUS_MPRV);
|
||||||
|
|
||||||
|
/* Leave some space around the trap message */
|
||||||
|
printk(BIOS_DEBUG, "\n");
|
||||||
|
|
||||||
|
if (tf->cause < ARRAY_SIZE(exception_names))
|
||||||
|
printk(BIOS_DEBUG, "Exception: %s\n",
|
||||||
|
exception_names[tf->cause]);
|
||||||
|
else
|
||||||
|
printk(BIOS_DEBUG, "Trap: Unknown cause %p\n",
|
||||||
|
(void *)tf->cause);
|
||||||
|
|
||||||
|
previous_mode = mstatus_to_previous_mode(read_csr(mstatus));
|
||||||
|
printk(BIOS_DEBUG, "Previous mode: %s%s\n",
|
||||||
|
previous_mode, mprv? " (MPRV)":"");
|
||||||
|
printk(BIOS_DEBUG, "Bad instruction pc: %p\n", (void *)tf->epc);
|
||||||
|
printk(BIOS_DEBUG, "Bad address: %p\n", (void *)tf->badvaddr);
|
||||||
|
printk(BIOS_DEBUG, "Stored ra: %p\n", (void*) tf->gpr[1]);
|
||||||
|
printk(BIOS_DEBUG, "Stored sp: %p\n", (void*) tf->gpr[2]);
|
||||||
|
}
|
||||||
|
|
||||||
void trap_handler(trapframe *tf) {
|
void trap_handler(trapframe *tf) {
|
||||||
write_csr(mscratch, tf);
|
write_csr(mscratch, tf);
|
||||||
uintptr_t cause;
|
|
||||||
void *epc;
|
|
||||||
void *badAddr;
|
|
||||||
|
|
||||||
// extract cause
|
switch(tf->cause) {
|
||||||
asm("csrr %0, mcause" : "=r"(cause));
|
case CAUSE_MISALIGNED_FETCH:
|
||||||
|
case CAUSE_FAULT_FETCH:
|
||||||
// extract faulting Instruction pc
|
case CAUSE_ILLEGAL_INSTRUCTION:
|
||||||
epc = (void*) tf->epc;
|
case CAUSE_BREAKPOINT:
|
||||||
|
case CAUSE_FAULT_LOAD:
|
||||||
// extract bad address
|
case CAUSE_FAULT_STORE:
|
||||||
asm("csrr %0, mbadaddr" : "=r"(badAddr));
|
case CAUSE_USER_ECALL:
|
||||||
|
case CAUSE_HYPERVISOR_ECALL:
|
||||||
switch(cause) {
|
case CAUSE_MACHINE_ECALL:
|
||||||
case 0:
|
print_trap_information(tf);
|
||||||
printk(BIOS_DEBUG, "Trap: Instruction address misaligned\n");
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case CAUSE_MISALIGNED_LOAD:
|
||||||
printk(BIOS_DEBUG, "Trap: Instruction access fault\n");
|
print_trap_information(tf);
|
||||||
printk(BIOS_DEBUG, "Bad instruction pc: %p\n", epc);
|
|
||||||
printk(BIOS_DEBUG, "Address: %p\n", badAddr);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
printk(BIOS_DEBUG, "Trap: Illegal instruction\n");
|
|
||||||
printk(BIOS_DEBUG, "Bad instruction pc: %p\n", epc);
|
|
||||||
printk(BIOS_DEBUG, "Address: %p\n", badAddr);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
printk(BIOS_DEBUG, "Trap: Breakpoint\n");
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
printk(BIOS_DEBUG, "Trap: Load address misaligned\n");
|
|
||||||
handle_misaligned_load(tf);
|
handle_misaligned_load(tf);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case CAUSE_MISALIGNED_STORE:
|
||||||
printk(BIOS_DEBUG, "Trap: Load access fault\n");
|
print_trap_information(tf);
|
||||||
printk(BIOS_DEBUG, "Bad instruction pc: %p\n", epc);
|
|
||||||
printk(BIOS_DEBUG, "Load Address: %p\n", badAddr);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
printk(BIOS_DEBUG, "Trap: Store address misaligned\n");
|
|
||||||
printk(BIOS_DEBUG, "Bad instruction pc: %p\n", epc);
|
|
||||||
printk(BIOS_DEBUG, "Store Address: %p\n", badAddr);
|
|
||||||
handle_misaligned_store(tf);
|
handle_misaligned_store(tf);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case CAUSE_SUPERVISOR_ECALL:
|
||||||
printk(BIOS_DEBUG, "Trap: Store access fault\n");
|
/* Don't print so we make console putchar calls look
|
||||||
printk(BIOS_DEBUG, "Bad instruction pc: %p\n", epc);
|
the way they should */
|
||||||
printk(BIOS_DEBUG, "Store Address: %p\n", badAddr);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
printk(BIOS_DEBUG, "Trap: Environment call from U-mode\n");
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
// Don't print so we make console putchar calls look the way they should
|
|
||||||
// printk(BIOS_DEBUG, "Trap: Environment call from S-mode\n");
|
|
||||||
handle_supervisor_call(tf);
|
handle_supervisor_call(tf);
|
||||||
break;
|
break;
|
||||||
case 10:
|
|
||||||
printk(BIOS_DEBUG, "Trap: Environment call from H-mode\n");
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
printk(BIOS_DEBUG, "Trap: Environment call from M-mode\n");
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
printk(BIOS_DEBUG, "Trap: Unknown cause %p\n",
|
print_trap_information(tf);
|
||||||
(void *)cause);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printk(BIOS_DEBUG, "Stored ra: %p\n", (void*) tf->gpr[1]);
|
|
||||||
printk(BIOS_DEBUG, "Stored sp: %p\n", (void*) tf->gpr[2]);
|
die("Can't recover from trap. Halting.\n");
|
||||||
printk(BIOS_DEBUG, "looping...\n");
|
|
||||||
while(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_misaligned_load(trapframe *tf) {
|
void handle_misaligned_load(trapframe *tf) {
|
||||||
|
|
Loading…
Reference in New Issue