mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vm-device: interrupt: Remove InterruptType dependencies and definitions
Having the InterruptManager trait depend on an InterruptType forces implementations into supporting potentially very different kind of interrupts from the same code base. What we're defining through the current, interrupt type based create_group() method is a need for having different interrupt managers for different kind of interrupts. By associating the InterruptManager trait to an interrupt group configuration type, we create a cleaner design to support that need as we're basically saying that one interrupt manager should have the single responsibility of supporting one kind of interrupt (defined through its configuration). Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
committed by
Sebastien Boeuf
parent
84fc807bc6
commit
da2b3c92d3
@@ -42,8 +42,9 @@ use std::sync::{Arc, Mutex};
|
||||
#[cfg(feature = "pci_support")]
|
||||
use vfio::{VfioDevice, VfioDmaMapping, VfioPciDevice, VfioPciError};
|
||||
use vm_allocator::SystemAllocator;
|
||||
use vm_device::interrupt::InterruptManager;
|
||||
use vm_device::interrupt::{InterruptIndex, PIN_IRQ};
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptManager, LegacyIrqGroupConfig, MsiIrqGroupConfig,
|
||||
};
|
||||
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
||||
use vm_memory::guest_memory::FileOffset;
|
||||
use vm_memory::{Address, GuestAddress, GuestUsize, MmapRegion};
|
||||
@@ -436,7 +437,7 @@ impl DeviceManager {
|
||||
// and then the legacy interrupt manager needs an IOAPIC. So we're
|
||||
// handling a linear dependency chain:
|
||||
// msi_interrupt_manager <- IOAPIC <- legacy_interrupt_manager.
|
||||
let msi_interrupt_manager: Arc<dyn InterruptManager> =
|
||||
let msi_interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>> =
|
||||
Arc::new(KvmMsiInterruptManager::new(
|
||||
Arc::clone(&address_manager.allocator),
|
||||
vm_fd,
|
||||
@@ -448,8 +449,9 @@ impl DeviceManager {
|
||||
|
||||
// Now we can create the legacy interrupt manager, which needs the freshly
|
||||
// formed IOAPIC device.
|
||||
let legacy_interrupt_manager: Arc<dyn InterruptManager> =
|
||||
Arc::new(KvmLegacyUserspaceInterruptManager::new(ioapic.clone()));
|
||||
let legacy_interrupt_manager: Arc<
|
||||
dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>,
|
||||
> = Arc::new(KvmLegacyUserspaceInterruptManager::new(ioapic.clone()));
|
||||
|
||||
#[cfg(feature = "acpi")]
|
||||
address_manager
|
||||
@@ -509,7 +511,7 @@ impl DeviceManager {
|
||||
fn add_pci_devices(
|
||||
&mut self,
|
||||
virtio_devices: Vec<(Arc<Mutex<dyn vm_virtio::VirtioDevice>>, bool)>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||
) -> DeviceManagerResult<()> {
|
||||
#[cfg(feature = "pci_support")]
|
||||
{
|
||||
@@ -587,7 +589,7 @@ impl DeviceManager {
|
||||
fn add_mmio_devices(
|
||||
&mut self,
|
||||
virtio_devices: Vec<(Arc<Mutex<dyn vm_virtio::VirtioDevice>>, bool)>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
||||
) -> DeviceManagerResult<()> {
|
||||
#[cfg(feature = "mmio_support")]
|
||||
{
|
||||
@@ -611,7 +613,7 @@ impl DeviceManager {
|
||||
|
||||
fn add_ioapic(
|
||||
address_manager: &Arc<AddressManager>,
|
||||
interrupt_manager: Arc<dyn InterruptManager>,
|
||||
interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||
) -> DeviceManagerResult<Arc<Mutex<ioapic::Ioapic>>> {
|
||||
// Create IOAPIC
|
||||
let ioapic = Arc::new(Mutex::new(
|
||||
@@ -630,7 +632,7 @@ impl DeviceManager {
|
||||
#[cfg(feature = "acpi")]
|
||||
fn add_acpi_devices(
|
||||
&mut self,
|
||||
interrupt_manager: &Arc<dyn InterruptManager>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
||||
reset_evt: EventFd,
|
||||
exit_evt: EventFd,
|
||||
) -> DeviceManagerResult<Option<Arc<Mutex<devices::AcpiGEDDevice>>>> {
|
||||
@@ -659,7 +661,9 @@ impl DeviceManager {
|
||||
.unwrap();
|
||||
|
||||
let interrupt_group = interrupt_manager
|
||||
.create_group(PIN_IRQ, ged_irq as InterruptIndex, 1 as InterruptIndex)
|
||||
.create_group(LegacyIrqGroupConfig {
|
||||
irq: ged_irq as InterruptIndex,
|
||||
})
|
||||
.map_err(DeviceManagerError::CreateInterruptGroup)?;
|
||||
|
||||
let ged_device = Arc::new(Mutex::new(devices::AcpiGEDDevice::new(
|
||||
@@ -721,7 +725,7 @@ impl DeviceManager {
|
||||
|
||||
fn add_console_device(
|
||||
&mut self,
|
||||
interrupt_manager: &Arc<dyn InterruptManager>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
||||
virtio_devices: &mut Vec<(Arc<Mutex<dyn vm_virtio::VirtioDevice>>, bool)>,
|
||||
) -> DeviceManagerResult<Arc<Console>> {
|
||||
let serial_config = self.config.lock().unwrap().serial.clone();
|
||||
@@ -738,7 +742,9 @@ impl DeviceManager {
|
||||
let serial_irq = 4;
|
||||
|
||||
let interrupt_group = interrupt_manager
|
||||
.create_group(PIN_IRQ, serial_irq as InterruptIndex, 1 as InterruptIndex)
|
||||
.create_group(LegacyIrqGroupConfig {
|
||||
irq: serial_irq as InterruptIndex,
|
||||
})
|
||||
.map_err(DeviceManagerError::CreateInterruptGroup)?;
|
||||
|
||||
let serial = Arc::new(Mutex::new(devices::legacy::Serial::new(
|
||||
@@ -1262,7 +1268,7 @@ impl DeviceManager {
|
||||
&mut self,
|
||||
pci: &mut PciBus,
|
||||
iommu_device: &mut Option<vm_virtio::Iommu>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||
) -> DeviceManagerResult<Vec<u32>> {
|
||||
let mut mem_slot = self
|
||||
.memory_manager
|
||||
@@ -1340,7 +1346,7 @@ impl DeviceManager {
|
||||
virtio_device: Arc<Mutex<dyn vm_virtio::VirtioDevice>>,
|
||||
pci: &mut PciBus,
|
||||
iommu_mapping: &Option<Arc<IommuMapping>>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||
) -> DeviceManagerResult<Option<u32>> {
|
||||
// Allows support for one MSI-X vector per queue. It also adds 1
|
||||
// as we need to take into account the dedicated vector to notify
|
||||
@@ -1427,7 +1433,7 @@ impl DeviceManager {
|
||||
fn add_virtio_mmio_device(
|
||||
&mut self,
|
||||
virtio_device: Arc<Mutex<dyn vm_virtio::VirtioDevice>>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager>,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
||||
mmio_base: GuestAddress,
|
||||
) -> DeviceManagerResult<()> {
|
||||
let memory = self.memory_manager.lock().unwrap().guest_memory();
|
||||
@@ -1451,7 +1457,9 @@ impl DeviceManager {
|
||||
.ok_or(DeviceManagerError::AllocateIrq)?;
|
||||
|
||||
let interrupt_group = interrupt_manager
|
||||
.create_group(PIN_IRQ, irq_num as InterruptIndex, 1 as InterruptIndex)
|
||||
.create_group(LegacyIrqGroupConfig {
|
||||
irq: irq_num as InterruptIndex,
|
||||
})
|
||||
.map_err(DeviceManagerError::CreateInterruptGroup)?;
|
||||
|
||||
mmio_device.assign_interrupt(interrupt_group);
|
||||
|
||||
@@ -12,8 +12,8 @@ use std::mem::size_of;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vm_allocator::SystemAllocator;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup, InterruptType,
|
||||
PCI_MSI_IRQ, PIN_IRQ,
|
||||
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
|
||||
LegacyIrqGroupConfig, MsiIrqGroupConfig,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
@@ -303,35 +303,16 @@ impl KvmMsiInterruptManager {
|
||||
}
|
||||
|
||||
impl InterruptManager for KvmLegacyUserspaceInterruptManager {
|
||||
type GroupConfig = LegacyIrqGroupConfig;
|
||||
|
||||
fn create_group(
|
||||
&self,
|
||||
interrupt_type: InterruptType,
|
||||
base: InterruptIndex,
|
||||
count: InterruptIndex,
|
||||
config: Self::GroupConfig,
|
||||
) -> Result<Arc<Box<dyn InterruptSourceGroup>>> {
|
||||
let interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>> = match interrupt_type {
|
||||
PIN_IRQ => {
|
||||
if count > 1 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Legacy cannot support more than one interrupt",
|
||||
));
|
||||
}
|
||||
|
||||
Arc::new(Box::new(LegacyUserspaceInterruptGroup::new(
|
||||
self.ioapic.clone(),
|
||||
base as u32,
|
||||
)))
|
||||
}
|
||||
_ => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Interrupt type not supported",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(interrupt_source_group)
|
||||
Ok(Arc::new(Box::new(LegacyUserspaceInterruptGroup::new(
|
||||
self.ioapic.clone(),
|
||||
config.irq as u32,
|
||||
))))
|
||||
}
|
||||
|
||||
fn destroy_group(&self, _group: Arc<Box<dyn InterruptSourceGroup>>) -> Result<()> {
|
||||
@@ -340,36 +321,24 @@ impl InterruptManager for KvmLegacyUserspaceInterruptManager {
|
||||
}
|
||||
|
||||
impl InterruptManager for KvmMsiInterruptManager {
|
||||
type GroupConfig = MsiIrqGroupConfig;
|
||||
|
||||
fn create_group(
|
||||
&self,
|
||||
interrupt_type: InterruptType,
|
||||
base: InterruptIndex,
|
||||
count: InterruptIndex,
|
||||
config: Self::GroupConfig,
|
||||
) -> Result<Arc<Box<dyn InterruptSourceGroup>>> {
|
||||
let interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>> = match interrupt_type {
|
||||
PCI_MSI_IRQ => {
|
||||
let mut allocator = self.allocator.lock().unwrap();
|
||||
let mut irq_routes: HashMap<InterruptIndex, InterruptRoute> =
|
||||
HashMap::with_capacity(count as usize);
|
||||
for i in base..base + count {
|
||||
irq_routes.insert(i, InterruptRoute::new(&mut allocator)?);
|
||||
}
|
||||
let mut allocator = self.allocator.lock().unwrap();
|
||||
let mut irq_routes: HashMap<InterruptIndex, InterruptRoute> =
|
||||
HashMap::with_capacity(config.count as usize);
|
||||
for i in config.base..config.base + config.count {
|
||||
irq_routes.insert(i, InterruptRoute::new(&mut allocator)?);
|
||||
}
|
||||
|
||||
Arc::new(Box::new(MsiInterruptGroup::new(
|
||||
self.vm_fd.clone(),
|
||||
self.gsi_msi_routes.clone(),
|
||||
irq_routes,
|
||||
)))
|
||||
}
|
||||
_ => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Interrupt type not supported",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(interrupt_source_group)
|
||||
Ok(Arc::new(Box::new(MsiInterruptGroup::new(
|
||||
self.vm_fd.clone(),
|
||||
self.gsi_msi_routes.clone(),
|
||||
irq_routes,
|
||||
))))
|
||||
}
|
||||
|
||||
fn destroy_group(&self, _group: Arc<Box<dyn InterruptSourceGroup>>) -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user