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
11#include "mos/tasks/signal.hpp"
12
14
16{
18 current_cpu->interrupt_regs = regs;
19 regs->sepc = sepc;
20 regs->sstatus = read_csr(sstatus);
21 const bool is_userspace = (regs->sstatus & SSTATUS_SPP) == 0;
22 const bool is_interrupt = scause & BIT(63);
23 const long exception = scause & ~BIT(63);
24 long ret = 0;
25
26 const char *name = "<unknown>";
27 if (is_interrupt)
28 {
29 switch (exception)
30 {
31 case 1: name = "Supervisor software interrupt"; break;
32 case 5: name = "Supervisor timer interrupt"; goto handle_timer;
33 case 9: name = "Supervisor external interrupt"; goto handle_irq;
34 case 13: name = "Counter-overflow interrupt"; break;
35 default: name = exception >= 16 ? "Designated for platform use" : "<reserved>";
36 }
37 }
38 else
39 {
40 switch (exception)
41 {
42 case 0: name = "Instruction address misaligned"; break;
43 case 1: name = "Instruction access fault"; break;
44 case 2: name = "Illegal instruction"; goto handle_ii;
45 case 3: name = "Breakpoint"; goto handle_bp;
46 case 4: name = "Load address misaligned"; break;
47 case 5: name = "Load access fault"; break;
48 case 6: name = "Store/AMO address misaligned"; break;
49 case 7: name = "Store/AMO access fault"; break;
50 case 8: name = "Environment call from U-mode"; goto handle_syscall;
51 case 9: name = "Environment call from S-mode"; break;
52 case 12: name = "Instruction page fault"; goto handle_pf;
53 case 13: name = "Load page fault"; goto handle_pf;
54 case 15: name = "Store/AMO page fault"; goto handle_pf;
55 case 18: name = "Software check"; break;
56 case 19: name = "Hardware error"; break;
57 default: name = ((exception >= 24 && exception <= 31) || (exception >= 48 && exception <= 63)) ? "Designated for custom use" : "<reserved>";
58 }
59 }
60
61 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);
62 MOS_ASSERT(!"Unhandled exception");
63
64handle_irq:
65{
66 const u32 irq = plic_claim_irq();
67 interrupt_entry(irq);
68 plic_complete(irq);
69 goto leave;
70}
71handle_bp:
72{
74 goto leave;
75}
76
77handle_timer:
78{
79 const reg_t stime = read_csr(time);
80 write_csr(stimecmp, stime + 1000 * 10); // 10ms
81 spinlock_acquire(&current_thread->state_lock);
83 reschedule();
84 goto leave;
85}
86
87handle_syscall:
88{
89 regs->sepc += 4; // increase sepc to the next instruction
90 ret = ksyscall_enter(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3, regs->a4, regs->a5);
91 goto leave;
92}
93
94handle_ii:
95{
96 if (sepc > MOS_KERNEL_START_VADDR)
97 {
99 MOS_ASSERT(!"Kernel mode illegal instruction");
100 }
101
103 goto leave;
104}
105
106handle_pf:
107{
108 MOS_ASSERT_X(!is_interrupt, "Page faults should not be interrupts");
109
110 const bool present = mm_do_get_present(current_cpu->mm_context->pgd, stval);
111
112 pagefault_t pfinfo = {
113 .is_present = present,
114 .is_write = exception == 15,
115 .is_user = is_userspace,
116 .is_exec = exception == 12,
117 .ip = sepc,
118 .regs = regs,
119 };
120 mm_handle_fault(stval, &pfinfo);
121 goto leave;
122}
123
124leave:
125 if (is_userspace)
126 {
127 ptr<platform_regs_t> syscall_ret_regs;
128 if (!is_interrupt && exception == 8)
129 syscall_ret_regs = signal_exit_to_user_prepare(regs, regs->a7, ret);
130 else
131 syscall_ret_regs = signal_exit_to_user_prepare(regs);
132
133 if (syscall_ret_regs)
134 *regs = *syscall_ret_regs;
135
136 reg_t sstatus = read_csr(sstatus);
137 sstatus &= ~SSTATUS_SPP;
138 sstatus |= SSTATUS_SPIE;
139 sstatus |= SSTATUS_SUM;
140
141 write_csr(sstatus, sstatus);
142 write_csr(sscratch, current_thread->k_stack.top);
144 write_csr(sepc, regs->sepc);
145 }
146
147 return regs;
148}
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.hpp:12
#define MOS_ASSERT(cond)
Definition assert.hpp:19
void clocksource_tick(clocksource_t *clocksource)
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:122
ptr< platform_regs_t > 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:88
void mm_handle_fault(ptr_t fault_addr, pagefault_t *info)
Handle a page fault.
Definition mm.cpp:363
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:68
#define current_thread
Definition platform.hpp:33
#define current_cpu
Definition platform.hpp:32
#define current_process
Definition platform.hpp:34
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_SPIE
Definition cpu.hpp:22
#define SSTATUS_SPP
Definition cpu.hpp:23
const char __riscv64_usermode_trap_entry[]
#define read_csr(reg)
Definition cpu.hpp:12
#define write_csr(reg, val)
Definition cpu.hpp:13
const char __riscv64_trap_entry[]
#define SSTATUS_SUM
Definition cpu.hpp:24
void reschedule(void)
reschedule.
Definition schedule.cpp:106
mos::shared_ptr< T > ptr
const char * name
Definition slab.cpp:33
#define spinlock_acquire(lock)
Definition spinlock.hpp:64
bool mm_do_get_present(pgd_t max, ptr_t vaddr)
platform_regs_t * riscv64_trap_handler(platform_regs_t *regs, reg_t scause, reg_t stval, reg_t sepc)
Definition trap.cpp:15
clocksource_t goldfish
uintn reg_t
Definition types.h:47
unsigned int u32
Definition types.h:17
#define PTR_FMT
Definition types.h:29
unsigned long ptr_t
Definition types.h:21