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