vmm: Use LegacyUserspaceInterruptGroup for mmio devices

This commit replaces the way legacy interrupts were handled with the
brand new implementation of the legacy InterruptSourceGroup for KVM.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2020-01-20 15:07:08 +01:00 committed by Samuel Ortiz
parent 12657ef59f
commit 8d7c4ea334
2 changed files with 25 additions and 22 deletions

View File

@ -10,11 +10,12 @@ use crate::{
}; };
use arc_swap::ArcSwap; use arc_swap::ArcSwap;
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use devices::{BusDevice, Interrupt}; use devices::BusDevice;
use libc::EFD_NONBLOCK; use libc::EFD_NONBLOCK;
use std::result; use std::result;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable}; use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
use vm_memory::{GuestAddress, GuestMemoryMmap}; use vm_memory::{GuestAddress, GuestMemoryMmap};
use vmm_sys_util::{errno::Result, eventfd::EventFd}; use vmm_sys_util::{errno::Result, eventfd::EventFd};
@ -26,11 +27,14 @@ const MMIO_VERSION: u32 = 2;
pub struct VirtioInterruptIntx { pub struct VirtioInterruptIntx {
interrupt_status: Arc<AtomicUsize>, interrupt_status: Arc<AtomicUsize>,
interrupt: Box<dyn Interrupt>, interrupt: Arc<Box<dyn InterruptSourceGroup>>,
} }
impl VirtioInterruptIntx { impl VirtioInterruptIntx {
pub fn new(interrupt_status: Arc<AtomicUsize>, interrupt: Box<dyn Interrupt>) -> Self { pub fn new(
interrupt_status: Arc<AtomicUsize>,
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
) -> Self {
VirtioInterruptIntx { VirtioInterruptIntx {
interrupt_status, interrupt_status,
interrupt, interrupt,
@ -51,7 +55,7 @@ impl VirtioInterrupt for VirtioInterruptIntx {
self.interrupt_status self.interrupt_status
.fetch_or(status as usize, Ordering::SeqCst); .fetch_or(status as usize, Ordering::SeqCst);
self.interrupt.deliver() self.interrupt.trigger(0)
} }
} }
@ -157,7 +161,7 @@ impl MmioDevice {
} }
} }
pub fn assign_interrupt(&mut self, interrupt: Box<dyn Interrupt>) { pub fn assign_interrupt(&mut self, interrupt: Arc<Box<dyn InterruptSourceGroup>>) {
self.interrupt_cb = Some(Arc::new(VirtioInterruptIntx::new( self.interrupt_cb = Some(Arc::new(VirtioInterruptIntx::new(
self.interrupt_status.clone(), self.interrupt_status.clone(),
interrupt, interrupt,

View File

@ -12,7 +12,6 @@
extern crate vm_device; extern crate vm_device;
use crate::config::{ConsoleOutputMode, VmConfig}; use crate::config::{ConsoleOutputMode, VmConfig};
#[cfg(feature = "pci_support")]
use crate::interrupt::{KvmInterruptManager, KvmRoutingEntry}; use crate::interrupt::{KvmInterruptManager, KvmRoutingEntry};
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager}; use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
use crate::vm::VmInfo; use crate::vm::VmInfo;
@ -30,7 +29,6 @@ use pci::{
DeviceRelocation, PciBarRegionType, PciBus, PciConfigIo, PciConfigMmio, PciDevice, PciRoot, DeviceRelocation, PciBarRegionType, PciBus, PciConfigIo, PciConfigMmio, PciDevice, PciRoot,
}; };
use qcow::{self, ImageType, QcowFile}; use qcow::{self, ImageType, QcowFile};
#[cfg(feature = "pci_support")]
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{self, sink, stdout}; use std::io::{self, sink, stdout};
@ -44,8 +42,9 @@ use std::sync::{Arc, Mutex};
#[cfg(feature = "pci_support")] #[cfg(feature = "pci_support")]
use vfio::{VfioDevice, VfioDmaMapping, VfioPciDevice, VfioPciError}; use vfio::{VfioDevice, VfioDmaMapping, VfioPciDevice, VfioPciError};
use vm_allocator::SystemAllocator; use vm_allocator::SystemAllocator;
#[cfg(feature = "pci_support")]
use vm_device::interrupt::InterruptManager; use vm_device::interrupt::InterruptManager;
#[cfg(feature = "mmio_support")]
use vm_device::interrupt::{InterruptIndex, PIN_IRQ};
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable}; use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
use vm_memory::GuestAddress; use vm_memory::GuestAddress;
use vm_memory::{Address, GuestMemoryMmap, GuestUsize}; use vm_memory::{Address, GuestMemoryMmap, GuestUsize};
@ -182,15 +181,17 @@ pub enum DeviceManagerError {
// Error from a memory manager operation // Error from a memory manager operation
MemoryManager(MemoryManagerError), MemoryManager(MemoryManagerError),
/// Failed to create new interrupt source group.
CreateInterruptGroup(io::Error),
/// Failed to update interrupt source group.
UpdateInterruptGroup(io::Error),
} }
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>; pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
type VirtioDeviceArc = Arc<Mutex<dyn vm_virtio::VirtioDevice>>; type VirtioDeviceArc = Arc<Mutex<dyn vm_virtio::VirtioDevice>>;
struct InterruptInfo<'a> {
_ioapic: &'a Arc<Mutex<ioapic::Ioapic>>,
}
struct UserIoapicIrq { struct UserIoapicIrq {
ioapic: Arc<Mutex<ioapic::Ioapic>>, ioapic: Arc<Mutex<ioapic::Ioapic>>,
irq: usize, irq: usize,
@ -445,7 +446,6 @@ impl DeviceManager {
}); });
let ioapic = DeviceManager::add_ioapic(vm_info, &address_manager)?; let ioapic = DeviceManager::add_ioapic(vm_info, &address_manager)?;
let interrupt_info = InterruptInfo { _ioapic: &ioapic };
// Create a shared list of GSI that can be shared through all PCI // Create a shared list of GSI that can be shared through all PCI
// devices. This way, we can maintain the full list of used GSI, // devices. This way, we can maintain the full list of used GSI,
@ -507,7 +507,7 @@ impl DeviceManager {
vm_info, vm_info,
&address_manager, &address_manager,
virtio_devices, virtio_devices,
&interrupt_info, &interrupt_manager,
&mut cmdline_additions, &mut cmdline_additions,
&mut migratable_devices, &mut migratable_devices,
)?; )?;
@ -654,7 +654,7 @@ impl DeviceManager {
vm_info: &VmInfo, vm_info: &VmInfo,
address_manager: &Arc<AddressManager>, address_manager: &Arc<AddressManager>,
virtio_devices: Vec<(Arc<Mutex<dyn vm_virtio::VirtioDevice>>, bool)>, virtio_devices: Vec<(Arc<Mutex<dyn vm_virtio::VirtioDevice>>, bool)>,
interrupt_info: &InterruptInfo, interrupt_manager: &Arc<dyn InterruptManager>,
mut cmdline_additions: &mut Vec<String>, mut cmdline_additions: &mut Vec<String>,
migratable_devices: &mut Vec<Arc<Mutex<dyn Migratable>>>, migratable_devices: &mut Vec<Arc<Mutex<dyn Migratable>>>,
) -> DeviceManagerResult<()> { ) -> DeviceManagerResult<()> {
@ -672,7 +672,7 @@ impl DeviceManager {
vm_info.memory, vm_info.memory,
&address_manager, &address_manager,
vm_info.vm_fd, vm_info.vm_fd,
&interrupt_info, interrupt_manager,
addr, addr,
&mut cmdline_additions, &mut cmdline_additions,
migratable_devices, migratable_devices,
@ -1526,7 +1526,7 @@ impl DeviceManager {
memory: &Arc<ArcSwap<GuestMemoryMmap>>, memory: &Arc<ArcSwap<GuestMemoryMmap>>,
address_manager: &Arc<AddressManager>, address_manager: &Arc<AddressManager>,
vm_fd: &Arc<VmFd>, vm_fd: &Arc<VmFd>,
interrupt_info: &InterruptInfo, interrupt_manager: &Arc<dyn InterruptManager>,
mmio_base: GuestAddress, mmio_base: GuestAddress,
cmdline_additions: &mut Vec<String>, cmdline_additions: &mut Vec<String>,
migratable_devices: &mut Vec<Arc<Mutex<dyn Migratable>>>, migratable_devices: &mut Vec<Arc<Mutex<dyn Migratable>>>,
@ -1548,12 +1548,11 @@ impl DeviceManager {
.allocate_irq() .allocate_irq()
.ok_or(DeviceManagerError::AllocateIrq)?; .ok_or(DeviceManagerError::AllocateIrq)?;
let interrupt: Box<dyn devices::Interrupt> = Box::new(UserIoapicIrq::new( let interrupt_group = interrupt_manager
interrupt_info._ioapic.clone(), .create_group(PIN_IRQ, irq_num as InterruptIndex, 1 as InterruptIndex)
irq_num as usize, .map_err(DeviceManagerError::CreateInterruptGroup)?;
));
mmio_device.assign_interrupt(interrupt); mmio_device.assign_interrupt(interrupt_group);
let mmio_device_arc = Arc::new(Mutex::new(mmio_device)); let mmio_device_arc = Arc::new(Mutex::new(mmio_device));
address_manager address_manager