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