xref: /DragonOS/kernel/src/arch/x86_64/interrupt/mod.rs (revision b5b571e02693d91eb6918d3b7561e088c3e7ee81)
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 
12f2022a8aSLoGin use system_error::SystemError;
13f678331aShanjiezhou 
14f2022a8aSLoGin use crate::{
15f2022a8aSLoGin     arch::CurrentIrqArch,
163bc96fa4SLoGin     exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
173bc96fa4SLoGin     kerror,
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) {
883bc96fa4SLoGin         kerror!("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     /// 判断当前中断是否来自用户模式
171*b5b571e0SLoGin     pub fn is_from_user(&self) -> bool {
172*b5b571e0SLoGin         return (self.cs & 0x3) != 0;
1731496ba7bSLoGin     }
1741496ba7bSLoGin }
175