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,30 +3375,42 @@ 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 {
|
||||||
// Let every virtio-mem device handle the DMA map/unmap through the
|
if iommu_mapping.is_some() {
|
||||||
// DMA handler provided.
|
if let Some(iommu) = &self.iommu_device {
|
||||||
for virtio_mem_device in self.virtio_mem_devices.iter() {
|
iommu
|
||||||
virtio_mem_device
|
.lock()
|
||||||
.lock()
|
.unwrap()
|
||||||
.unwrap()
|
.add_external_mapping(pci_device_bdf.into(), dma_handler.clone());
|
||||||
.add_dma_mapping_handler(
|
} else {
|
||||||
VirtioMemMappingSource::Device(pci_device_bdf.into()),
|
return Err(DeviceManagerError::MissingVirtualIommu);
|
||||||
dma_handler.clone(),
|
}
|
||||||
)
|
} else {
|
||||||
.map_err(DeviceManagerError::AddDmaMappingHandlerVirtioMem)?;
|
// 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() {
|
||||||
|
virtio_mem_device
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.add_dma_mapping_handler(
|
||||||
|
VirtioMemMappingSource::Device(pci_device_bdf.into()),
|
||||||
|
dma_handler.clone(),
|
||||||
|
)
|
||||||
|
.map_err(DeviceManagerError::AddDmaMappingHandlerVirtioMem)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Do not register virtio-mem regions, as they are handled directly by
|
// Do not register virtio-mem regions, as they are handled directly by
|
||||||
// virtio-mem devices.
|
// virtio-mem devices.
|
||||||
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 gpa = region.start_addr().0;
|
let gpa = region.start_addr().0;
|
||||||
let size = region.len();
|
let size = region.len();
|
||||||
dma_handler
|
dma_handler
|
||||||
.map(gpa, gpa, size)
|
.map(gpa, gpa, size)
|
||||||
.map_err(DeviceManagerError::VirtioDmaMap)?;
|
.map_err(DeviceManagerError::VirtioDmaMap)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3510,11 +3522,13 @@ 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 {
|
||||||
let gpa = new_region.start_addr().0;
|
if !handle.iommu {
|
||||||
let size = new_region.len();
|
let gpa = new_region.start_addr().0;
|
||||||
dma_handler
|
let size = new_region.len();
|
||||||
.map(gpa, gpa, size)
|
dma_handler
|
||||||
.map_err(DeviceManagerError::VirtioDmaMap)?;
|
.map(gpa, gpa, size)
|
||||||
|
.map_err(DeviceManagerError::VirtioDmaMap)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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,13 +3741,15 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(dma_handler) = dev.dma_handler() {
|
if let Some(dma_handler) = dev.dma_handler() {
|
||||||
for (_, zone) in self.memory_manager.lock().unwrap().memory_zones().iter() {
|
if !iommu_attached {
|
||||||
for region in zone.regions() {
|
for (_, zone) in self.memory_manager.lock().unwrap().memory_zones().iter() {
|
||||||
let iova = region.start_addr().0;
|
for region in zone.regions() {
|
||||||
let size = region.len();
|
let iova = region.start_addr().0;
|
||||||
dma_handler
|
let size = region.len();
|
||||||
.unmap(iova, size)
|
dma_handler
|
||||||
.map_err(DeviceManagerError::VirtioDmaUnmap)?;
|
.unmap(iova, size)
|
||||||
|
.map_err(DeviceManagerError::VirtioDmaUnmap)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3735,7 +3758,7 @@ 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