xref: /DragonOS/kernel/src/arch/x86_64/interrupt/mod.rs (revision f3b05a97ec061e766247b18dc12e2a413b977b14)
1 mod c_adapter;
2 pub(super) mod entry;
3 mod handle;
4 pub mod ipi;
5 pub mod msi;
6 pub mod trap;
7 
8 use core::{
9     arch::asm,
10     sync::atomic::{compiler_fence, Ordering},
11 };
12 
13 use system_error::SystemError;
14 
15 use crate::{
16     arch::CurrentIrqArch,
17     exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
18     kerror,
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]
28 pub fn cli() {
29     unsafe {
30         asm!("cli");
31     }
32 }
33 
34 /// @brief 开启中断
35 #[inline]
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)]
46     unsafe fn arch_irq_init() -> Result<(), SystemError> {
47         CurrentIrqArch::interrupt_disable();
48 
49         return Ok(());
50     }
51     unsafe fn interrupt_enable() {
52         sti();
53     }
54 
55     unsafe fn interrupt_disable() {
56         cli();
57     }
58 
59     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 
67     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 
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 
82     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 
88     fn ack_bad_irq(irq: IrqNumber) {
89         kerror!("Unexpected IRQ trap at vector {}", irq.data());
90         CurrentApic.send_eoi();
91     }
92 
93     fn arch_early_irq_init() -> Result<(), SystemError> {
94         arch_early_irq_init()
95     }
96 }
97 
98 /// 中断栈帧结构体
99 #[repr(C)]
100 #[derive(Debug, Copy, Clone)]
101 pub struct TrapFrame {
102     pub r15: ::core::ffi::c_ulong,
103     pub r14: ::core::ffi::c_ulong,
104     pub r13: ::core::ffi::c_ulong,
105     pub r12: ::core::ffi::c_ulong,
106     pub r11: ::core::ffi::c_ulong,
107     pub r10: ::core::ffi::c_ulong,
108     pub r9: ::core::ffi::c_ulong,
109     pub r8: ::core::ffi::c_ulong,
110     pub rbx: ::core::ffi::c_ulong,
111     pub rcx: ::core::ffi::c_ulong,
112     pub rdx: ::core::ffi::c_ulong,
113     pub rsi: ::core::ffi::c_ulong,
114     pub rdi: ::core::ffi::c_ulong,
115     pub rbp: ::core::ffi::c_ulong,
116     pub ds: ::core::ffi::c_ulong,
117     pub es: ::core::ffi::c_ulong,
118     pub rax: ::core::ffi::c_ulong,
119     pub func: ::core::ffi::c_ulong,
120     pub errcode: ::core::ffi::c_ulong,
121     pub rip: ::core::ffi::c_ulong,
122     pub cs: ::core::ffi::c_ulong,
123     pub rflags: ::core::ffi::c_ulong,
124     pub rsp: ::core::ffi::c_ulong,
125     pub ss: ::core::ffi::c_ulong,
126 }
127 
128 impl TrapFrame {
129     pub fn new() -> Self {
130         Self {
131             r15: 0,
132             r14: 0,
133             r13: 0,
134             r12: 0,
135             r11: 0,
136             r10: 0,
137             r9: 0,
138             r8: 0,
139             rbx: 0,
140             rcx: 0,
141             rdx: 0,
142             rsi: 0,
143             rdi: 0,
144             rbp: 0,
145             ds: 0,
146             es: 0,
147             rax: 0,
148             func: 0,
149             errcode: 0,
150             rip: 0,
151             cs: 0,
152             rflags: 0,
153             rsp: 0,
154             ss: 0,
155         }
156     }
157 
158     /// 设置中断栈帧返回值
159     pub fn set_return_value(&mut self, value: usize) {
160         self.rax = value as u64;
161     }
162 
163     /// 判断当前中断是否来自用户模式
164     pub fn from_user(&self) -> bool {
165         if (self.cs & 0x3) != 0 {
166             return true;
167         } else {
168             return false;
169         }
170     }
171 }
172