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]
cli()27 pub fn cli() {
28 unsafe {
29 asm!("cli");
30 }
31 }
32
33 /// @brief 开启中断
34 #[inline]
sti()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)]
arch_irq_init() -> Result<(), SystemError>45 unsafe fn arch_irq_init() -> Result<(), SystemError> {
46 CurrentIrqArch::interrupt_disable();
47
48 return Ok(());
49 }
interrupt_enable()50 unsafe fn interrupt_enable() {
51 sti();
52 }
53
interrupt_disable()54 unsafe fn interrupt_disable() {
55 cli();
56 }
57
is_irq_enabled() -> bool58 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
save_and_disable_irq() -> IrqFlagsGuard66 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
restore_irq(flags: IrqFlags)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
probe_total_irq_num() -> u3281 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
ack_bad_irq(irq: IrqNumber)87 fn ack_bad_irq(irq: IrqNumber) {
88 error!("Unexpected IRQ trap at vector {}", irq.data());
89 CurrentApic.send_eoi();
90 }
91
arch_early_irq_init() -> Result<(), SystemError>92 fn arch_early_irq_init() -> Result<(), SystemError> {
93 arch_early_irq_init()
94 }
95
arch_ap_early_irq_init() -> Result<(), SystemError>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 Default for TrapFrame {
default() -> Self136 fn default() -> Self {
137 Self::new()
138 }
139 }
140
141 impl TrapFrame {
new() -> Self142 pub fn new() -> Self {
143 Self {
144 r15: 0,
145 r14: 0,
146 r13: 0,
147 r12: 0,
148 r11: 0,
149 r10: 0,
150 r9: 0,
151 r8: 0,
152 rbx: 0,
153 rcx: 0,
154 rdx: 0,
155 rsi: 0,
156 rdi: 0,
157 rbp: 0,
158 ds: 0,
159 es: 0,
160 rax: 0,
161 func: 0,
162 errcode: 0,
163 rip: 0,
164 cs: 0,
165 rflags: 0,
166 rsp: 0,
167 ss: 0,
168 }
169 }
170
171 /// 设置中断栈帧返回值
set_return_value(&mut self, value: usize)172 pub fn set_return_value(&mut self, value: usize) {
173 self.rax = value as u64;
174 }
175
176 /// 判断当前中断是否来自用户模式
is_from_user(&self) -> bool177 pub fn is_from_user(&self) -> bool {
178 return (self.cs & 0x3) != 0;
179 }
180 }
181