xref: /DragonOS/kernel/src/arch/x86_64/interrupt/mod.rs (revision 3bc96fa4a9c01d91cddeb152fe78d6408351c29f)
170a4e555SLoGin mod c_adapter;
2f2022a8aSLoGin pub(super) mod entry;
3aa0367d6SLoGin pub mod ipi;
4f2022a8aSLoGin pub mod trap;
5aa0367d6SLoGin 
6f678331aShanjiezhou use core::{
7f678331aShanjiezhou     arch::asm,
8f678331aShanjiezhou     sync::atomic::{compiler_fence, Ordering},
9f678331aShanjiezhou };
10f678331aShanjiezhou 
11f2022a8aSLoGin use system_error::SystemError;
12f678331aShanjiezhou 
13f2022a8aSLoGin use crate::{
14f2022a8aSLoGin     arch::CurrentIrqArch,
15*3bc96fa4SLoGin     exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
16*3bc96fa4SLoGin     kerror,
17f2022a8aSLoGin };
18f2022a8aSLoGin 
19f2022a8aSLoGin use self::entry::setup_interrupt_gate;
20f2022a8aSLoGin 
21f2022a8aSLoGin use super::{
22f2022a8aSLoGin     asm::irqflags::{local_irq_restore, local_irq_save},
23f2022a8aSLoGin     driver::apic::{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();
48f2022a8aSLoGin         setup_interrupt_gate();
49f2022a8aSLoGin         CurrentApic.init_current_cpu();
50f2022a8aSLoGin         return Ok(());
51f2022a8aSLoGin     }
52f678331aShanjiezhou     unsafe fn interrupt_enable() {
53f678331aShanjiezhou         sti();
54f678331aShanjiezhou     }
55f678331aShanjiezhou 
56f678331aShanjiezhou     unsafe fn interrupt_disable() {
57f678331aShanjiezhou         cli();
58f678331aShanjiezhou     }
59f678331aShanjiezhou 
60f678331aShanjiezhou     fn is_irq_enabled() -> bool {
61f678331aShanjiezhou         let rflags: u64;
62f678331aShanjiezhou         unsafe {
6340fe15e0SLoGin             asm!("pushfq; pop {}", out(reg) rflags, options(nomem, preserves_flags));
64f678331aShanjiezhou         }
65de71ec25SLoGin         return (rflags & (1 << 9)) != 0;
66f678331aShanjiezhou     }
67f678331aShanjiezhou 
68f678331aShanjiezhou     unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
69f678331aShanjiezhou         compiler_fence(Ordering::SeqCst);
7040fe15e0SLoGin         let rflags = local_irq_save();
71f678331aShanjiezhou         let flags = IrqFlags::new(rflags);
72f678331aShanjiezhou         let guard = IrqFlagsGuard::new(flags);
73f678331aShanjiezhou         compiler_fence(Ordering::SeqCst);
74f678331aShanjiezhou         return guard;
75f678331aShanjiezhou     }
76f678331aShanjiezhou 
77f678331aShanjiezhou     unsafe fn restore_irq(flags: IrqFlags) {
78f678331aShanjiezhou         compiler_fence(Ordering::SeqCst);
7940fe15e0SLoGin         local_irq_restore(flags.flags());
80f678331aShanjiezhou         compiler_fence(Ordering::SeqCst);
81f678331aShanjiezhou     }
82*3bc96fa4SLoGin 
83*3bc96fa4SLoGin     fn probe_total_irq_num() -> u32 {
84*3bc96fa4SLoGin         // todo: 从APIC获取
85*3bc96fa4SLoGin         // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c?r=&mo=19514&fi=704#704
86*3bc96fa4SLoGin         256
87*3bc96fa4SLoGin     }
88*3bc96fa4SLoGin 
89*3bc96fa4SLoGin     fn ack_bad_irq(irq: IrqNumber) {
90*3bc96fa4SLoGin         kerror!("Unexpected IRQ trap at vector {}", irq.data());
91*3bc96fa4SLoGin         CurrentApic.send_eoi();
92*3bc96fa4SLoGin     }
93f678331aShanjiezhou }
941496ba7bSLoGin 
951496ba7bSLoGin /// 中断栈帧结构体
961496ba7bSLoGin #[repr(C)]
971496ba7bSLoGin #[derive(Debug, Copy, Clone)]
981496ba7bSLoGin pub struct TrapFrame {
991496ba7bSLoGin     pub r15: ::core::ffi::c_ulong,
1001496ba7bSLoGin     pub r14: ::core::ffi::c_ulong,
1011496ba7bSLoGin     pub r13: ::core::ffi::c_ulong,
1021496ba7bSLoGin     pub r12: ::core::ffi::c_ulong,
1031496ba7bSLoGin     pub r11: ::core::ffi::c_ulong,
1041496ba7bSLoGin     pub r10: ::core::ffi::c_ulong,
1051496ba7bSLoGin     pub r9: ::core::ffi::c_ulong,
1061496ba7bSLoGin     pub r8: ::core::ffi::c_ulong,
1071496ba7bSLoGin     pub rbx: ::core::ffi::c_ulong,
1081496ba7bSLoGin     pub rcx: ::core::ffi::c_ulong,
1091496ba7bSLoGin     pub rdx: ::core::ffi::c_ulong,
1101496ba7bSLoGin     pub rsi: ::core::ffi::c_ulong,
1111496ba7bSLoGin     pub rdi: ::core::ffi::c_ulong,
1121496ba7bSLoGin     pub rbp: ::core::ffi::c_ulong,
1131496ba7bSLoGin     pub ds: ::core::ffi::c_ulong,
1141496ba7bSLoGin     pub es: ::core::ffi::c_ulong,
1151496ba7bSLoGin     pub rax: ::core::ffi::c_ulong,
1161496ba7bSLoGin     pub func: ::core::ffi::c_ulong,
1171496ba7bSLoGin     pub errcode: ::core::ffi::c_ulong,
1181496ba7bSLoGin     pub rip: ::core::ffi::c_ulong,
1191496ba7bSLoGin     pub cs: ::core::ffi::c_ulong,
1201496ba7bSLoGin     pub rflags: ::core::ffi::c_ulong,
1211496ba7bSLoGin     pub rsp: ::core::ffi::c_ulong,
1221496ba7bSLoGin     pub ss: ::core::ffi::c_ulong,
1231496ba7bSLoGin }
1241496ba7bSLoGin 
1251496ba7bSLoGin impl TrapFrame {
1261496ba7bSLoGin     pub fn new() -> Self {
1271496ba7bSLoGin         Self {
1281496ba7bSLoGin             r15: 0,
1291496ba7bSLoGin             r14: 0,
1301496ba7bSLoGin             r13: 0,
1311496ba7bSLoGin             r12: 0,
1321496ba7bSLoGin             r11: 0,
1331496ba7bSLoGin             r10: 0,
1341496ba7bSLoGin             r9: 0,
1351496ba7bSLoGin             r8: 0,
1361496ba7bSLoGin             rbx: 0,
1371496ba7bSLoGin             rcx: 0,
1381496ba7bSLoGin             rdx: 0,
1391496ba7bSLoGin             rsi: 0,
1401496ba7bSLoGin             rdi: 0,
1411496ba7bSLoGin             rbp: 0,
1421496ba7bSLoGin             ds: 0,
1431496ba7bSLoGin             es: 0,
1441496ba7bSLoGin             rax: 0,
1451496ba7bSLoGin             func: 0,
1461496ba7bSLoGin             errcode: 0,
1471496ba7bSLoGin             rip: 0,
1481496ba7bSLoGin             cs: 0,
1491496ba7bSLoGin             rflags: 0,
1501496ba7bSLoGin             rsp: 0,
1511496ba7bSLoGin             ss: 0,
1521496ba7bSLoGin         }
1531496ba7bSLoGin     }
1541496ba7bSLoGin 
1551496ba7bSLoGin     /// 设置中断栈帧返回值
1561496ba7bSLoGin     pub fn set_return_value(&mut self, value: usize) {
1571496ba7bSLoGin         self.rax = value as u64;
1581496ba7bSLoGin     }
1591496ba7bSLoGin 
1601496ba7bSLoGin     /// 判断当前中断是否来自用户模式
1611496ba7bSLoGin     pub fn from_user(&self) -> bool {
1621496ba7bSLoGin         if (self.cs & 0x3) != 0 {
1631496ba7bSLoGin             return true;
1641496ba7bSLoGin         } else {
1651496ba7bSLoGin             return false;
1661496ba7bSLoGin         }
1671496ba7bSLoGin     }
1681496ba7bSLoGin }
169