mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-07-04 17:02:36 +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();
|
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 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
|
// Let every virtio-mem device handle the DMA map/unmap through the
|
||||||
// DMA handler provided.
|
// DMA handler provided.
|
||||||
for virtio_mem_device in self.virtio_mem_devices.iter() {
|
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 device_type = virtio_device.lock().unwrap().device_type();
|
||||||
let mut virtio_pci_device = VirtioPciDevice::new(
|
let mut virtio_pci_device = VirtioPciDevice::new(
|
||||||
|
@ -3510,6 +3522,7 @@ impl DeviceManager {
|
||||||
.map_err(DeviceManagerError::UpdateMemoryForVirtioDevice)?;
|
.map_err(DeviceManagerError::UpdateMemoryForVirtioDevice)?;
|
||||||
|
|
||||||
if let Some(dma_handler) = &handle.dma_handler {
|
if let Some(dma_handler) = &handle.dma_handler {
|
||||||
|
if !handle.iommu {
|
||||||
let gpa = new_region.start_addr().0;
|
let gpa = new_region.start_addr().0;
|
||||||
let size = new_region.len();
|
let size = new_region.len();
|
||||||
dma_handler
|
dma_handler
|
||||||
|
@ -3517,6 +3530,7 @@ impl DeviceManager {
|
||||||
.map_err(DeviceManagerError::VirtioDmaMap)?;
|
.map_err(DeviceManagerError::VirtioDmaMap)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Take care of updating the memory for VFIO PCI devices.
|
// Take care of updating the memory for VFIO PCI devices.
|
||||||
if let Some(vfio_container) = &self.vfio_container {
|
if let Some(vfio_container) = &self.vfio_container {
|
||||||
|
@ -3697,6 +3711,13 @@ impl DeviceManager {
|
||||||
device_tree.remove(child);
|
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
|
let pci_device_handle = pci_device_node
|
||||||
.pci_device_handle
|
.pci_device_handle
|
||||||
.ok_or(DeviceManagerError::MissingPciDevice)?;
|
.ok_or(DeviceManagerError::MissingPciDevice)?;
|
||||||
|
@ -3720,6 +3741,7 @@ impl DeviceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(dma_handler) = dev.dma_handler() {
|
if let Some(dma_handler) = dev.dma_handler() {
|
||||||
|
if !iommu_attached {
|
||||||
for (_, zone) in self.memory_manager.lock().unwrap().memory_zones().iter() {
|
for (_, zone) in self.memory_manager.lock().unwrap().memory_zones().iter() {
|
||||||
for region in zone.regions() {
|
for region in zone.regions() {
|
||||||
let iova = region.start_addr().0;
|
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 PciDevice>>,
|
||||||
Arc::clone(&virtio_pci_device) as Arc<Mutex<dyn BusDevice>>,
|
Arc::clone(&virtio_pci_device) as Arc<Mutex<dyn BusDevice>>,
|
||||||
Some(dev.virtio_device()),
|
Some(dev.virtio_device()),
|
||||||
dev.dma_handler().is_some(),
|
dev.dma_handler().is_some() && !iommu_attached,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
PciDeviceHandle::VfioUser(vfio_user_pci_device) => {
|
PciDeviceHandle::VfioUser(vfio_user_pci_device) => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user