xref: /DragonOS/kernel/src/arch/x86_64/interrupt/trap.rs (revision 7b0ef10895108a0de5ff5ef3d2f93f40cf2e33a5)
1 use log::{error, trace, warn};
2 use system_error::SystemError;
3 
4 use super::{
5     entry::{set_intr_gate, set_system_trap_gate},
6     TrapFrame,
7 };
8 use crate::exception::debug::DebugException;
9 use crate::exception::ebreak::EBreak;
10 use crate::{
11     arch::{CurrentIrqArch, MMArch},
12     exception::InterruptArch,
13     mm::VirtAddr,
14     process::ProcessManager,
15     smp::core::smp_get_processor_id,
16 };
17 
18 extern "C" {
19     fn trap_divide_error();
20     fn trap_debug();
21     fn trap_nmi();
22     fn trap_int3();
23     fn trap_overflow();
24     fn trap_bounds();
25     fn trap_undefined_opcode();
26     fn trap_dev_not_avaliable();
27     fn trap_double_fault();
28     fn trap_coprocessor_segment_overrun();
29     fn trap_invalid_TSS();
30     fn trap_segment_not_exists();
31     fn trap_stack_segment_fault();
32     fn trap_general_protection();
33     fn trap_page_fault();
34     fn trap_x87_FPU_error();
35     fn trap_alignment_check();
36     fn trap_machine_check();
37     fn trap_SIMD_exception();
38     fn trap_virtualization_exception();
39 }
40 
41 bitflags! {
42     pub struct TrapNr: u64 {
43         const X86_TRAP_DE = 0;
44         const X86_TRAP_DB = 1;
45         const X86_TRAP_NMI = 2;
46         const X86_TRAP_BP = 3;
47         const X86_TRAP_OF = 4;
48         const X86_TRAP_BR = 5;
49         const X86_TRAP_UD = 6;
50         const X86_TRAP_NM = 7;
51         const X86_TRAP_DF = 8;
52         const X86_TRAP_OLD_MF = 9;
53         const X86_TRAP_TS = 10;
54         const X86_TRAP_NP = 11;
55         const X86_TRAP_SS = 12;
56         const X86_TRAP_GP = 13;
57         const X86_TRAP_PF = 14;
58         const X86_TRAP_SPURIOUS = 15;
59         const X86_TRAP_MF = 16;
60         const X86_TRAP_AC = 17;
61         const X86_TRAP_MC = 18;
62         const X86_TRAP_XF = 19;
63         const X86_TRAP_VE = 20;
64         const X86_TRAP_CP = 21;
65         const X86_TRAP_VC = 29;
66         const X86_TRAP_IRET = 32;
67     }
68 
69         pub struct X86PfErrorCode : u32{
70         const X86_PF_PROT = 1 << 0;
71         const X86_PF_WRITE = 1 << 1;
72         const X86_PF_USER = 1 << 2;
73         const X86_PF_RSVD = 1 << 3;
74         const X86_PF_INSTR = 1 << 4;
75         const X86_PF_PK = 1 << 5;
76         const X86_PF_SHSTK = 1 << 6;
77         const X86_PF_SGX = 1 << 15;
78     }
79 }
80 
81 #[inline(never)]
82 pub fn arch_trap_init() -> Result<(), SystemError> {
83     unsafe {
84         set_intr_gate(0, 0, VirtAddr::new(trap_divide_error as usize));
85         set_intr_gate(1, 0, VirtAddr::new(trap_debug as usize));
86         set_intr_gate(2, 0, VirtAddr::new(trap_nmi as usize));
87         set_system_trap_gate(3, 0, VirtAddr::new(trap_int3 as usize));
88         set_system_trap_gate(4, 0, VirtAddr::new(trap_overflow as usize));
89         set_system_trap_gate(5, 0, VirtAddr::new(trap_bounds as usize));
90         set_intr_gate(6, 0, VirtAddr::new(trap_undefined_opcode as usize));
91         set_intr_gate(7, 0, VirtAddr::new(trap_dev_not_avaliable as usize));
92         set_intr_gate(8, 0, VirtAddr::new(trap_double_fault as usize));
93         set_intr_gate(
94             9,
95             0,
96             VirtAddr::new(trap_coprocessor_segment_overrun as usize),
97         );
98         set_intr_gate(10, 0, VirtAddr::new(trap_invalid_TSS as usize));
99         set_intr_gate(11, 0, VirtAddr::new(trap_segment_not_exists as usize));
100         set_intr_gate(12, 0, VirtAddr::new(trap_stack_segment_fault as usize));
101         set_intr_gate(13, 0, VirtAddr::new(trap_general_protection as usize));
102         set_intr_gate(14, 0, VirtAddr::new(trap_page_fault as usize));
103         // 中断号15由Intel保留,不能使用
104         set_intr_gate(16, 0, VirtAddr::new(trap_x87_FPU_error as usize));
105         set_intr_gate(17, 0, VirtAddr::new(trap_alignment_check as usize));
106         set_intr_gate(18, 0, VirtAddr::new(trap_machine_check as usize));
107         set_intr_gate(19, 0, VirtAddr::new(trap_SIMD_exception as usize));
108         set_intr_gate(20, 0, VirtAddr::new(trap_virtualization_exception as usize));
109     }
110     return Ok(());
111 }
112 
113 /// 处理除法错误 0 #DE
114 #[no_mangle]
115 unsafe extern "C" fn do_divide_error(regs: &'static TrapFrame, error_code: u64) {
116     error!(
117         "do_divide_error(0), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
118         error_code,
119         regs.rsp,
120         regs.rip,
121         smp_get_processor_id().data(),
122         ProcessManager::current_pid()
123     );
124     panic!("Divide Error");
125 }
126 
127 /// 处理调试异常 1 #DB
128 #[no_mangle]
129 unsafe extern "C" fn do_debug(regs: &'static mut TrapFrame, error_code: u64) {
130     trace!(
131         "do_debug(1), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
132         error_code,
133         regs.rsp,
134         regs.rip,
135         smp_get_processor_id().data(),
136         ProcessManager::current_pid()
137     );
138     DebugException::handle(regs).unwrap();
139 }
140 
141 /// 处理NMI中断 2 NMI
142 #[no_mangle]
143 unsafe extern "C" fn do_nmi(regs: &'static TrapFrame, error_code: u64) {
144     error!(
145         "do_nmi(2), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
146         error_code,
147         regs.rsp,
148         regs.rip,
149         smp_get_processor_id().data(),
150         ProcessManager::current_pid()
151     );
152     panic!("NMI Interrupt");
153 }
154 
155 /// 处理断点异常 3 #BP
156 #[no_mangle]
157 unsafe extern "C" fn do_int3(regs: &'static mut TrapFrame, error_code: u64) {
158     trace!(
159         "do_int3(3), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
160         error_code,
161         regs.rsp,
162         regs.rip,
163         smp_get_processor_id().data(),
164         ProcessManager::current_pid()
165     );
166     EBreak::handle(regs).unwrap();
167 }
168 
169 /// 处理溢出异常 4 #OF
170 #[no_mangle]
171 unsafe extern "C" fn do_overflow(regs: &'static TrapFrame, error_code: u64) {
172     error!(
173         "do_overflow(4), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
174         error_code,
175         regs.rsp,
176         regs.rip,
177         smp_get_processor_id().data(),
178         ProcessManager::current_pid()
179     );
180     panic!("Overflow Exception");
181 }
182 
183 /// 处理BOUND指令检查异常 5 #BR
184 #[no_mangle]
185 unsafe extern "C" fn do_bounds(regs: &'static TrapFrame, error_code: u64) {
186     error!(
187         "do_bounds(5), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
188         error_code,
189         regs.rsp,
190         regs.rip,
191         smp_get_processor_id().data(),
192         ProcessManager::current_pid()
193     );
194     panic!("Bounds Check");
195 }
196 
197 /// 处理未定义操作码异常 6 #UD
198 #[no_mangle]
199 unsafe extern "C" fn do_undefined_opcode(regs: &'static TrapFrame, error_code: u64) {
200     error!(
201         "do_undefined_opcode(6), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
202         error_code,
203         regs.rsp,
204         regs.rip,
205         smp_get_processor_id().data(),
206         ProcessManager::current_pid()
207     );
208     panic!("Undefined Opcode");
209 }
210 
211 /// 处理设备不可用异常(FPU不存在) 7 #NM
212 #[no_mangle]
213 unsafe extern "C" fn do_dev_not_avaliable(regs: &'static TrapFrame, error_code: u64) {
214     error!(
215         "do_dev_not_avaliable(7), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
216         error_code,
217         regs.rsp,
218         regs.rip,
219         smp_get_processor_id().data(),
220         ProcessManager::current_pid()
221     );
222     panic!("Device Not Available");
223 }
224 
225 /// 处理双重错误 8 #DF
226 #[no_mangle]
227 unsafe extern "C" fn do_double_fault(regs: &'static TrapFrame, error_code: u64) {
228     error!(
229         "do_double_fault(8), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
230         error_code,
231         regs.rsp,
232         regs.rip,
233         smp_get_processor_id().data(),
234         ProcessManager::current_pid()
235     );
236     panic!("Double Fault");
237 }
238 
239 /// 处理协处理器段越界 9 #MF
240 #[no_mangle]
241 unsafe extern "C" fn do_coprocessor_segment_overrun(regs: &'static TrapFrame, error_code: u64) {
242     error!(
243         "do_coprocessor_segment_overrun(9), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
244         error_code,
245         regs.rsp,
246         regs.rip,
247         smp_get_processor_id().data(),
248         ProcessManager::current_pid()
249     );
250     panic!("Coprocessor Segment Overrun");
251 }
252 
253 /// 处理无效TSS 10 #TS
254 #[no_mangle]
255 unsafe extern "C" fn do_invalid_TSS(regs: &'static TrapFrame, error_code: u64) {
256     const ERR_MSG_1: &str =
257         "The exception occurred during delivery of an event external to the program.\n";
258     const ERR_MSG_2: &str = "Refers to a descriptor in the IDT.\n";
259     const ERR_MSG_3: &str = "Refers to a descriptor in the current LDT.\n";
260     const ERR_MSG_4: &str = "Refers to a descriptor in the GDT.\n";
261 
262     let msg1: &str = if (error_code & 0x1) != 0 {
263         ERR_MSG_1
264     } else {
265         ""
266     };
267 
268     let msg2: &str = if (error_code & 0x02) != 0 {
269         ERR_MSG_2
270     } else if (error_code & 0x04) != 0 {
271         ERR_MSG_3
272     } else {
273         ERR_MSG_4
274     };
275 
276     error!(
277         "do_invalid_TSS(10), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}\n{}{}",
278         error_code,
279         regs.rsp,
280         regs.rip,
281         smp_get_processor_id().data(),
282         ProcessManager::current_pid(),
283         msg1,
284         msg2
285     );
286     panic!("Invalid TSS");
287 }
288 
289 /// 处理段不存在 11 #NP
290 #[no_mangle]
291 unsafe extern "C" fn do_segment_not_exists(regs: &'static TrapFrame, error_code: u64) {
292     error!(
293         "do_segment_not_exists(11), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
294         error_code,
295         regs.rsp,
296         regs.rip,
297         smp_get_processor_id().data(),
298         ProcessManager::current_pid()
299     );
300     panic!("Segment Not Exists");
301 }
302 
303 /// 处理栈段错误 12 #SS
304 #[no_mangle]
305 unsafe extern "C" fn do_stack_segment_fault(regs: &'static TrapFrame, error_code: u64) {
306     error!(
307         "do_stack_segment_fault(12), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
308         error_code,
309         regs.rsp,
310         regs.rip,
311         smp_get_processor_id().data(),
312         ProcessManager::current_pid()
313     );
314     panic!("Stack Segment Fault");
315 }
316 
317 /// 处理一般保护异常 13 #GP
318 #[no_mangle]
319 unsafe extern "C" fn do_general_protection(regs: &'static TrapFrame, error_code: u64) {
320     const ERR_MSG_1: &str = "The exception occurred during delivery of an event external to the program, such as an interrupt or an earlier exception.";
321     const ERR_MSG_2: &str = "Refers to a gate descriptor in the IDT;\n";
322     const ERR_MSG_3: &str = "Refers to a descriptor in the GDT or the current LDT;\n";
323     const ERR_MSG_4: &str = "Refers to a segment or gate descriptor in the LDT;\n";
324     const ERR_MSG_5: &str = "Refers to a descriptor in the current GDT;\n";
325 
326     let msg1: &str = if (error_code & 0x1) != 0 {
327         ERR_MSG_1
328     } else {
329         ""
330     };
331 
332     let msg2: &str = if (error_code & 0x02) != 0 {
333         ERR_MSG_2
334     } else {
335         ERR_MSG_3
336     };
337 
338     let msg3: &str = if (error_code & 0x02) == 0 {
339         if (error_code & 0x04) != 0 {
340             ERR_MSG_4
341         } else {
342             ERR_MSG_5
343         }
344     } else {
345         ""
346     };
347     error!(
348         "do_general_protection(13), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t rflags: {:#x}\t CPU: {}, \tpid: {:?}
349 {}{}{}
350 Segment Selector Index: {:#x}\n
351 ",
352         error_code,
353         regs.rsp,
354         regs.rip,
355         regs.rflags,
356         smp_get_processor_id().data(),
357         ProcessManager::current_pid(),
358         msg1, msg2, msg3,
359         error_code & 0xfff8
360     );
361     panic!("General Protection");
362 }
363 
364 /// 处理页错误 14 #PF
365 #[no_mangle]
366 unsafe extern "C" fn do_page_fault(regs: &'static TrapFrame, error_code: u64) {
367     // error!(
368     //     "do_page_fault(14), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}, \nFault Address: {:#x}",
369     //     error_code,
370     //     regs.rsp,
371     //     regs.rip,
372     //     smp_get_processor_id().data(),
373     //     ProcessManager::current_pid(),
374     //     x86::controlregs::cr2()
375     // );
376 
377     // if (error_code & 0x01) == 0 {
378     //     print!("Page Not Present,\t");
379     // }
380     // if (error_code & 0x02) != 0 {
381     //     print!("Write Access,\t");
382     // } else {
383     //     print!("Read Access,\t");
384     // }
385 
386     // if (error_code & 0x04) != 0 {
387     //     print!("Fault in user(3),\t");
388     // } else {
389     //     print!("Fault in supervisor(0,1,2),\t");
390     // }
391 
392     // if (error_code & 0x08) != 0 {
393     //     print!("Reserved bit violation cause fault,\t");
394     // }
395 
396     // if (error_code & 0x10) != 0 {
397     //     print!("Instruction fetch cause fault,\t");
398     // }
399     // print!("\n");
400 
401     // CurrentIrqArch::interrupt_enable();
402     // panic!("Page Fault");
403     CurrentIrqArch::interrupt_disable();
404     let address = x86::controlregs::cr2();
405     // log::info!(
406     //     "fault address: {:#x}, error_code: {:#b}, pid: {}\n",
407     //     address,
408     //     error_code,
409     //     ProcessManager::current_pid().data()
410     // );
411 
412     let address = VirtAddr::new(address);
413     let error_code = X86PfErrorCode::from_bits_truncate(error_code as u32);
414     if address.check_user() {
415         MMArch::do_user_addr_fault(regs, error_code, address);
416     } else {
417         MMArch::do_kern_addr_fault(regs, error_code, address);
418     }
419     CurrentIrqArch::interrupt_enable();
420 }
421 
422 /// 处理x87 FPU错误 16 #MF
423 #[no_mangle]
424 unsafe extern "C" fn do_x87_FPU_error(regs: &'static TrapFrame, error_code: u64) {
425     error!(
426         "do_x87_FPU_error(16), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
427         error_code,
428         regs.rsp,
429         regs.rip,
430         smp_get_processor_id().data(),
431         ProcessManager::current_pid()
432     );
433     panic!("x87 FPU Error");
434 }
435 
436 /// 处理对齐检查 17 #AC
437 #[no_mangle]
438 unsafe extern "C" fn do_alignment_check(regs: &'static TrapFrame, error_code: u64) {
439     error!(
440         "do_alignment_check(17), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
441         error_code,
442         regs.rsp,
443         regs.rip,
444         smp_get_processor_id().data(),
445         ProcessManager::current_pid()
446     );
447     panic!("Alignment Check");
448 }
449 
450 /// 处理机器检查 18 #MC
451 #[no_mangle]
452 unsafe extern "C" fn do_machine_check(regs: &'static TrapFrame, error_code: u64) {
453     error!(
454         "do_machine_check(18), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
455         error_code,
456         regs.rsp,
457         regs.rip,
458         smp_get_processor_id().data(),
459         ProcessManager::current_pid()
460     );
461     panic!("Machine Check");
462 }
463 
464 /// 处理SIMD异常 19 #XM
465 #[no_mangle]
466 unsafe extern "C" fn do_SIMD_exception(regs: &'static TrapFrame, error_code: u64) {
467     error!(
468         "do_SIMD_exception(19), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
469         error_code,
470         regs.rsp,
471         regs.rip,
472         smp_get_processor_id().data(),
473         ProcessManager::current_pid()
474     );
475     panic!("SIMD Exception");
476 }
477 
478 /// 处理虚拟化异常 20 #VE
479 #[no_mangle]
480 unsafe extern "C" fn do_virtualization_exception(regs: &'static TrapFrame, error_code: u64) {
481     error!(
482         "do_virtualization_exception(20), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
483         error_code,
484         regs.rsp,
485         regs.rip,
486         smp_get_processor_id().data(),
487         ProcessManager::current_pid()
488     );
489     panic!("Virtualization Exception");
490 }
491 
492 #[no_mangle]
493 unsafe extern "C" fn ignore_int_handler(_regs: &'static TrapFrame, _error_code: u64) {
494     warn!("Unknown interrupt.");
495 }
496