mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-10 08:06:48 +00:00
175 lines
4.0 KiB
Rust
175 lines
4.0 KiB
Rust
pub(super) mod entry;
|
|
mod handle;
|
|
pub mod ipi;
|
|
pub mod msi;
|
|
pub mod trap;
|
|
|
|
use core::{
|
|
arch::asm,
|
|
sync::atomic::{compiler_fence, Ordering},
|
|
};
|
|
|
|
use log::error;
|
|
use system_error::SystemError;
|
|
|
|
use crate::{
|
|
arch::CurrentIrqArch,
|
|
exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
|
|
};
|
|
|
|
use super::{
|
|
asm::irqflags::{local_irq_restore, local_irq_save},
|
|
driver::apic::{lapic_vector::arch_early_irq_init, CurrentApic, LocalAPIC},
|
|
};
|
|
|
|
/// @brief 关闭中断
|
|
#[inline]
|
|
pub fn cli() {
|
|
unsafe {
|
|
asm!("cli");
|
|
}
|
|
}
|
|
|
|
/// @brief 开启中断
|
|
#[inline]
|
|
pub fn sti() {
|
|
unsafe {
|
|
asm!("sti");
|
|
}
|
|
}
|
|
|
|
pub struct X86_64InterruptArch;
|
|
|
|
impl InterruptArch for X86_64InterruptArch {
|
|
#[inline(never)]
|
|
unsafe fn arch_irq_init() -> Result<(), SystemError> {
|
|
CurrentIrqArch::interrupt_disable();
|
|
|
|
return Ok(());
|
|
}
|
|
unsafe fn interrupt_enable() {
|
|
sti();
|
|
}
|
|
|
|
unsafe fn interrupt_disable() {
|
|
cli();
|
|
}
|
|
|
|
fn is_irq_enabled() -> bool {
|
|
let rflags: u64;
|
|
unsafe {
|
|
asm!("pushfq; pop {}", out(reg) rflags, options(nomem, preserves_flags));
|
|
}
|
|
return (rflags & (1 << 9)) != 0;
|
|
}
|
|
|
|
unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
|
|
compiler_fence(Ordering::SeqCst);
|
|
let rflags = local_irq_save();
|
|
let flags = IrqFlags::new(rflags);
|
|
let guard = IrqFlagsGuard::new(flags);
|
|
compiler_fence(Ordering::SeqCst);
|
|
return guard;
|
|
}
|
|
|
|
unsafe fn restore_irq(flags: IrqFlags) {
|
|
compiler_fence(Ordering::SeqCst);
|
|
local_irq_restore(flags.flags());
|
|
compiler_fence(Ordering::SeqCst);
|
|
}
|
|
|
|
fn probe_total_irq_num() -> u32 {
|
|
// todo: 从APIC获取
|
|
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c?r=&mo=19514&fi=704#704
|
|
256
|
|
}
|
|
|
|
fn ack_bad_irq(irq: IrqNumber) {
|
|
error!("Unexpected IRQ trap at vector {}", irq.data());
|
|
CurrentApic.send_eoi();
|
|
}
|
|
|
|
fn arch_early_irq_init() -> Result<(), SystemError> {
|
|
arch_early_irq_init()
|
|
}
|
|
|
|
fn arch_ap_early_irq_init() -> Result<(), SystemError> {
|
|
if !CurrentApic.init_current_cpu() {
|
|
return Err(SystemError::ENODEV);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// 中断栈帧结构体
|
|
#[repr(C)]
|
|
#[derive(Debug, Copy, Clone)]
|
|
pub struct TrapFrame {
|
|
pub r15: ::core::ffi::c_ulong,
|
|
pub r14: ::core::ffi::c_ulong,
|
|
pub r13: ::core::ffi::c_ulong,
|
|
pub r12: ::core::ffi::c_ulong,
|
|
pub r11: ::core::ffi::c_ulong,
|
|
pub r10: ::core::ffi::c_ulong,
|
|
pub r9: ::core::ffi::c_ulong,
|
|
pub r8: ::core::ffi::c_ulong,
|
|
pub rbx: ::core::ffi::c_ulong,
|
|
pub rcx: ::core::ffi::c_ulong,
|
|
pub rdx: ::core::ffi::c_ulong,
|
|
pub rsi: ::core::ffi::c_ulong,
|
|
pub rdi: ::core::ffi::c_ulong,
|
|
pub rbp: ::core::ffi::c_ulong,
|
|
pub ds: ::core::ffi::c_ulong,
|
|
pub es: ::core::ffi::c_ulong,
|
|
pub rax: ::core::ffi::c_ulong,
|
|
pub func: ::core::ffi::c_ulong,
|
|
pub errcode: ::core::ffi::c_ulong,
|
|
pub rip: ::core::ffi::c_ulong,
|
|
pub cs: ::core::ffi::c_ulong,
|
|
pub rflags: ::core::ffi::c_ulong,
|
|
pub rsp: ::core::ffi::c_ulong,
|
|
pub ss: ::core::ffi::c_ulong,
|
|
}
|
|
|
|
impl TrapFrame {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
r15: 0,
|
|
r14: 0,
|
|
r13: 0,
|
|
r12: 0,
|
|
r11: 0,
|
|
r10: 0,
|
|
r9: 0,
|
|
r8: 0,
|
|
rbx: 0,
|
|
rcx: 0,
|
|
rdx: 0,
|
|
rsi: 0,
|
|
rdi: 0,
|
|
rbp: 0,
|
|
ds: 0,
|
|
es: 0,
|
|
rax: 0,
|
|
func: 0,
|
|
errcode: 0,
|
|
rip: 0,
|
|
cs: 0,
|
|
rflags: 0,
|
|
rsp: 0,
|
|
ss: 0,
|
|
}
|
|
}
|
|
|
|
/// 设置中断栈帧返回值
|
|
pub fn set_return_value(&mut self, value: usize) {
|
|
self.rax = value as u64;
|
|
}
|
|
|
|
/// 判断当前中断是否来自用户模式
|
|
pub fn is_from_user(&self) -> bool {
|
|
return (self.cs & 0x3) != 0;
|
|
}
|
|
}
|