Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 106 additions & 2 deletions loader/src/riscv/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,113 @@
*/

#include "../arch.h"
#include "../cutil.h"
#include "../uart.h"

#if __riscv_xlen == 32
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we bother doing this when everything else assumes 64-bit?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just did it since it's trivial

#define SCAUSE_IRQ BIT(31)
#define SCAUSE_CODE MASK(31)
#else
#define SCAUSE_IRQ BIT(63)
#define SCAUSE_CODE MASK(63)
#endif

static inline uint64_t read_stval(void)
{
uint64_t temp;
asm volatile("csrr %0, stval" : "=r"(temp));
return temp;
}

static inline uint64_t read_scause(void)
{
uint64_t temp;
asm volatile("csrr %0, scause" : "=r"(temp));
return temp;
}

static inline uint64_t read_sepc(void)
{
uint64_t temp;
asm volatile("csrr %0, sepc" : "=r"(temp));
return temp;
}

static inline void write_stvec(void *value)
{
asm volatile("csrw stvec, %0" :: "rK"(value) : "memory");
}

static char *scause_to_string(uint64_t scause)
{
if (scause & SCAUSE_IRQ) {
switch (scause & SCAUSE_CODE) {
case 1:
return "Supervisor software interrupt";
case 5:
return "Supervisor timer interrupt";
case 9:
return "Supervisor external interrupt";
case 13:
return "Counter-overflow interrupt";
default:
return "<unknown>";
}
} else {
switch (scause) {
case 0:
return "Instruction address misaligned";
case 1:
return "Instruction access fault";
case 2:
return "Illegal instruction";
case 3:
return "Breakpoint";
case 4:
return "Load address misaligned";
case 5:
return "Load access fault";
case 6:
return "Store/AMO address misaligned";
case 7:
return "Store/AMO access fault";
case 8:
return "Environment call from U-mode";
case 9:
return "Environment call from S-mode";
case 12:
return "Instruction page fault";
case 13:
return "Load page fault";
case 15:
return "Store/AMO page fault";
case 18:
return "Software check";
case 19:
return "Hardware error";
default:
return "<unknown>";
}
}
}

static void exception_handler(void)
{
uint64_t scause = read_scause();
puts("LDR|ERROR: loader trapped exception with reason '");
puts(scause_to_string(scause));
puts("' (scause: ");
puthex64(scause);
puts(", stval: ");
puthex64(read_stval());
puts(", sepc: ");
puthex64(read_sepc());
puts(")\n");

while (1) {}
}

void arch_set_exception_handler(void)
{
/* Don't do anything on RISC-V since we always are in S-mode so M-mode
* will catch our faults (e.g SBI). */
write_stvec((void *)exception_handler);
}
Loading