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