diff --git a/devices/src/ioapic.rs b/devices/src/ioapic.rs index 04c8f5dbd..97a8c87ea 100644 --- a/devices/src/ioapic.rs +++ b/devices/src/ioapic.rs @@ -13,8 +13,10 @@ use crate::BusDevice; use byteorder::{ByteOrder, LittleEndian}; use kvm_bindings::kvm_msi; use kvm_ioctls::VmFd; +use std::io; use std::result; use std::sync::Arc; +use vm_device::interrupt::{InterruptIndex, InterruptManager, InterruptSourceGroup, PCI_MSI_IRQ}; use vm_memory::GuestAddress; #[derive(Debug)] @@ -27,6 +29,8 @@ pub enum Error { InvalidTriggerMode, /// Invalid delivery mode. InvalidDeliveryMode, + /// Failed creating the interrupt source group. + CreateInterruptSourceGroup(io::Error), } type Result = result::Result; @@ -158,6 +162,7 @@ pub struct Ioapic { reg_entries: [RedirectionTableEntry; NUM_IOAPIC_PINS], vm_fd: Arc, apic_address: GuestAddress, + _interrupt_source_group: Arc>, } impl BusDevice for Ioapic { @@ -196,14 +201,27 @@ impl BusDevice for Ioapic { } impl Ioapic { - pub fn new(vm_fd: Arc, apic_address: GuestAddress) -> Ioapic { - Ioapic { + pub fn new( + vm_fd: Arc, + apic_address: GuestAddress, + interrupt_manager: Arc, + ) -> Result { + let interrupt_source_group = interrupt_manager + .create_group( + PCI_MSI_IRQ, + 0 as InterruptIndex, + NUM_IOAPIC_PINS as InterruptIndex, + ) + .map_err(Error::CreateInterruptSourceGroup)?; + + Ok(Ioapic { id: 0, reg_sel: 0, reg_entries: [0; NUM_IOAPIC_PINS], vm_fd, apic_address, - } + _interrupt_source_group: interrupt_source_group, + }) } // The ioapic must be informed about EOIs in order to deassert interrupts diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index d86aa056f..6ccfec812 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -189,6 +189,9 @@ pub enum DeviceManagerError { /// Failed to update interrupt source group. UpdateInterruptGroup(io::Error), + + /// Failed creating IOAPIC. + CreateIoapic(ioapic::Error), } pub type DeviceManagerResult = result::Result; @@ -697,13 +700,13 @@ impl DeviceManager { fn add_ioapic( vm_info: &VmInfo, address_manager: &Arc, - _ioapic_interrupt_manager: Arc, + interrupt_manager: Arc, ) -> DeviceManagerResult>> { // Create IOAPIC - let ioapic = Arc::new(Mutex::new(ioapic::Ioapic::new( - vm_info.vm_fd.clone(), - APIC_START, - ))); + let ioapic = Arc::new(Mutex::new( + ioapic::Ioapic::new(vm_info.vm_fd.clone(), APIC_START, interrupt_manager) + .map_err(DeviceManagerError::CreateIoapic)?, + )); address_manager .mmio_bus