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