From 4df1ebc6d6fb4aec89ae357ccd965bbd5c0531ff Mon Sep 17 00:00:00 2001 From: yufeng <321353225@qq.com> Date: Wed, 29 May 2024 16:53:30 +0800 Subject: [PATCH] feat: add irq support for aarch64 and x86_64 --- src/aarch64/gic.rs | 22 ++++++++++++++++------ src/aarch64/timer.rs | 5 +++-- src/loongarch64/timer.rs | 17 +++++++++++++++++ src/loongarch64/trap.rs | 5 +++-- src/riscv64/irq.rs | 16 ++++++++++++++++ src/riscv64/mod.rs | 1 + src/x86_64/apic.rs | 40 ++++++++++++++++++++++++++-------------- 7 files changed, 82 insertions(+), 24 deletions(-) create mode 100644 src/riscv64/irq.rs diff --git a/src/aarch64/gic.rs b/src/aarch64/gic.rs index d6c4cd9..abdc5df 100644 --- a/src/aarch64/gic.rs +++ b/src/aarch64/gic.rs @@ -3,6 +3,7 @@ use arm_gic::{translate_irq, InterruptType}; use irq_safety::MutexIrqSafe; use crate::addr::PhysAddr; +use crate::irq::IRQ; /// The maximum number of IRQs. #[allow(dead_code)] @@ -24,12 +25,6 @@ static GICD: MutexIrqSafe = // per-CPU, no lock static GICC: GicCpuInterface = GicCpuInterface::new(GICC_BASE.get_mut_ptr()); -/// Enables or disables the given IRQ. -pub fn set_enable(irq_num: usize, enabled: bool) { - trace!("GICD set enable: {} {}", irq_num, enabled); - GICD.lock().set_enable(irq_num as _, enabled); -} - /// Initializes GICD, GICC on the primary CPU. pub(crate) fn init() { info!("Initialize GICv2..."); @@ -44,3 +39,18 @@ where { GICC.handle_irq(f) } + +/// Implement IRQ operations for the IRQ interface. +impl IRQ { + /// Enable irq for the given IRQ number. + #[inline] + pub fn enable(irq_num: usize) { + GICD.lock().set_enable(irq_num, true); + } + + /// Disable irq for the given IRQ number. + #[inline] + pub fn disable(irq_num: usize) { + GICD.lock().set_enable(irq_num, false); + } +} diff --git a/src/aarch64/timer.rs b/src/aarch64/timer.rs index 6cc1837..f6c07f5 100644 --- a/src/aarch64/timer.rs +++ b/src/aarch64/timer.rs @@ -3,7 +3,7 @@ use aarch64_cpu::registers::{CNTFRQ_EL0, CNTPCT_EL0, CNTP_CTL_EL0, CNTP_TVAL_EL0}; use tock_registers::interfaces::{Readable, Writeable}; -use crate::time::Time; +use crate::{irq::IRQ, time::Time}; impl Time { #[inline] @@ -27,6 +27,7 @@ pub fn init() { debug!("freq: {}", freq); CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET); CNTP_TVAL_EL0.set(0); - super::gic::set_enable(super::gic::TIMER_IRQ_NUM, true); + // Enable the timer irq. + IRQ::enable(super::gic::TIMER_IRQ_NUM); set_next_timer(); } diff --git a/src/loongarch64/timer.rs b/src/loongarch64/timer.rs index 536f34c..09060df 100644 --- a/src/loongarch64/timer.rs +++ b/src/loongarch64/timer.rs @@ -4,6 +4,8 @@ use loongArch64::register::tcfg; use loongArch64::time::{get_timer_freq, Time}; use spin::Lazy; +use crate::irq::IRQ; + // static mut FREQ: usize = 0; static FREQ: Lazy = Lazy::new(|| get_timer_freq()); @@ -32,3 +34,18 @@ pub fn init_timer() { | LineBasedInterrupt::HWI0; ecfg::set_lie(inter); } + +/// Implement IRQ operations for the IRQ interface. +impl IRQ { + /// Enable irq for the given IRQ number. + #[inline] + pub fn enable(_irq_num: usize) { + log::warn!("irq not implemented in loongarch64 platform yet"); + } + + /// Disable irq for the given IRQ number. + #[inline] + pub fn disable(_irq_num: usize) { + log::warn!("irq not implemented in loongarch64 platform yet"); + } +} diff --git a/src/loongarch64/trap.rs b/src/loongarch64/trap.rs index 08066f3..e659720 100644 --- a/src/loongarch64/trap.rs +++ b/src/loongarch64/trap.rs @@ -349,8 +349,9 @@ fn loongarch64_trap_handler(tf: &mut TrapFrame) -> TrapType { // TrapType::Un TrapType::StorePageFault(badv::read().vaddr()) } - Trap::Exception(Exception::FetchPageFault) - | Trap::Exception(Exception::LoadPageFault) => TrapType::LoadPageFault(badv::read().vaddr()), + Trap::Exception(Exception::FetchPageFault) | Trap::Exception(Exception::LoadPageFault) => { + TrapType::LoadPageFault(badv::read().vaddr()) + } _ => { panic!( "Unhandled trap {:?} @ {:#x} BADV: {:#x}:\n{:#x?}", diff --git a/src/riscv64/irq.rs b/src/riscv64/irq.rs new file mode 100644 index 0000000..1d63057 --- /dev/null +++ b/src/riscv64/irq.rs @@ -0,0 +1,16 @@ +use crate::irq::IRQ; + +/// Implement IRQ operations for the IRQ interface. +impl IRQ { + /// Enable irq for the given IRQ number. + #[inline] + pub fn enable(_irq_num: usize) { + log::warn!("irq not implemented in riscv platform yet"); + } + + /// Disable irq for the given IRQ number. + #[inline] + pub fn disable(_irq_num: usize) { + log::warn!("irq not implemented in riscv platform yet"); + } +} diff --git a/src/riscv64/mod.rs b/src/riscv64/mod.rs index 93b7d48..b4d02aa 100644 --- a/src/riscv64/mod.rs +++ b/src/riscv64/mod.rs @@ -4,6 +4,7 @@ mod consts; mod context; mod entry; mod interrupt; +mod irq; #[cfg(feature = "kcontext")] mod kcontext; mod page_table; diff --git a/src/x86_64/apic.rs b/src/x86_64/apic.rs index 04cb4a4..5e5920e 100644 --- a/src/x86_64/apic.rs +++ b/src/x86_64/apic.rs @@ -7,6 +7,7 @@ use x2apic::lapic::{xapic_base, LocalApic, LocalApicBuilder}; use x86_64::instructions::port::Port; use self::vectors::*; +use crate::irq::IRQ; use crate::VIRT_ADDR_START; pub(super) mod vectors { @@ -27,20 +28,6 @@ static mut LOCAL_APIC: Option = None; static mut IS_X2APIC: bool = false; static IO_APIC: Once> = Once::new(); -/// Enables or disables the given IRQ. -pub fn set_enable(vector: usize, enabled: bool) { - // should not affect LAPIC interrupts - if vector < APIC_TIMER_VECTOR as _ { - unsafe { - if enabled { - IO_APIC.get_unchecked().lock().enable_irq(vector as u8); - } else { - IO_APIC.get_unchecked().lock().disable_irq(vector as u8); - } - } - } -} - /// Registers an IRQ handler for the given IRQ. /// /// It also enables the IRQ if the registration succeeds. It returns `false` if @@ -112,3 +99,28 @@ pub(super) fn init() { let io_apic = unsafe { IoApic::new(IO_APIC_BASE) }; IO_APIC.call_once(|| MutexIrqSafe::new(io_apic)); } + +/// Implement IRQ operations for the IRQ interface. +impl IRQ { + /// Enable irq for the given IRQ number. + #[inline] + pub fn enable(irq_num: usize) { + // should not affect LAPIC interrupts + if irq_num < APIC_TIMER_VECTOR as _ { + unsafe { + IO_APIC.get_unchecked().lock().enable_irq(irq_num as _); + } + } + } + + /// Disable irq for the given IRQ number. + #[inline] + pub fn disable(irq_num: usize) { + // should not affect LAPIC interrupts + if irq_num < APIC_TIMER_VECTOR as _ { + unsafe { + IO_APIC.get_unchecked().lock().disable_irq(irq_num as _); + } + } + } +}