1 //! 处理中断和异常
2 //!
3 //! 架构相关的处理逻辑参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/kernel/traps.c
4 use core::hint::spin_loop;
5
6 use log::{error, trace};
7 use system_error::SystemError;
8
9 use super::TrapFrame;
10 use crate::exception::ebreak::EBreak;
11 use crate::{arch::syscall::syscall_handler, driver::irqchip::riscv_intc::riscv_intc_irq};
12
13 type ExceptionHandler = fn(&mut TrapFrame) -> Result<(), SystemError>;
14
15 static EXCEPTION_HANDLERS: [ExceptionHandler; 16] = [
16 do_trap_insn_misaligned, // 0
17 do_trap_insn_access_fault, // 1
18 do_trap_insn_illegal, // 2
19 do_trap_break, // 3
20 do_trap_load_misaligned, // 4
21 do_trap_load_access_fault, // 5
22 do_trap_store_misaligned, // 6
23 do_trap_store_access_fault, // 7
24 do_trap_user_env_call, // 8
25 default_handler, // 9
26 default_handler, // 10
27 default_handler, // 11
28 do_trap_insn_page_fault, // 12
29 do_trap_load_page_fault, // 13
30 default_handler, // 14
31 do_trap_store_page_fault, // 15
32 ];
33
34 #[no_mangle]
riscv64_do_irq(trap_frame: &mut TrapFrame)35 unsafe extern "C" fn riscv64_do_irq(trap_frame: &mut TrapFrame) {
36 if trap_frame.cause.is_interrupt() {
37 riscv64_do_interrupt(trap_frame);
38 } else if trap_frame.cause.is_exception() {
39 riscv64_do_exception(trap_frame);
40 }
41 }
42
43 /// 处理中断
riscv64_do_interrupt(trap_frame: &mut TrapFrame)44 fn riscv64_do_interrupt(trap_frame: &mut TrapFrame) {
45 riscv_intc_irq(trap_frame);
46 }
47
48 /// 处理异常
riscv64_do_exception(trap_frame: &mut TrapFrame)49 fn riscv64_do_exception(trap_frame: &mut TrapFrame) {
50 let code = trap_frame.cause.code();
51
52 if code < EXCEPTION_HANDLERS.len() {
53 let handler = EXCEPTION_HANDLERS[code];
54 handler(trap_frame).ok();
55 } else {
56 error!("riscv64_do_irq: exception code out of range");
57 loop {
58 // kernel die
59 spin_loop();
60 }
61 };
62 }
63
default_handler(_trap_frame: &mut TrapFrame) -> Result<(), SystemError>64 fn default_handler(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
65 error!("riscv64_do_irq: handler not found");
66 loop {
67 spin_loop();
68 }
69 }
70
71 /// 处理指令地址不对齐异常 #0
do_trap_insn_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError>72 fn do_trap_insn_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
73 error!("riscv64_do_irq: do_trap_insn_misaligned");
74 loop {
75 spin_loop();
76 }
77 }
78
79 /// 处理指令访问异常 #1
do_trap_insn_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError>80 fn do_trap_insn_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
81 error!("riscv64_do_irq: do_trap_insn_access_fault");
82 loop {
83 spin_loop();
84 }
85 }
86
87 /// 处理非法指令异常 #2
do_trap_insn_illegal(_trap_frame: &mut TrapFrame) -> Result<(), SystemError>88 fn do_trap_insn_illegal(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
89 error!("riscv64_do_irq: do_trap_insn_illegal");
90 loop {
91 spin_loop();
92 }
93 }
94
95 /// 处理断点异常 #3
do_trap_break(trap_frame: &mut TrapFrame) -> Result<(), SystemError>96 fn do_trap_break(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
97 trace!("riscv64_do_irq: do_trap_break");
98 // handle breakpoint
99 EBreak::handle(trap_frame)
100 }
101
102 /// 处理加载地址不对齐异常 #4
do_trap_load_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError>103 fn do_trap_load_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
104 error!("riscv64_do_irq: do_trap_load_misaligned");
105 loop {
106 spin_loop();
107 }
108 }
109
110 /// 处理加载访问异常 #5
do_trap_load_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError>111 fn do_trap_load_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
112 error!("riscv64_do_irq: do_trap_load_access_fault");
113 loop {
114 spin_loop();
115 }
116 }
117
118 /// 处理存储地址不对齐异常 #6
do_trap_store_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError>119 fn do_trap_store_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
120 error!("riscv64_do_irq: do_trap_store_misaligned");
121 loop {
122 spin_loop();
123 }
124 }
125
126 /// 处理存储访问异常 #7
do_trap_store_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError>127 fn do_trap_store_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
128 error!("riscv64_do_irq: do_trap_store_access_fault");
129 loop {
130 spin_loop();
131 }
132 }
133
134 /// 处理环境调用异常 #8
do_trap_user_env_call(trap_frame: &mut TrapFrame) -> Result<(), SystemError>135 fn do_trap_user_env_call(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
136 if trap_frame.is_from_user() {
137 let syscall_num = trap_frame.a7;
138 trap_frame.epc += 4;
139 trap_frame.origin_a0 = trap_frame.a0;
140 syscall_handler(syscall_num, trap_frame);
141 } else {
142 panic!("do_trap_user_env_call: not from user mode")
143 }
144 Ok(())
145 }
146
147 // 9-11 reserved
148
149 /// 处理指令页错误异常 #12
do_trap_insn_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError>150 fn do_trap_insn_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
151 let vaddr = trap_frame.badaddr;
152 let cause = trap_frame.cause;
153 let epc = trap_frame.epc;
154 error!(
155 "riscv64_do_irq: do_insn_page_fault vaddr: {:#x}, cause: {:?} epc: {:#x}",
156 vaddr, cause, epc
157 );
158 loop {
159 spin_loop();
160 }
161 }
162
163 /// 处理页加载错误异常 #13
do_trap_load_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError>164 fn do_trap_load_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
165 let vaddr = trap_frame.badaddr;
166 let cause = trap_frame.cause;
167 let epc = trap_frame.epc;
168 error!(
169 "riscv64_do_irq: do_trap_load_page_fault: epc: {epc:#x}, vaddr={:#x}, cause={:?}",
170 vaddr, cause
171 );
172
173 loop {
174 spin_loop();
175 }
176 }
177
178 // 14 reserved
179
180 /// 处理页存储错误异常 #15
do_trap_store_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError>181 fn do_trap_store_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
182 error!(
183 "riscv64_do_irq: do_trap_store_page_fault: epc: {:#x}, vaddr={:#x}, cause={:?}",
184 trap_frame.epc, trap_frame.badaddr, trap_frame.cause
185 );
186 loop {
187 spin_loop();
188 }
189 }
190