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