1f2022a8aSLoGin pub(super) mod entry; 2e2841179SLoGin mod handle; 3aa0367d6SLoGin pub mod ipi; 4e2841179SLoGin pub mod msi; 5f2022a8aSLoGin pub mod trap; 6aa0367d6SLoGin 7f678331aShanjiezhou use core::{ 8f678331aShanjiezhou arch::asm, 9f678331aShanjiezhou sync::atomic::{compiler_fence, Ordering}, 10f678331aShanjiezhou }; 11f678331aShanjiezhou 12*2eab6dd7S曾俊 use log::error; 13f2022a8aSLoGin use system_error::SystemError; 14f678331aShanjiezhou 15f2022a8aSLoGin use crate::{ 16f2022a8aSLoGin arch::CurrentIrqArch, 173bc96fa4SLoGin exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber}, 18f2022a8aSLoGin }; 19f2022a8aSLoGin 20f2022a8aSLoGin use super::{ 21f2022a8aSLoGin asm::irqflags::{local_irq_restore, local_irq_save}, 22e2841179SLoGin driver::apic::{lapic_vector::arch_early_irq_init, CurrentApic, LocalAPIC}, 23f2022a8aSLoGin }; 241a2eaa40Slogin 251a2eaa40Slogin /// @brief 关闭中断 261a2eaa40Slogin #[inline] 271a2eaa40Slogin pub fn cli() { 281a2eaa40Slogin unsafe { 291a2eaa40Slogin asm!("cli"); 301a2eaa40Slogin } 311a2eaa40Slogin } 321a2eaa40Slogin 331a2eaa40Slogin /// @brief 开启中断 341a2eaa40Slogin #[inline] 351a2eaa40Slogin pub fn sti() { 361a2eaa40Slogin unsafe { 371a2eaa40Slogin asm!("sti"); 381a2eaa40Slogin } 391a2eaa40Slogin } 40f678331aShanjiezhou 41f678331aShanjiezhou pub struct X86_64InterruptArch; 42f678331aShanjiezhou 43f678331aShanjiezhou impl InterruptArch for X86_64InterruptArch { 44f2022a8aSLoGin #[inline(never)] 45f2022a8aSLoGin unsafe fn arch_irq_init() -> Result<(), SystemError> { 46f2022a8aSLoGin CurrentIrqArch::interrupt_disable(); 47e2841179SLoGin 48f2022a8aSLoGin return Ok(()); 49f2022a8aSLoGin } 50f678331aShanjiezhou unsafe fn interrupt_enable() { 51f678331aShanjiezhou sti(); 52f678331aShanjiezhou } 53f678331aShanjiezhou 54f678331aShanjiezhou unsafe fn interrupt_disable() { 55f678331aShanjiezhou cli(); 56f678331aShanjiezhou } 57f678331aShanjiezhou 58f678331aShanjiezhou fn is_irq_enabled() -> bool { 59f678331aShanjiezhou let rflags: u64; 60f678331aShanjiezhou unsafe { 6140fe15e0SLoGin asm!("pushfq; pop {}", out(reg) rflags, options(nomem, preserves_flags)); 62f678331aShanjiezhou } 63de71ec25SLoGin return (rflags & (1 << 9)) != 0; 64f678331aShanjiezhou } 65f678331aShanjiezhou 66f678331aShanjiezhou unsafe fn save_and_disable_irq() -> IrqFlagsGuard { 67f678331aShanjiezhou compiler_fence(Ordering::SeqCst); 6840fe15e0SLoGin let rflags = local_irq_save(); 69f678331aShanjiezhou let flags = IrqFlags::new(rflags); 70f678331aShanjiezhou let guard = IrqFlagsGuard::new(flags); 71f678331aShanjiezhou compiler_fence(Ordering::SeqCst); 72f678331aShanjiezhou return guard; 73f678331aShanjiezhou } 74f678331aShanjiezhou 75f678331aShanjiezhou unsafe fn restore_irq(flags: IrqFlags) { 76f678331aShanjiezhou compiler_fence(Ordering::SeqCst); 7740fe15e0SLoGin local_irq_restore(flags.flags()); 78f678331aShanjiezhou compiler_fence(Ordering::SeqCst); 79f678331aShanjiezhou } 803bc96fa4SLoGin 813bc96fa4SLoGin fn probe_total_irq_num() -> u32 { 823bc96fa4SLoGin // todo: 从APIC获取 833bc96fa4SLoGin // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c?r=&mo=19514&fi=704#704 843bc96fa4SLoGin 256 853bc96fa4SLoGin } 863bc96fa4SLoGin 873bc96fa4SLoGin fn ack_bad_irq(irq: IrqNumber) { 88*2eab6dd7S曾俊 error!("Unexpected IRQ trap at vector {}", irq.data()); 893bc96fa4SLoGin CurrentApic.send_eoi(); 903bc96fa4SLoGin } 91e2841179SLoGin 92e2841179SLoGin fn arch_early_irq_init() -> Result<(), SystemError> { 93e2841179SLoGin arch_early_irq_init() 94e2841179SLoGin } 958cb2e9b3SLoGin 968cb2e9b3SLoGin fn arch_ap_early_irq_init() -> Result<(), SystemError> { 978cb2e9b3SLoGin if !CurrentApic.init_current_cpu() { 988cb2e9b3SLoGin return Err(SystemError::ENODEV); 998cb2e9b3SLoGin } 1008cb2e9b3SLoGin 1018cb2e9b3SLoGin Ok(()) 1028cb2e9b3SLoGin } 103f678331aShanjiezhou } 1041496ba7bSLoGin 1051496ba7bSLoGin /// 中断栈帧结构体 1061496ba7bSLoGin #[repr(C)] 1071496ba7bSLoGin #[derive(Debug, Copy, Clone)] 1081496ba7bSLoGin pub struct TrapFrame { 1091496ba7bSLoGin pub r15: ::core::ffi::c_ulong, 1101496ba7bSLoGin pub r14: ::core::ffi::c_ulong, 1111496ba7bSLoGin pub r13: ::core::ffi::c_ulong, 1121496ba7bSLoGin pub r12: ::core::ffi::c_ulong, 1131496ba7bSLoGin pub r11: ::core::ffi::c_ulong, 1141496ba7bSLoGin pub r10: ::core::ffi::c_ulong, 1151496ba7bSLoGin pub r9: ::core::ffi::c_ulong, 1161496ba7bSLoGin pub r8: ::core::ffi::c_ulong, 1171496ba7bSLoGin pub rbx: ::core::ffi::c_ulong, 1181496ba7bSLoGin pub rcx: ::core::ffi::c_ulong, 1191496ba7bSLoGin pub rdx: ::core::ffi::c_ulong, 1201496ba7bSLoGin pub rsi: ::core::ffi::c_ulong, 1211496ba7bSLoGin pub rdi: ::core::ffi::c_ulong, 1221496ba7bSLoGin pub rbp: ::core::ffi::c_ulong, 1231496ba7bSLoGin pub ds: ::core::ffi::c_ulong, 1241496ba7bSLoGin pub es: ::core::ffi::c_ulong, 1251496ba7bSLoGin pub rax: ::core::ffi::c_ulong, 1261496ba7bSLoGin pub func: ::core::ffi::c_ulong, 1271496ba7bSLoGin pub errcode: ::core::ffi::c_ulong, 1281496ba7bSLoGin pub rip: ::core::ffi::c_ulong, 1291496ba7bSLoGin pub cs: ::core::ffi::c_ulong, 1301496ba7bSLoGin pub rflags: ::core::ffi::c_ulong, 1311496ba7bSLoGin pub rsp: ::core::ffi::c_ulong, 1321496ba7bSLoGin pub ss: ::core::ffi::c_ulong, 1331496ba7bSLoGin } 1341496ba7bSLoGin 1351496ba7bSLoGin impl TrapFrame { 1361496ba7bSLoGin pub fn new() -> Self { 1371496ba7bSLoGin Self { 1381496ba7bSLoGin r15: 0, 1391496ba7bSLoGin r14: 0, 1401496ba7bSLoGin r13: 0, 1411496ba7bSLoGin r12: 0, 1421496ba7bSLoGin r11: 0, 1431496ba7bSLoGin r10: 0, 1441496ba7bSLoGin r9: 0, 1451496ba7bSLoGin r8: 0, 1461496ba7bSLoGin rbx: 0, 1471496ba7bSLoGin rcx: 0, 1481496ba7bSLoGin rdx: 0, 1491496ba7bSLoGin rsi: 0, 1501496ba7bSLoGin rdi: 0, 1511496ba7bSLoGin rbp: 0, 1521496ba7bSLoGin ds: 0, 1531496ba7bSLoGin es: 0, 1541496ba7bSLoGin rax: 0, 1551496ba7bSLoGin func: 0, 1561496ba7bSLoGin errcode: 0, 1571496ba7bSLoGin rip: 0, 1581496ba7bSLoGin cs: 0, 1591496ba7bSLoGin rflags: 0, 1601496ba7bSLoGin rsp: 0, 1611496ba7bSLoGin ss: 0, 1621496ba7bSLoGin } 1631496ba7bSLoGin } 1641496ba7bSLoGin 1651496ba7bSLoGin /// 设置中断栈帧返回值 1661496ba7bSLoGin pub fn set_return_value(&mut self, value: usize) { 1671496ba7bSLoGin self.rax = value as u64; 1681496ba7bSLoGin } 1691496ba7bSLoGin 1701496ba7bSLoGin /// 判断当前中断是否来自用户模式 171b5b571e0SLoGin pub fn is_from_user(&self) -> bool { 172b5b571e0SLoGin return (self.cs & 0x3) != 0; 1731496ba7bSLoGin } 1741496ba7bSLoGin } 175