mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
vmm: device_manager: Make virtio DMA mapping conditional on vIOMMU
In case the virtio device which requires DMA mapping is placed behind a virtual IOMMU, we shouldn't map/unmap any region manually. Instead, we provide the DMA handler to the virtio-iommu device so that it can trigger the proper mappings. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
a4f742277b
commit
9d46890dc0
@ -3375,8 +3375,19 @@ impl DeviceManager {
|
||||
|
||||
let memory = self.memory_manager.lock().unwrap().guest_memory();
|
||||
|
||||
// Map DMA ranges if a DMA handler is available
|
||||
// Map DMA ranges if a DMA handler is available and if the device is
|
||||
// not attached to a virtual IOMMU.
|
||||
if let Some(dma_handler) = &dma_handler {
|
||||
if iommu_mapping.is_some() {
|
||||
if let Some(iommu) = &self.iommu_device {
|
||||
iommu
|
||||
.lock()
|
||||
.unwrap()
|
||||
.add_external_mapping(pci_device_bdf.into(), dma_handler.clone());
|
||||
} else {
|
||||
return Err(DeviceManagerError::MissingVirtualIommu);
|
||||
}
|
||||
} else {
|
||||
// Let every virtio-mem device handle the DMA map/unmap through the
|
||||
// DMA handler provided.
|
||||
for virtio_mem_device in self.virtio_mem_devices.iter() {
|
||||
@ -3402,6 +3413,7 @@ impl DeviceManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let device_type = virtio_device.lock().unwrap().device_type();
|
||||
let mut virtio_pci_device = VirtioPciDevice::new(
|
||||
@ -3510,6 +3522,7 @@ impl DeviceManager {
|
||||
.map_err(DeviceManagerError::UpdateMemoryForVirtioDevice)?;
|
||||
|
||||
if let Some(dma_handler) = &handle.dma_handler {
|
||||
if !handle.iommu {
|
||||
let gpa = new_region.start_addr().0;
|
||||
let size = new_region.len();
|
||||
dma_handler
|
||||
@ -3517,6 +3530,7 @@ impl DeviceManager {
|
||||
.map_err(DeviceManagerError::VirtioDmaMap)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Take care of updating the memory for VFIO PCI devices.
|
||||
if let Some(vfio_container) = &self.vfio_container {
|
||||
@ -3697,6 +3711,13 @@ impl DeviceManager {
|
||||
device_tree.remove(child);
|
||||
}
|
||||
|
||||
let mut iommu_attached = false;
|
||||
if let Some((_, iommu_attached_devices)) = &self.iommu_attached_devices {
|
||||
if iommu_attached_devices.contains(&pci_device_bdf) {
|
||||
iommu_attached = true;
|
||||
}
|
||||
}
|
||||
|
||||
let pci_device_handle = pci_device_node
|
||||
.pci_device_handle
|
||||
.ok_or(DeviceManagerError::MissingPciDevice)?;
|
||||
@ -3720,6 +3741,7 @@ impl DeviceManager {
|
||||
}
|
||||
|
||||
if let Some(dma_handler) = dev.dma_handler() {
|
||||
if !iommu_attached {
|
||||
for (_, zone) in self.memory_manager.lock().unwrap().memory_zones().iter() {
|
||||
for region in zone.regions() {
|
||||
let iova = region.start_addr().0;
|
||||
@ -3730,12 +3752,13 @@ impl DeviceManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
Arc::clone(&virtio_pci_device) as Arc<Mutex<dyn PciDevice>>,
|
||||
Arc::clone(&virtio_pci_device) as Arc<Mutex<dyn BusDevice>>,
|
||||
Some(dev.virtio_device()),
|
||||
dev.dma_handler().is_some(),
|
||||
dev.dma_handler().is_some() && !iommu_attached,
|
||||
)
|
||||
}
|
||||
PciDeviceHandle::VfioUser(vfio_user_pci_device) => {
|
||||
|
Loading…
Reference in New Issue
Block a user