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