os/arch/riscv/trap/
trap_handler.rs1use core::sync::atomic::Ordering;
6
7use crate::earlyprintln;
8use crate::ipc::check_signal;
9use riscv::register::scause::{self, Trap};
10use riscv::register::sstatus::SPP;
11use riscv::register::{sepc, sscratch, sstatus, stval};
12
13use crate::arch::syscall::dispatch_syscall;
14use crate::arch::timer::{TIMER_TICKS, clock_freq, get_time};
15use crate::arch::trap::restore;
16use crate::kernel::{
17 SCHEDULER, TIMER, TIMER_QUEUE, schedule, send_signal_process, wake_up_with_block,
18};
19
20#[unsafe(no_mangle)]
36pub extern "C" fn trap_handler(trap_frame: &mut super::TrapFrame) {
37 let sstatus_old = sstatus::read();
39 let sepc_old = sepc::read();
40 let scause = scause::read();
41
42 match sstatus_old.spp() {
43 SPP::User => user_trap(scause, sepc_old, sstatus_old, trap_frame),
44 SPP::Supervisor => kernel_trap(scause, sepc_old, sstatus_old),
45 }
46
47 check_signal();
48 unsafe { restore(trap_frame) };
57}
58
59pub fn user_trap(
61 scause: scause::Scause,
62 sepc_old: usize,
63 sstatus_old: sstatus::Sstatus,
64 trap_frame: &mut super::TrapFrame,
65) {
66 crate::pr_debug!("[user_trap] scause: {:?}", scause.cause());
67 match scause.cause() {
68 Trap::Exception(8) => {
69 trap_frame.sepc = sepc_old.wrapping_add(4);
71 dispatch_syscall(trap_frame);
73 }
74 Trap::Interrupt(5) => {
75 crate::arch::timer::set_next_trigger();
77 check_timer();
78 }
79 _ => {
80 let stval_val = stval::read();
82 let scause_val = scause.bits();
83 let sscratch_val = sscratch::read();
84
85 crate::earlyprintln!("\n");
87 crate::earlyprintln!("===============================================");
88 crate::earlyprintln!(" UNEXPECTED TRAP IN USER MODE (U-Mode)");
89 crate::earlyprintln!("===============================================");
90 crate::earlyprintln!("");
91 crate::earlyprintln!("[!] Exception Type:");
92 crate::earlyprintln!(" Trap: {:?}", scause.cause());
93 crate::earlyprintln!(" Raw scause: {:#x}", scause_val);
94 crate::earlyprintln!("");
95 crate::earlyprintln!("[!] Exception Location:");
96 crate::earlyprintln!(" sepc (fault PC): {:#x}", sepc_old);
97 crate::earlyprintln!(" stval (fault VA): {:#x}", stval_val);
98 crate::earlyprintln!("");
99 crate::earlyprintln!("[!] Register State:");
100 crate::earlyprintln!(" sstatus: {:#x}", sstatus_old.bits());
101 crate::earlyprintln!(" sscratch: {:#x}", sscratch_val);
102 crate::earlyprintln!("");
103 crate::earlyprintln!("[!] TrapFrame Details:");
104 crate::earlyprintln!(" Stack Pointers:");
105 crate::earlyprintln!(" x2_sp (user stack): {:#x} <===", trap_frame.x2_sp);
106 crate::earlyprintln!(" kernel_sp: {:#x}", trap_frame.kernel_sp);
107 crate::earlyprintln!("");
108 crate::earlyprintln!(" General Registers:");
109 crate::earlyprintln!(
110 " x1_ra: {:#x} x3_gp: {:#x} x4_tp: {:#x}",
111 trap_frame.x1_ra,
112 trap_frame.x3_gp,
113 trap_frame.x4_tp
114 );
115 crate::earlyprintln!(
116 " x5_t0: {:#x} x6_t1: {:#x} x7_t2: {:#x}",
117 trap_frame.x5_t0,
118 trap_frame.x6_t1,
119 trap_frame.x7_t2
120 );
121 crate::earlyprintln!("");
122 crate::earlyprintln!(" Argument Registers:");
123 crate::earlyprintln!(
124 " x10_a0: {:#x} x11_a1: {:#x} x12_a2: {:#x}",
125 trap_frame.x10_a0,
126 trap_frame.x11_a1,
127 trap_frame.x12_a2
128 );
129 crate::earlyprintln!(
130 " x13_a3: {:#x} x14_a4: {:#x} x15_a5: {:#x}",
131 trap_frame.x13_a3,
132 trap_frame.x14_a4,
133 trap_frame.x15_a5
134 );
135 crate::earlyprintln!(
136 " x16_a6: {:#x} x17_a7: {:#x}",
137 trap_frame.x16_a6,
138 trap_frame.x17_a7
139 );
140 crate::earlyprintln!("");
141 crate::earlyprintln!(" Saved Registers:");
142 crate::earlyprintln!(
143 " x8_s0: {:#x} x9_s1: {:#x}",
144 trap_frame.x8_s0,
145 trap_frame.x9_s1
146 );
147 crate::earlyprintln!(
148 " x18_s2: {:#x} x19_s3: {:#x}",
149 trap_frame.x18_s2,
150 trap_frame.x19_s3
151 );
152 crate::earlyprintln!("");
153
154 crate::earlyprintln!("[!] Exception Explanation:");
156 match scause.cause() {
157 Trap::Exception(0) => {
158 crate::earlyprintln!(" Instruction Address Misaligned");
159 crate::earlyprintln!(" -> PC address {:#x} is not 2-byte aligned", sepc_old);
160 }
161 Trap::Exception(1) => {
162 crate::earlyprintln!(" Instruction Access Fault");
163 crate::earlyprintln!(" -> Cannot fetch instruction from {:#x}", sepc_old);
164 }
165 Trap::Exception(2) => {
166 crate::earlyprintln!(" Illegal Instruction");
167 crate::earlyprintln!(" -> Illegal instruction at {:#x}", sepc_old);
168 }
169 Trap::Exception(4) => {
170 crate::earlyprintln!(" Load Address Misaligned");
171 crate::earlyprintln!(
172 " -> Tried to load from misaligned address {:#x}",
173 stval_val
174 );
175 }
176 Trap::Exception(5) => {
177 crate::earlyprintln!(" Load Access Fault");
178 crate::earlyprintln!(" -> Cannot read from address {:#x}", stval_val);
179 }
180 Trap::Exception(6) => {
181 crate::earlyprintln!(" Store/AMO Address Misaligned");
182 crate::earlyprintln!(
183 " -> Tried to store to misaligned address {:#x}",
184 stval_val
185 );
186 }
187 Trap::Exception(7) => {
188 crate::earlyprintln!(" Store/AMO Access Fault");
189 crate::earlyprintln!(" -> Cannot write to address {:#x}", stval_val);
190 }
191 Trap::Exception(12) => {
192 crate::earlyprintln!(" Instruction Page Fault");
193 crate::earlyprintln!(
194 " -> Page table entry invalid or no permission at {:#x}",
195 sepc_old
196 );
197 }
198 Trap::Exception(13) => {
199 crate::earlyprintln!(" Load Page Fault");
200 crate::earlyprintln!(
201 " -> Page table entry invalid or no read permission at {:#x}",
202 stval_val
203 );
204 }
205 Trap::Exception(15) => {
206 crate::earlyprintln!(" Store Page Fault");
207 crate::earlyprintln!(
208 " -> Page table entry invalid or no write permission at {:#x}",
209 stval_val
210 );
211 }
212 _ => {
213 crate::earlyprintln!(" Unknown exception type");
214 }
215 }
216 crate::earlyprintln!("");
217 crate::earlyprintln!("===============================================");
218
219 panic!(
220 "Unexpected trap in user mode: {:?}, sepc = {:#x}, stval = {:#x}, sstatus = {:#x}",
221 scause.cause(),
222 sepc_old,
223 stval_val,
224 sstatus_old.bits()
225 );
226 }
227 }
228}
229
230pub fn kernel_trap(scause: scause::Scause, sepc_old: usize, sstatus_old: sstatus::Sstatus) {
232 match scause.cause() {
233 Trap::Interrupt(5) => {
234 crate::arch::timer::set_next_trigger();
236 check_timer();
237 }
238 Trap::Exception(e) => {
240 let sscratch_val = sscratch::read();
242 let stval_val = stval::read();
243 let scause_val = scause.bits();
244
245 earlyprintln!("\n");
247 earlyprintln!("================ KERNEL PANIC ================");
248 earlyprintln!("Unexpected exception in S-Mode (Kernel)!");
249 earlyprintln!("----------------------------------------------");
250 earlyprintln!(" Exception: {:?} (Raw scause: {:#x})", e, scause_val);
251 earlyprintln!(" Faulting VA (stval): {:#x}", stval_val);
252 earlyprintln!(" Faulting PC (sepc): {:#x}", sepc_old);
253 earlyprintln!(" sstatus: {:#x}", sstatus_old.bits());
254 earlyprintln!(" sscratch: {:#x}", sscratch_val);
255 earlyprintln!("==============================================");
256 panic!("Kernel exception in S-Mode");
258 }
259 trap => panic!(
260 "Unexpected trap in kernel: {:?}, sepc = {:#x}, sstatus = {:#x}",
261 trap,
262 sepc_old,
263 sstatus_old.bits()
264 ),
265 }
266}
267
268pub fn check_timer() {
270 let _ticks = TIMER_TICKS.fetch_add(1, Ordering::Relaxed);
271 while let Some(task) = TIMER_QUEUE.lock().pop_due_task(get_time()) {
272 wake_up_with_block(task);
273 }
274 while let Some(entry) = TIMER.lock().pop_due_entry(get_time()) {
275 send_signal_process(&entry.task, entry.sig);
276 if !entry.it_interval.is_zero() {
277 let next_trigger = get_time() + entry.it_interval.into_freq(clock_freq());
278 TIMER.lock().push(next_trigger, entry);
279 }
280 }
281 if SCHEDULER.lock().update_time_slice() {
282 schedule();
283 }
284}
285
286#[allow(dead_code)]
287pub fn check_device() {}