xref: /DragonOS/kernel/src/arch/x86_64/interrupt/handle.rs (revision e28411791f090c421fe4b6fa5956fb1bd362a8d9) !
1 use core::intrinsics::likely;
2 
3 use crate::{
4     arch::{
5         driver::apic::{apic_timer::APIC_TIMER_IRQ_NUM, CurrentApic, LocalAPIC},
6         sched::sched,
7     },
8     exception::{irqdesc::irq_desc_manager, softirq::do_softirq, IrqNumber},
9     process::{
10         process::{current_pcb_flags, current_pcb_preempt_count},
11         ProcessFlags,
12     },
13 };
14 
15 use super::TrapFrame;
16 
17 #[no_mangle]
18 unsafe extern "C" fn x86_64_do_irq(trap_frame: &mut TrapFrame, vector: u32) {
19     // swapgs
20 
21     if trap_frame.from_user() {
22         x86_64::registers::segmentation::GS::swap();
23         // 拒绝用户态中断
24         return;
25     }
26 
27     // 由于x86上面,虚拟中断号与物理中断号是一一对应的,所以这里直接使用vector作为中断号来查询irqdesc
28 
29     let desc = irq_desc_manager().lookup(IrqNumber::new(vector));
30 
31     if likely(desc.is_some()) {
32         let desc = desc.unwrap();
33         let handler = desc.handler();
34         if likely(handler.is_some()) {
35             handler.unwrap().handle(&desc, trap_frame);
36         } else {
37             CurrentApic.send_eoi();
38         }
39     } else {
40         CurrentApic.send_eoi();
41     }
42 
43     do_softirq();
44 
45     if current_pcb_preempt_count() > 0 {
46         return;
47     }
48     // 检测当前进程是否可被调度
49     if (current_pcb_flags().contains(ProcessFlags::NEED_SCHEDULE))
50         && vector == APIC_TIMER_IRQ_NUM.data()
51     {
52         sched();
53     }
54 }
55