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