MOS Source Code
Loading...
Searching...
No Matches
trap.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
10#include "mos/tasks/signal.hpp"
11
12extern "C" void riscv64_trap_handler(platform_regs_t *regs, reg_t scause, reg_t stval, reg_t sepc)
13{
15 current_cpu->interrupt_regs = regs;
16 regs->sepc = sepc;
17 regs->sstatus = read_csr(sstatus);
18 const bool is_userspace = (regs->sstatus & SSTATUS_SPP) == 0;
19 const bool is_interrupt = scause & BIT(63);
20 const long exception = scause & ~BIT(63);
21 long ret = 0;
22
23 const char *name = "<unknown>";
24 if (is_interrupt)
25 {
26 switch (exception)
27 {
28 case 1: name = "Supervisor software interrupt"; break;
29 case 5: name = "Supervisor timer interrupt"; goto handle_timer;
30 case 9: name = "Supervisor external interrupt"; goto handle_irq;
31 case 13: name = "Counter-overflow interrupt"; break;
32 default: name = exception >= 16 ? "Designated for platform use" : "<reserved>";
33 }
34 }
35 else
36 {
37 switch (exception)
38 {
39 case 0: name = "Instruction address misaligned"; break;
40 case 1: name = "Instruction access fault"; break;
41 case 2: name = "Illegal instruction"; goto handle_ii;
42 case 3: name = "Breakpoint"; goto handle_bp;
43 case 4: name = "Load address misaligned"; break;
44 case 5: name = "Load access fault"; break;
45 case 6: name = "Store/AMO address misaligned"; break;
46 case 7: name = "Store/AMO access fault"; break;
47 case 8: name = "Environment call from U-mode"; goto handle_syscall;
48 case 9: name = "Environment call from S-mode"; break;
49 case 12: name = "Instruction page fault"; goto handle_pf;
50 case 13: name = "Load page fault"; goto handle_pf;
51 case 15: name = "Store/AMO page fault"; goto handle_pf;
52 case 18: name = "Software check"; break;
53 case 19: name = "Hardware error"; break;
54 default: name = ((exception >= 24 && exception <= 31) || (exception >= 48 && exception <= 63)) ? "Designated for custom use" : "<reserved>";
55 }
56 }
57
58 pr_info("riscv64 trap: sepc=" PTR_FMT ", scause" PTR_FMT ", stval=" PTR_FMT ", %s, code = %ld, interrupt = %d", sepc, scause, stval, name, exception, is_interrupt);
59 MOS_ASSERT(!"Unhandled exception");
60
61handle_irq:
62{
63 const u32 irq = plic_claim_irq();
64 interrupt_entry(irq);
65 plic_complete(irq);
66 goto leave;
67}
68handle_bp:
69{
71 goto leave;
72}
73
74handle_timer:
75{
76 const reg_t stime = read_csr(time);
77 write_csr(stimecmp, stime + 500 * 1000); // 0.5 ms
78 spinlock_acquire(&current_thread->state_lock);
79 reschedule();
80 goto leave;
81}
82
83handle_syscall:
84{
85 regs->sepc += 4; // increase sepc to the next instruction
86 ret = ksyscall_enter(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3, regs->a4, regs->a5);
87 goto leave;
88}
89
90handle_ii:
91{
92 if (sepc > MOS_KERNEL_START_VADDR)
93 {
95 MOS_ASSERT(!"Kernel mode illegal instruction");
96 }
97
99 goto leave;
100}
101
102handle_pf:
103{
104 MOS_ASSERT_X(!is_interrupt, "Page faults should not be interrupts");
105
106 const bool present = mm_do_get_present(current_cpu->mm_context->pgd, stval);
107
108 pagefault_t pfinfo = {
109 .is_present = present,
110 .is_write = exception == 15,
111 .is_user = is_userspace,
112 .is_exec = exception == 12,
113 .ip = sepc,
114 .regs = regs,
115 };
116 mm_handle_fault(stval, &pfinfo);
117 goto leave;
118}
119
120leave:
121 if (is_userspace)
122 {
123 if (!is_interrupt && exception == 8)
124 signal_exit_to_user_prepare_syscall(regs, regs->a7, ret);
125 else
128 }
129
130 MOS_ASSERT_X(!is_userspace, "should not return to userspace here");
131 riscv64_trap_exit(regs);
132}
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.hpp:15
#define MOS_ASSERT(cond)
Definition assert.hpp:14
long signal_send_to_process(Process *target, signal_t signal)
Send a signal to a process, an arbitrary thread will be chosen to receive the signal.
Definition signal.cpp:121
void signal_exit_to_user_prepare_syscall(platform_regs_t *regs, reg_t syscall_nr, reg_t syscall_ret)
Prepare to exit to userspace after a syscall.
Definition signal.cpp:256
void signal_exit_to_user_prepare(platform_regs_t *regs)
Prepare to exit to userspace.
Definition signal.cpp:240
long signal_send_to_thread(Thread *target, signal_t signal)
Send a signal to a thread.
Definition signal.cpp:87
void mm_handle_fault(ptr_t fault_addr, pagefault_t *info)
Handle a page fault.
Definition mm.cpp:358
void interrupt_entry(u32 irq)
Definition interrupt.cpp:21
reg_t ksyscall_enter(reg_t number, reg_t arg1, reg_t arg2, reg_t arg3, reg_t arg4, reg_t arg5, reg_t arg6)
#define BIT(x)
Definition mos_global.h:107
void try_handle_kernel_panics(ptr_t ip)
Definition panic.cpp:67
#define current_thread
Definition platform.hpp:32
#define current_cpu
Definition platform.hpp:31
#define current_process
Definition platform.hpp:33
u32 plic_claim_irq()
Definition plic.cpp:22
void plic_complete(u32 irq)
Definition plic.cpp:27
#define pr_info(fmt,...)
Definition printk.hpp:35
#define MOS_KERNEL_START_VADDR
#define SSTATUS_SPP
Definition cpu.hpp:34
void riscv64_trap_exit(platform_regs_t *regs)
#define read_csr(reg)
Definition cpu.hpp:23
#define write_csr(reg, val)
Definition cpu.hpp:24
const char __riscv64_trap_entry[]
void platform_return_to_userspace(platform_regs_t *regs)
void reschedule(void)
reschedule.
Definition schedule.cpp:107
const char * name
Definition slab.cpp:35
#define spinlock_acquire(lock)
Definition spinlock.hpp:64
reg_t sepc
Definition cpu.hpp:18
reg_t sstatus
Definition cpu.hpp:18
bool mm_do_get_present(pgd_t max, ptr_t vaddr)
void riscv64_trap_handler(platform_regs_t *regs, reg_t scause, reg_t stval, reg_t sepc)
Definition trap.cpp:12
uintn reg_t
Definition types.h:47
unsigned int u32
Definition types.h:17
#define PTR_FMT
Definition types.h:29