vfio: Don't map guest memory for VFIO devices attached to vIOMMU

In case a VFIO devices is being attached behind a virtual IOMMU, we
should not automatically map the entire guest memory for the specific
device.

A VFIO device attached to the virtual IOMMU will be driven with IOVAs,
hence we should simply wait for the requests coming from the virtual
IOMMU.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2019-10-08 12:50:05 -07:00 committed by Samuel Ortiz
parent 63c30a6e79
commit 3acf9dfcf3
2 changed files with 24 additions and 13 deletions

View File

@ -578,6 +578,7 @@ pub struct VfioDevice {
regions: Vec<VfioRegion>,
irqs: HashMap<u32, VfioIrq>,
mem: Arc<RwLock<GuestMemoryMmap>>,
iommu_attached: bool,
}
impl VfioDevice {
@ -588,6 +589,7 @@ impl VfioDevice {
sysfspath: &Path,
device_fd: Arc<DeviceFd>,
mem: Arc<RwLock<GuestMemoryMmap>>,
iommu_attached: bool,
) -> Result<Self> {
let uuid_path: PathBuf = [sysfspath, Path::new("iommu_group")].iter().collect();
let group_path = uuid_path.read_link().map_err(|_| VfioError::InvalidPath)?;
@ -609,6 +611,7 @@ impl VfioDevice {
regions,
irqs,
mem,
iommu_attached,
})
}
@ -841,22 +844,26 @@ impl VfioDevice {
/// Add all guest memory regions into vfio container's iommu table,
/// then vfio kernel driver could access guest memory from gfn
pub fn setup_dma_map(&self) -> Result<()> {
self.mem.read().unwrap().with_regions(|_index, region| {
self.vfio_dma_map(
region.start_addr().raw_value(),
region.len() as u64,
region.as_ptr() as u64,
)
})?;
if !self.iommu_attached {
self.mem.read().unwrap().with_regions(|_index, region| {
self.vfio_dma_map(
region.start_addr().raw_value(),
region.len() as u64,
region.as_ptr() as u64,
)
})?;
}
Ok(())
}
/// remove all guest memory regions from vfio containers iommu table
/// then vfio kernel driver couldn't access this guest memory
pub fn unset_dma_map(&self) -> Result<()> {
self.mem.read().unwrap().with_regions(|_index, region| {
self.vfio_dma_unmap(region.start_addr().raw_value(), region.len() as u64)
})?;
if !self.iommu_attached {
self.mem.read().unwrap().with_regions(|_index, region| {
self.vfio_dma_unmap(region.start_addr().raw_value(), region.len() as u64)
})?;
}
Ok(())
}

View File

@ -999,9 +999,13 @@ impl DeviceManager {
// global device ID.
let device_id = pci.next_device_id() << 3;
let vfio_device =
VfioDevice::new(&device_cfg.path, device_fd.clone(), vm_info.memory.clone())
.map_err(DeviceManagerError::VfioCreate)?;
let vfio_device = VfioDevice::new(
&device_cfg.path,
device_fd.clone(),
vm_info.memory.clone(),
device_cfg.iommu,
)
.map_err(DeviceManagerError::VfioCreate)?;
if device_cfg.iommu {
if let Some(iommu) = iommu_device {