Skip to content

Commit

Permalink
feat(irq): add support for virtual GIC in AArch64
Browse files Browse the repository at this point in the history
- Add GIC hypervisor interface (GICH) and virtual GIC (GICV) support
- Implement MyVgic struct to provide access to GIC components
- Update timer functionality to support both physical and virtual timers
- Modify IRQ registration and dispatching to work with virtual GIC
- Adjust logging level for IRQ handling
  • Loading branch information
luodeb committed Jan 14, 2025
1 parent 3984835 commit 54eec8f
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 10 deletions.
2 changes: 1 addition & 1 deletion modules/axhal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ irq = []
tls = ["alloc"]
rtc = ["x86_rtc", "riscv_goldfish", "arm_pl031"]
default = []
hv = ["paging", "cortex-a", "percpu/arm-el2", "page_table_entry/arm-el2", "arm_gicv2/el2", "dep:crate_interface"]
hv = ["paging", "cortex-a", "percpu/arm-el2", "page_table_entry/arm-el2", "arm_gicv2/el2", "arm_gicv2/hv", "dep:crate_interface"]

[dependencies]
log = "=0.4.21"
Expand Down
2 changes: 1 addition & 1 deletion modules/axhal/src/irq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use handler_table::HandlerTable;
use crate::platform::irq::{MAX_IRQ_COUNT, dispatch_irq};
use crate::trap::{IRQ, register_trap_handler};

pub use crate::platform::irq::{register_handler, set_enable};
pub use crate::platform::irq::{MyVgic, register_handler, set_enable};

#[cfg(target_arch = "aarch64")]
pub use crate::platform::irq::fetch_irq;
Expand Down
16 changes: 15 additions & 1 deletion modules/axhal/src/platform/aarch64_common/generic_timer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(unused_imports)]

use aarch64_cpu::registers::{CNTFRQ_EL0, CNTP_CTL_EL0, CNTP_TVAL_EL0, CNTPCT_EL0};
use aarch64_cpu::registers::{CNTFRQ_EL0, CNTP_CTL_EL0, CNTP_TVAL_EL0, CNTPCT_EL0, CNTV_TVAL_EL0};
use int_ratio::Ratio;
use tock_registers::interfaces::{Readable, Writeable};

Expand Down Expand Up @@ -48,8 +48,22 @@ pub fn set_oneshot_timer(deadline_ns: u64) {
}
}

pub fn set_oneshot_timer_cntp(deadline_ns: u64) {
// debug!("set_oneshot_timer: cntp_deadline_ns={}", deadline_ns);
let cnptct = CNTPCT_EL0.get();
let cnptct_deadline = nanos_to_ticks(deadline_ns);
if cnptct < cnptct_deadline {
let interval = cnptct_deadline - cnptct;
debug_assert!(interval <= u32::MAX as u64);
CNTV_TVAL_EL0.set(interval);
} else {
CNTV_TVAL_EL0.set(0);
}
}

#[cfg(all(feature = "irq", feature = "hv"))]
pub fn set_oneshot_timer(deadline_ns: u64) {
// debug!("set_oneshot_timer: deadline_ns={}", deadline_ns);
let cnptct = CNTPCT_EL0.get();
let cnptct_deadline = nanos_to_ticks(deadline_ns);
if cnptct < cnptct_deadline {
Expand Down
34 changes: 30 additions & 4 deletions modules/axhal/src/platform/aarch64_common/gic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::{irq::IrqHandler, mem::phys_to_virt};
use arm_gicv2::{GicCpuInterface, GicDistributor, InterruptType, translate_irq};
use axconfig::devices::{GICC_PADDR, GICD_PADDR, UART_IRQ};
use arm_gicv2::{
GicCpuInterface, GicDistributor, GicHypervisorInterface, InterruptType, translate_irq,
};
use axconfig::devices::{GICC_PADDR, GICD_PADDR, GICH_PADDR, GICV_PADDR, UART_IRQ};
use kspin::SpinNoIrq;
use memory_addr::PhysAddr;

Expand All @@ -20,12 +22,17 @@ pub const UART_IRQ_NUM: usize = translate_irq(UART_IRQ, InterruptType::SPI).unwr

const GICD_BASE: PhysAddr = pa!(GICD_PADDR);
const GICC_BASE: PhysAddr = pa!(GICC_PADDR);
const GICV_BASE: PhysAddr = pa!(GICV_PADDR);
const GICH_BASE: PhysAddr = pa!(GICH_PADDR);

static GICD: SpinNoIrq<GicDistributor> =
SpinNoIrq::new(GicDistributor::new(phys_to_virt(GICD_BASE).as_mut_ptr()));

// per-CPU, no lock
static GICC: GicCpuInterface = GicCpuInterface::new(phys_to_virt(GICC_BASE).as_mut_ptr());
static GICV: GicCpuInterface = GicCpuInterface::new(phys_to_virt(GICV_BASE).as_mut_ptr());
static GICH: GicHypervisorInterface =
GicHypervisorInterface::new(phys_to_virt(GICH_BASE).as_mut_ptr());

/// Enables or disables the given IRQ.
pub fn set_enable(irq_num: usize, enabled: bool) {
Expand All @@ -38,7 +45,7 @@ pub fn set_enable(irq_num: usize, enabled: bool) {
/// It also enables the IRQ if the registration succeeds. It returns `false` if
/// the registration failed.
pub fn register_handler(irq_num: usize, handler: IrqHandler) -> bool {
trace!("register handler irq {}", irq_num);
debug!("register handler irq {}", irq_num);
crate::irq::register_handler_common(irq_num, handler)
}

Expand All @@ -64,9 +71,28 @@ pub fn dispatch_irq(irq_no: usize) {

/// Initializes GICD, GICC on the primary CPU.
pub(crate) fn init_primary() {
info!("Initialize GICv2...");
info!("Initialize GICv2... {:?}", GICH_BASE);
GICD.lock().init();
GICC.init();
GICV.init();
GICH.get_hcr();
}

pub struct MyVgic {}

impl MyVgic {
pub fn get_gich() -> &'static GicHypervisorInterface {
&GICH
}
pub fn get_gicd() -> &'static SpinNoIrq<GicDistributor> {
&GICD
}
pub fn get_gicc() -> &'static GicCpuInterface {
&GICC
}
pub fn get_gicv() -> &'static GicCpuInterface {
&GICV
}
}

/// Initializes GICC on secondary CPUs.
Expand Down
4 changes: 2 additions & 2 deletions modules/axhal/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ pub type TimeValue = Duration;

#[cfg(feature = "irq")]
pub use crate::platform::irq::TIMER_IRQ_NUM;
#[cfg(feature = "irq")]
pub use crate::platform::time::set_oneshot_timer;
pub use crate::platform::time::{current_ticks, epochoffset_nanos, nanos_to_ticks, ticks_to_nanos};
#[cfg(feature = "irq")]
pub use crate::platform::time::{set_oneshot_timer, set_oneshot_timer_cntp};

/// Number of milliseconds in a second.
pub const MILLIS_PER_SEC: u64 = 1_000;
Expand Down
2 changes: 1 addition & 1 deletion modules/axtask/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ pub fn exit(exit_code: i32) -> ! {
pub fn run_idle() -> ! {
loop {
yield_now();
debug!("idle task: waiting for IRQs...");
trace!("idle task: waiting for IRQs...");
#[cfg(feature = "irq")]
axhal::arch::wait_for_irqs();
}
Expand Down

0 comments on commit 54eec8f

Please sign in to comment.