1 pub(super) mod entry; 2 mod handle; 3 pub mod ipi; 4 pub mod msi; 5 pub mod trap; 6 7 use core::any::Any; 8 use core::{ 9 arch::asm, 10 sync::atomic::{compiler_fence, Ordering}, 11 }; 12 use kprobe::ProbeArgs; 13 use log::error; 14 use system_error::SystemError; 15 16 use crate::{ 17 arch::CurrentIrqArch, 18 exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber}, 19 }; 20 21 use super::{ 22 asm::irqflags::{local_irq_restore, local_irq_save}, 23 driver::apic::{lapic_vector::arch_early_irq_init, CurrentApic, LocalAPIC}, 24 }; 25 26 /// @brief 关闭中断 27 #[inline] 28 pub fn cli() { 29 unsafe { 30 asm!("cli"); 31 } 32 } 33 34 /// @brief 开启中断 35 #[inline] 36 pub fn sti() { 37 unsafe { 38 asm!("sti"); 39 } 40 } 41 42 pub struct X86_64InterruptArch; 43 44 impl InterruptArch for X86_64InterruptArch { 45 #[inline(never)] 46 unsafe fn arch_irq_init() -> Result<(), SystemError> { 47 CurrentIrqArch::interrupt_disable(); 48 49 return Ok(()); 50 } 51 unsafe fn interrupt_enable() { 52 sti(); 53 } 54 55 unsafe fn interrupt_disable() { 56 cli(); 57 } 58 59 fn is_irq_enabled() -> bool { 60 let rflags: u64; 61 unsafe { 62 asm!("pushfq; pop {}", out(reg) rflags, options(nomem, preserves_flags)); 63 } 64 return (rflags & (1 << 9)) != 0; 65 } 66 67 unsafe fn save_and_disable_irq() -> IrqFlagsGuard { 68 compiler_fence(Ordering::SeqCst); 69 let rflags = local_irq_save(); 70 let flags = IrqFlags::new(rflags); 71 let guard = IrqFlagsGuard::new(flags); 72 compiler_fence(Ordering::SeqCst); 73 return guard; 74 } 75 76 unsafe fn restore_irq(flags: IrqFlags) { 77 compiler_fence(Ordering::SeqCst); 78 local_irq_restore(flags.flags()); 79 compiler_fence(Ordering::SeqCst); 80 } 81 82 fn probe_total_irq_num() -> u32 { 83 // todo: 从APIC获取 84 // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c?r=&mo=19514&fi=704#704 85 256 86 } 87 88 fn ack_bad_irq(irq: IrqNumber) { 89 error!("Unexpected IRQ trap at vector {}", irq.data()); 90 CurrentApic.send_eoi(); 91 } 92 93 fn arch_early_irq_init() -> Result<(), SystemError> { 94 arch_early_irq_init() 95 } 96 97 fn arch_ap_early_irq_init() -> Result<(), SystemError> { 98 if !CurrentApic.init_current_cpu() { 99 return Err(SystemError::ENODEV); 100 } 101 102 Ok(()) 103 } 104 } 105 106 /// 中断栈帧结构体 107 #[repr(C)] 108 #[derive(Debug, Copy, Clone)] 109 pub struct TrapFrame { 110 pub r15: ::core::ffi::c_ulong, 111 pub r14: ::core::ffi::c_ulong, 112 pub r13: ::core::ffi::c_ulong, 113 pub r12: ::core::ffi::c_ulong, 114 pub r11: ::core::ffi::c_ulong, 115 pub r10: ::core::ffi::c_ulong, 116 pub r9: ::core::ffi::c_ulong, 117 pub r8: ::core::ffi::c_ulong, 118 pub rbx: ::core::ffi::c_ulong, 119 pub rcx: ::core::ffi::c_ulong, 120 pub rdx: ::core::ffi::c_ulong, 121 pub rsi: ::core::ffi::c_ulong, 122 pub rdi: ::core::ffi::c_ulong, 123 pub rbp: ::core::ffi::c_ulong, 124 pub ds: ::core::ffi::c_ulong, 125 pub es: ::core::ffi::c_ulong, 126 pub rax: ::core::ffi::c_ulong, 127 pub func: ::core::ffi::c_ulong, 128 pub errcode: ::core::ffi::c_ulong, 129 pub rip: ::core::ffi::c_ulong, 130 pub cs: ::core::ffi::c_ulong, 131 pub rflags: ::core::ffi::c_ulong, 132 pub rsp: ::core::ffi::c_ulong, 133 pub ss: ::core::ffi::c_ulong, 134 } 135 136 impl Default for TrapFrame { 137 fn default() -> Self { 138 Self::new() 139 } 140 } 141 142 impl TrapFrame { 143 pub fn new() -> Self { 144 Self { 145 r15: 0, 146 r14: 0, 147 r13: 0, 148 r12: 0, 149 r11: 0, 150 r10: 0, 151 r9: 0, 152 r8: 0, 153 rbx: 0, 154 rcx: 0, 155 rdx: 0, 156 rsi: 0, 157 rdi: 0, 158 rbp: 0, 159 ds: 0, 160 es: 0, 161 rax: 0, 162 func: 0, 163 errcode: 0, 164 rip: 0, 165 cs: 0, 166 rflags: 0, 167 rsp: 0, 168 ss: 0, 169 } 170 } 171 172 /// 设置中断栈帧返回值 173 pub fn set_return_value(&mut self, value: usize) { 174 self.rax = value as u64; 175 } 176 177 /// 判断当前中断是否来自用户模式 178 pub fn is_from_user(&self) -> bool { 179 return (self.cs & 0x3) != 0; 180 } 181 /// 设置当前的程序计数器 182 pub fn set_pc(&mut self, pc: usize) { 183 self.rip = pc as u64; 184 } 185 } 186 187 impl ProbeArgs for TrapFrame { 188 fn as_any(&self) -> &dyn Any { 189 self 190 } 191 fn break_address(&self) -> usize { 192 (self.rip - 1) as usize 193 } 194 195 fn debug_address(&self) -> usize { 196 self.rip as usize 197 } 198 } 199