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" {
trap_divide_error()19 fn trap_divide_error();
trap_debug()20 fn trap_debug();
trap_nmi()21 fn trap_nmi();
trap_int3()22 fn trap_int3();
trap_overflow()23 fn trap_overflow();
trap_bounds()24 fn trap_bounds();
trap_undefined_opcode()25 fn trap_undefined_opcode();
trap_dev_not_avaliable()26 fn trap_dev_not_avaliable();
trap_double_fault()27 fn trap_double_fault();
trap_coprocessor_segment_overrun()28 fn trap_coprocessor_segment_overrun();
trap_invalid_TSS()29 fn trap_invalid_TSS();
trap_segment_not_exists()30 fn trap_segment_not_exists();
trap_stack_segment_fault()31 fn trap_stack_segment_fault();
trap_general_protection()32 fn trap_general_protection();
trap_page_fault()33 fn trap_page_fault();
trap_x87_FPU_error()34 fn trap_x87_FPU_error();
trap_alignment_check()35 fn trap_alignment_check();
trap_machine_check()36 fn trap_machine_check();
trap_SIMD_exception()37 fn trap_SIMD_exception();
trap_virtualization_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)]
arch_trap_init() -> Result<(), SystemError>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]
do_divide_error(regs: &'static TrapFrame, error_code: u64)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]
do_debug(regs: &'static mut TrapFrame, error_code: u64)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]
do_nmi(regs: &'static TrapFrame, error_code: u64)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]
do_int3(regs: &'static mut TrapFrame, error_code: u64)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]
do_overflow(regs: &'static TrapFrame, error_code: u64)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]
do_bounds(regs: &'static TrapFrame, error_code: u64)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]
do_undefined_opcode(regs: &'static TrapFrame, error_code: u64)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]
do_dev_not_avaliable(regs: &'static TrapFrame, error_code: u64)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]
do_double_fault(regs: &'static TrapFrame, error_code: u64)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]
do_coprocessor_segment_overrun(regs: &'static TrapFrame, error_code: u64)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]
do_invalid_TSS(regs: &'static TrapFrame, error_code: u64)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]
do_segment_not_exists(regs: &'static TrapFrame, error_code: u64)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]
do_stack_segment_fault(regs: &'static TrapFrame, error_code: u64)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]
do_general_protection(regs: &'static TrapFrame, error_code: u64)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]
do_page_fault(regs: &'static TrapFrame, error_code: u64)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]
do_x87_FPU_error(regs: &'static TrapFrame, error_code: u64)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]
do_alignment_check(regs: &'static TrapFrame, error_code: u64)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]
do_machine_check(regs: &'static TrapFrame, error_code: u64)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]
do_SIMD_exception(regs: &'static TrapFrame, error_code: u64)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]
do_virtualization_exception(regs: &'static TrapFrame, error_code: u64)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]
ignore_int_handler(_regs: &'static TrapFrame, _error_code: u64)493 unsafe extern "C" fn ignore_int_handler(_regs: &'static TrapFrame, _error_code: u64) {
494 warn!("Unknown interrupt.");
495 }
496