From e4a034aef9631fd476afc60392204a4b715e1516 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Thu, 26 Mar 2020 14:05:27 +0100 Subject: [PATCH] vfio: Add support for memory hotplug Whenever the guest memory is extended, the IOMMU mappings related to each VFIO device must be updated. This allows subsequent RAM accesses to be authorized by the physical IOMMU for the newly added RAM region. Signed-off-by: Sebastien Boeuf --- vfio/src/vfio_device.rs | 14 +++++++++++++- vfio/src/vfio_pci.rs | 10 +++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/vfio/src/vfio_device.rs b/vfio/src/vfio_device.rs index 3e95295ae..e952f2086 100644 --- a/vfio/src/vfio_device.rs +++ b/vfio/src/vfio_device.rs @@ -25,7 +25,7 @@ use vfio_ioctls::*; use vm_device::{get_host_address_range, ExternalDmaMapping}; use vm_memory::{ Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap, - GuestMemoryRegion, + GuestMemoryRegion, GuestRegionMmap, }; use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::fam::FamStruct; @@ -873,6 +873,18 @@ impl VfioDevice { Ok(()) } + pub fn extend_dma_map(&self, new_region: &Arc) -> Result<()> { + if !self.iommu_attached { + self.vfio_dma_map( + new_region.start_addr().raw_value(), + new_region.len() as u64, + new_region.as_ptr() as u64, + ) + } else { + Ok(()) + } + } + /// Return the maximum numner of interrupts a VFIO device can request. /// This is used for pre-allocating the VFIO PCI routes. pub fn max_interrupts(&self) -> u32 { diff --git a/vfio/src/vfio_pci.rs b/vfio/src/vfio_pci.rs index d7a19f3c8..1582d5ea1 100644 --- a/vfio/src/vfio_pci.rs +++ b/vfio/src/vfio_pci.rs @@ -27,7 +27,7 @@ use vm_allocator::SystemAllocator; use vm_device::interrupt::{ InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig, }; -use vm_memory::{Address, GuestAddress, GuestUsize}; +use vm_memory::{Address, GuestAddress, GuestRegionMmap, GuestUsize}; use vmm_sys_util::eventfd::EventFd; #[derive(Debug)] @@ -41,6 +41,7 @@ pub enum VfioPciError { SetGsiRouting(kvm_ioctls::Error), MsiNotConfigured, MsixNotConfigured, + UpdateMemory(crate::VfioError), UpdateMsiEventFd, UpdateMsixEventFd, } @@ -62,6 +63,7 @@ impl fmt::Display for VfioPciError { VfioPciError::SetGsiRouting(e) => write!(f, "failed to set GSI routes for KVM: {}", e), VfioPciError::MsiNotConfigured => write!(f, "MSI interrupt not yet configured"), VfioPciError::MsixNotConfigured => write!(f, "MSI-X interrupt not yet configured"), + VfioPciError::UpdateMemory(e) => write!(f, "failed to update memory: {}", e), VfioPciError::UpdateMsiEventFd => write!(f, "failed to update MSI eventfd"), VfioPciError::UpdateMsixEventFd => write!(f, "failed to update MSI-X eventfd"), } @@ -610,6 +612,12 @@ impl VfioPciDevice { } } } + + pub fn update_memory(&self, new_region: &Arc) -> Result<()> { + self.device + .extend_dma_map(new_region) + .map_err(VfioPciError::UpdateMemory) + } } impl Drop for VfioPciDevice {