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:
Jonathan Neuschäfer 2016-08-13 04:20:09 +02:00 committed by Ronald G. Minnich
parent 38103bde75
commit 363526cfb8
1 changed files with 72 additions and 62 deletions

View File

@ -84,81 +84,91 @@ void handle_supervisor_call(trapframe *tf) {
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) {
write_csr(mscratch, tf);
uintptr_t cause;
void *epc;
void *badAddr;
// extract cause
asm("csrr %0, mcause" : "=r"(cause));
// extract faulting Instruction pc
epc = (void*) tf->epc;
// extract bad address
asm("csrr %0, mbadaddr" : "=r"(badAddr));
switch(cause) {
case 0:
printk(BIOS_DEBUG, "Trap: Instruction address misaligned\n");
switch(tf->cause) {
case CAUSE_MISALIGNED_FETCH:
case CAUSE_FAULT_FETCH:
case CAUSE_ILLEGAL_INSTRUCTION:
case CAUSE_BREAKPOINT:
case CAUSE_FAULT_LOAD:
case CAUSE_FAULT_STORE:
case CAUSE_USER_ECALL:
case CAUSE_HYPERVISOR_ECALL:
case CAUSE_MACHINE_ECALL:
print_trap_information(tf);
break;
case 1:
printk(BIOS_DEBUG, "Trap: Instruction access fault\n");
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");
case CAUSE_MISALIGNED_LOAD:
print_trap_information(tf);
handle_misaligned_load(tf);
break;
case 5:
printk(BIOS_DEBUG, "Trap: Load access fault\n");
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);
case CAUSE_MISALIGNED_STORE:
print_trap_information(tf);
handle_misaligned_store(tf);
break;
case 7:
printk(BIOS_DEBUG, "Trap: Store access fault\n");
printk(BIOS_DEBUG, "Bad instruction pc: %p\n", epc);
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");
case CAUSE_SUPERVISOR_ECALL:
/* Don't print so we make console putchar calls look
the way they should */
handle_supervisor_call(tf);
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:
printk(BIOS_DEBUG, "Trap: Unknown cause %p\n",
(void *)cause);
print_trap_information(tf);
break;
}
printk(BIOS_DEBUG, "Stored ra: %p\n", (void*) tf->gpr[1]);
printk(BIOS_DEBUG, "Stored sp: %p\n", (void*) tf->gpr[2]);
printk(BIOS_DEBUG, "looping...\n");
while(1);
die("Can't recover from trap. Halting.\n");
}
void handle_misaligned_load(trapframe *tf) {