os/arch/riscv/trap/
trap_handler.rs

1//! RISC-V 架构的陷阱处理程序实现
2//!
3//! 64 位 RISC-V,usize = 8 字节
4
5use 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/// 陷阱处理程序
21/// 从中断处理入口跳转到这里时,
22/// 陷阱帧的地址(sp)被隐式地作为参数 a0 传递给了 trap_handler 函数。
23/// 在这里,trap_frame 指向了保存的 TrapFrame 结构体。
24/// 此外,在通过 stvec 跳转到中断处理入口时,SSIE 被自动清除,
25/// 因此在内核陷阱处理程序开始时,中断是被禁用的。
26/// 必须从这个函数正常返回后,通过 restore 中的 sret 指令才能正确恢复中断状态。
27///
28/// # 警告:
29/// - 不要在中断处理中调用任何可能引起内存分配或阻塞的函数,
30///   因为这可能会导致死锁或不可预测的行为。
31/// - 确保在中断处理程序中正确保存和恢复所有必要的寄存器状态,
32///   以避免破坏正在运行的进程的状态。
33/// - 注意陷阱处理程序的执行时间,
34///   避免长时间占用 CPU,影响系统的响应性。
35#[unsafe(no_mangle)]
36pub extern "C" fn trap_handler(trap_frame: &mut super::TrapFrame) {
37    // 保存进入中断时的状态
38    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    // Safe:
49    // restore 是一个汇编函数,它恢复寄存器并执行 sret。
50    //
51    // 这里的 unsafe 调用是安全的,前提是:
52    // 1. 所有的中断处理逻辑处理已完成。
53    // 2. **关键前提:在 match 中调用的 `user_trap` 必须保证如果它修改了 `trap_frame`,
54    //    则其中的所有寄存器值(尤其是 sepc 和栈指针)都是有效的、合法的上下文状态。**
55    // 3. `restore` 的汇编实现本身是正确的。
56    unsafe { restore(trap_frame) };
57}
58
59/// 处理来自用户态的陷阱(系统调用、中断、异常)
60pub 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            // 设置返回地址为下一个指令
70            trap_frame.sepc = sepc_old.wrapping_add(4);
71            // 处理系统调用
72            dispatch_syscall(trap_frame);
73        }
74        Trap::Interrupt(5) => {
75            // 处理时钟中断
76            crate::arch::timer::set_next_trigger();
77            check_timer();
78        }
79        _ => {
80            // 立即读取相关寄存器的当前值
81            let stval_val = stval::read();
82            let scause_val = scause.bits();
83            let sscratch_val = sscratch::read();
84
85            // 打印详细的异常信息
86            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            // 解释常见的异常类型
155            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
230/// 处理来自内核态的陷阱(中断、异常)
231pub fn kernel_trap(scause: scause::Scause, sepc_old: usize, sstatus_old: sstatus::Sstatus) {
232    match scause.cause() {
233        Trap::Interrupt(5) => {
234            // 处理时钟中断
235            crate::arch::timer::set_next_trigger();
236            check_timer();
237        }
238        // 中断处理时发生异常一般是致命的
239        Trap::Exception(e) => {
240            // 立即读取 sscratch 和 stval 寄存器的当前值
241            let sscratch_val = sscratch::read();
242            let stval_val = stval::read();
243            let scause_val = scause.bits();
244
245            // 先直接打印到控制台,避免panic格式化时再次触发异常
246            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            // sbi::shutdown(true);
257            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
268/// 处理时钟中断
269pub 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)]
287/// TODO: 处理设备中断
288pub fn check_device() {}