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