mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 21:55:20 +00:00
vmm: device_manager: Add a PCI devices creation routine
In order to reduce the DeviceManager's new() complexity, we can move the PCI devices creation code into its own routine. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
5087f633f6
commit
79b8f8e477
@ -463,96 +463,14 @@ impl DeviceManager {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
if cfg!(feature = "pci_support") {
|
if cfg!(feature = "pci_support") {
|
||||||
#[cfg(feature = "pci_support")]
|
DeviceManager::add_pci_devices(
|
||||||
{
|
vm_info,
|
||||||
let pci_root = PciRoot::new(None);
|
&address_manager,
|
||||||
let mut pci_bus = PciBus::new(
|
mem_slots,
|
||||||
pci_root,
|
&mut virt_iommu,
|
||||||
Arc::downgrade(&address_manager) as Weak<dyn DeviceRelocation>,
|
virtio_devices,
|
||||||
);
|
&interrupt_info,
|
||||||
|
)?;
|
||||||
let (mut iommu_device, iommu_mapping) = if vm_info.vm_cfg.iommu {
|
|
||||||
let (device, mapping) =
|
|
||||||
vm_virtio::Iommu::new().map_err(DeviceManagerError::CreateVirtioIommu)?;
|
|
||||||
(Some(device), Some(mapping))
|
|
||||||
} else {
|
|
||||||
(None, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut iommu_attached_devices = Vec::new();
|
|
||||||
|
|
||||||
for (device, iommu_attached) in virtio_devices {
|
|
||||||
let mapping: &Option<Arc<IommuMapping>> = if iommu_attached {
|
|
||||||
&iommu_mapping
|
|
||||||
} else {
|
|
||||||
&None
|
|
||||||
};
|
|
||||||
|
|
||||||
let virtio_iommu_attach_dev = DeviceManager::add_virtio_pci_device(
|
|
||||||
device,
|
|
||||||
vm_info.memory,
|
|
||||||
&address_manager,
|
|
||||||
vm_info.vm_fd,
|
|
||||||
&mut pci_bus,
|
|
||||||
&interrupt_info,
|
|
||||||
mapping,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if let Some(dev_id) = virtio_iommu_attach_dev {
|
|
||||||
iommu_attached_devices.push(dev_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut vfio_iommu_device_ids = DeviceManager::add_vfio_devices(
|
|
||||||
vm_info,
|
|
||||||
&address_manager,
|
|
||||||
&mut pci_bus,
|
|
||||||
mem_slots,
|
|
||||||
&mut iommu_device,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
iommu_attached_devices.append(&mut vfio_iommu_device_ids);
|
|
||||||
|
|
||||||
if let Some(iommu_device) = iommu_device {
|
|
||||||
// We need to shift the device id since the 3 first bits
|
|
||||||
// are dedicated to the PCI function, and we know we don't
|
|
||||||
// do multifunction. Also, because we only support one PCI
|
|
||||||
// bus, the bus 0, we don't need to add anything to the
|
|
||||||
// global device ID.
|
|
||||||
let iommu_id = pci_bus.next_device_id() << 3;
|
|
||||||
|
|
||||||
// Because we determined the virtio-iommu b/d/f, we have to
|
|
||||||
// add the device to the PCI topology now. Otherwise, the
|
|
||||||
// b/d/f won't match the virtio-iommu device as expected.
|
|
||||||
DeviceManager::add_virtio_pci_device(
|
|
||||||
Box::new(iommu_device),
|
|
||||||
vm_info.memory,
|
|
||||||
&address_manager,
|
|
||||||
vm_info.vm_fd,
|
|
||||||
&mut pci_bus,
|
|
||||||
&interrupt_info,
|
|
||||||
&None,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
virt_iommu = Some((iommu_id, iommu_attached_devices));
|
|
||||||
}
|
|
||||||
|
|
||||||
let pci_bus = Arc::new(Mutex::new(pci_bus));
|
|
||||||
let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(pci_bus.clone())));
|
|
||||||
address_manager
|
|
||||||
.io_bus
|
|
||||||
.insert(pci_config_io, 0xcf8, 0x8)
|
|
||||||
.map_err(DeviceManagerError::BusError)?;
|
|
||||||
let pci_config_mmio = Arc::new(Mutex::new(PciConfigMmio::new(pci_bus)));
|
|
||||||
address_manager
|
|
||||||
.mmio_bus
|
|
||||||
.insert(
|
|
||||||
pci_config_mmio,
|
|
||||||
arch::layout::PCI_MMCONFIG_START.0,
|
|
||||||
arch::layout::PCI_MMCONFIG_SIZE,
|
|
||||||
)
|
|
||||||
.map_err(DeviceManagerError::BusError)?;
|
|
||||||
}
|
|
||||||
} else if cfg!(feature = "mmio_support") {
|
} else if cfg!(feature = "mmio_support") {
|
||||||
#[cfg(feature = "mmio_support")]
|
#[cfg(feature = "mmio_support")]
|
||||||
{
|
{
|
||||||
@ -589,6 +507,109 @@ impl DeviceManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn add_pci_devices(
|
||||||
|
vm_info: &VmInfo,
|
||||||
|
address_manager: &Arc<AddressManager>,
|
||||||
|
mem_slots: u32,
|
||||||
|
virt_iommu: &mut Option<(u32, Vec<u32>)>,
|
||||||
|
virtio_devices: Vec<(Box<dyn vm_virtio::VirtioDevice>, bool)>,
|
||||||
|
interrupt_info: &InterruptInfo,
|
||||||
|
) -> DeviceManagerResult<()> {
|
||||||
|
#[cfg(feature = "pci_support")]
|
||||||
|
{
|
||||||
|
let pci_root = PciRoot::new(None);
|
||||||
|
let mut pci_bus = PciBus::new(
|
||||||
|
pci_root,
|
||||||
|
Arc::downgrade(&address_manager) as Weak<dyn DeviceRelocation>,
|
||||||
|
);
|
||||||
|
|
||||||
|
let (mut iommu_device, iommu_mapping) = if vm_info.vm_cfg.iommu {
|
||||||
|
let (device, mapping) =
|
||||||
|
vm_virtio::Iommu::new().map_err(DeviceManagerError::CreateVirtioIommu)?;
|
||||||
|
(Some(device), Some(mapping))
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut iommu_attached_devices = Vec::new();
|
||||||
|
|
||||||
|
for (device, iommu_attached) in virtio_devices {
|
||||||
|
let mapping: &Option<Arc<IommuMapping>> = if iommu_attached {
|
||||||
|
&iommu_mapping
|
||||||
|
} else {
|
||||||
|
&None
|
||||||
|
};
|
||||||
|
|
||||||
|
let virtio_iommu_attach_dev = DeviceManager::add_virtio_pci_device(
|
||||||
|
device,
|
||||||
|
vm_info.memory,
|
||||||
|
&address_manager,
|
||||||
|
vm_info.vm_fd,
|
||||||
|
&mut pci_bus,
|
||||||
|
&interrupt_info,
|
||||||
|
mapping,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if let Some(dev_id) = virtio_iommu_attach_dev {
|
||||||
|
iommu_attached_devices.push(dev_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut vfio_iommu_device_ids = DeviceManager::add_vfio_devices(
|
||||||
|
vm_info,
|
||||||
|
&address_manager,
|
||||||
|
&mut pci_bus,
|
||||||
|
mem_slots,
|
||||||
|
&mut iommu_device,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
iommu_attached_devices.append(&mut vfio_iommu_device_ids);
|
||||||
|
|
||||||
|
if let Some(iommu_device) = iommu_device {
|
||||||
|
// We need to shift the device id since the 3 first bits
|
||||||
|
// are dedicated to the PCI function, and we know we don't
|
||||||
|
// do multifunction. Also, because we only support one PCI
|
||||||
|
// bus, the bus 0, we don't need to add anything to the
|
||||||
|
// global device ID.
|
||||||
|
let iommu_id = pci_bus.next_device_id() << 3;
|
||||||
|
|
||||||
|
// Because we determined the virtio-iommu b/d/f, we have to
|
||||||
|
// add the device to the PCI topology now. Otherwise, the
|
||||||
|
// b/d/f won't match the virtio-iommu device as expected.
|
||||||
|
DeviceManager::add_virtio_pci_device(
|
||||||
|
Box::new(iommu_device),
|
||||||
|
vm_info.memory,
|
||||||
|
&address_manager,
|
||||||
|
vm_info.vm_fd,
|
||||||
|
&mut pci_bus,
|
||||||
|
&interrupt_info,
|
||||||
|
&None,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
*virt_iommu = Some((iommu_id, iommu_attached_devices));
|
||||||
|
}
|
||||||
|
|
||||||
|
let pci_bus = Arc::new(Mutex::new(pci_bus));
|
||||||
|
let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(pci_bus.clone())));
|
||||||
|
address_manager
|
||||||
|
.io_bus
|
||||||
|
.insert(pci_config_io, 0xcf8, 0x8)
|
||||||
|
.map_err(DeviceManagerError::BusError)?;
|
||||||
|
let pci_config_mmio = Arc::new(Mutex::new(PciConfigMmio::new(pci_bus)));
|
||||||
|
address_manager
|
||||||
|
.mmio_bus
|
||||||
|
.insert(
|
||||||
|
pci_config_mmio,
|
||||||
|
arch::layout::PCI_MMCONFIG_START.0,
|
||||||
|
arch::layout::PCI_MMCONFIG_SIZE,
|
||||||
|
)
|
||||||
|
.map_err(DeviceManagerError::BusError)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn make_ioapic(
|
fn make_ioapic(
|
||||||
vm_info: &VmInfo,
|
vm_info: &VmInfo,
|
||||||
address_manager: &Arc<AddressManager>,
|
address_manager: &Arc<AddressManager>,
|
||||||
|
Loading…
Reference in New Issue
Block a user