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