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