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