diff --git a/arch/src/aarch64/layout.rs b/arch/src/aarch64/layout.rs index 22a74edce..16b559ac8 100644 --- a/arch/src/aarch64/layout.rs +++ b/arch/src/aarch64/layout.rs @@ -78,9 +78,9 @@ pub const FDT_MAX_SIZE: usize = 0x20_0000; // * bigger than 32 // * less than 1023 and // * a multiple of 32. -// We are setting up our interrupt controller to support a maximum of 128 interrupts. +// We are setting up our interrupt controller to support a maximum of 256 interrupts. /// First usable interrupt on aarch64. -pub const IRQ_BASE: u32 = 32; +pub const IRQ_BASE: u32 = 0; /// Last usable interrupt on aarch64. -pub const IRQ_MAX: u32 = 159; +pub const IRQ_MAX: u32 = 255; diff --git a/devices/src/gic.rs b/devices/src/gic.rs index 319dc8cdb..2e534727a 100644 --- a/devices/src/gic.rs +++ b/devices/src/gic.rs @@ -6,16 +6,16 @@ use super::interrupt_controller::{Error, InterruptController}; use std::result; use std::sync::Arc; use vm_device::interrupt::{ - InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig, + InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup, + LegacyIrqSourceConfig, MsiIrqGroupConfig, }; use vmm_sys_util::eventfd::EventFd; type Result = result::Result; -// Reserve 32 IRQs (GSI 32 ~ 64) for legacy device. -// GsiAllocator should allocate beyond this: from 64 on +// Reserve 32 IRQs for legacy device. +pub const IRQ_LEGACY_BASE: usize = 0; pub const IRQ_LEGACY_COUNT: usize = 32; -pub const IRQ_SPI_OFFSET: usize = 32; // This Gic struct implements InterruptController to provide interrupt delivery service. // The Gic source files in arch/ folder maintain the Aarch64 specific Gic device. @@ -34,7 +34,7 @@ impl Gic { ) -> Result { let interrupt_source_group = interrupt_manager .create_group(MsiIrqGroupConfig { - base: IRQ_SPI_OFFSET as InterruptIndex, + base: IRQ_LEGACY_BASE as InterruptIndex, count: IRQ_LEGACY_COUNT as InterruptIndex, }) .map_err(Error::CreateInterruptSourceGroup)?; @@ -47,9 +47,26 @@ impl Gic { impl InterruptController for Gic { fn enable(&self) -> Result<()> { + // Set irqfd for legacy interrupts self.interrupt_source_group .enable() .map_err(Error::EnableInterrupt)?; + + // Set irq_routing for legacy interrupts. + // irqchip: Hardcode to 0 as we support only 1 GIC + // pin: Use irq number as pin + for i in IRQ_LEGACY_BASE..(IRQ_LEGACY_BASE + IRQ_LEGACY_COUNT) { + let config = LegacyIrqSourceConfig { + irqchip: 0, + pin: i as u32, + }; + self.interrupt_source_group + .update( + i as InterruptIndex, + InterruptSourceConfig::LegacyIrq(config), + ) + .map_err(Error::EnableInterrupt)?; + } Ok(()) } diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 42c934b03..b7426c821 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -57,8 +57,8 @@ pub use kvm_bindings; use kvm_bindings::KVMIO; pub use kvm_bindings::{ kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO, kvm_irq_routing, kvm_irq_routing_entry, - kvm_userspace_memory_region, KVM_IRQ_ROUTING_MSI, KVM_MEM_LOG_DIRTY_PAGES, KVM_MEM_READONLY, - KVM_MSI_VALID_DEVID, + kvm_userspace_memory_region, KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI, + KVM_MEM_LOG_DIRTY_PAGES, KVM_MEM_READONLY, KVM_MSI_VALID_DEVID, }; #[cfg(target_arch = "aarch64")] use kvm_bindings::{ diff --git a/vm-allocator/src/system.rs b/vm-allocator/src/system.rs index eb44b6f44..e73ee8b48 100644 --- a/vm-allocator/src/system.rs +++ b/vm-allocator/src/system.rs @@ -42,11 +42,11 @@ fn pagesize() -> usize { /// #[cfg(target_arch = "x86_64")] /// assert_eq!(allocator.allocate_irq(), Some(5)); /// #[cfg(target_arch = "aarch64")] -/// assert_eq!(allocator.allocate_irq(), Some(32)); +/// assert_eq!(allocator.allocate_irq(), Some(0)); /// #[cfg(target_arch = "x86_64")] /// assert_eq!(allocator.allocate_irq(), Some(6)); /// #[cfg(target_arch = "aarch64")] -/// assert_eq!(allocator.allocate_irq(), Some(33)); +/// assert_eq!(allocator.allocate_irq(), Some(1)); /// assert_eq!(allocator.allocate_mmio_addresses(None, 0x1000, Some(0x1000)), Some(GuestAddress(0x1fff_f000))); /// /// ``` diff --git a/vm-device/src/interrupt/mod.rs b/vm-device/src/interrupt/mod.rs index 4f344e395..9f403d54c 100644 --- a/vm-device/src/interrupt/mod.rs +++ b/vm-device/src/interrupt/mod.rs @@ -70,7 +70,10 @@ pub type InterruptIndex = u32; /// /// On x86 platforms, legacy interrupts means those interrupts routed through PICs or IOAPICs. #[derive(Copy, Clone, Debug)] -pub struct LegacyIrqSourceConfig {} +pub struct LegacyIrqSourceConfig { + pub irqchip: u32, + pub pin: u32, +} /// Configuration data for MSI/MSI-X interrupts. /// diff --git a/vmm/src/interrupt.rs b/vmm/src/interrupt.rs index 34b1713a2..a033fcf6f 100644 --- a/vmm/src/interrupt.rs +++ b/vmm/src/interrupt.rs @@ -337,7 +337,7 @@ where pub mod kvm { use super::*; use hypervisor::kvm::KVM_MSI_VALID_DEVID; - use hypervisor::kvm::{kvm_irq_routing_entry, KVM_IRQ_ROUTING_MSI}; + use hypervisor::kvm::{kvm_irq_routing_entry, KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI}; type KvmMsiInterruptGroup = MsiInterruptGroup; type KvmRoutingEntry = RoutingEntry; @@ -370,6 +370,20 @@ pub mod kvm { masked: false, }; + return Ok(Box::new(kvm_entry)); + } else if let InterruptSourceConfig::LegacyIrq(cfg) = &config { + let mut kvm_route = kvm_irq_routing_entry { + gsi, + type_: KVM_IRQ_ROUTING_IRQCHIP, + ..Default::default() + }; + kvm_route.u.irqchip.irqchip = cfg.irqchip; + kvm_route.u.irqchip.pin = cfg.pin; + let kvm_entry = KvmRoutingEntry { + route: kvm_route, + masked: false, + }; + return Ok(Box::new(kvm_entry)); } @@ -493,7 +507,7 @@ mod tests { let res = get_dist_regs(gic.device()); assert!(res.is_ok()); let state = res.unwrap(); - assert_eq!(state.len(), 244); + assert_eq!(state.len(), 649); let res = set_dist_regs(gic.device(), &state); assert!(res.is_ok());