diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index b1b4b3cf8..8b22c2b65 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -234,7 +234,7 @@ impl vm::Vm for KvmVm { .map_err(|e| vm::HypervisorVmError::SetGsiRouting(e.into())) } /// - /// Creates a memory region structure that can be used with set_user_memory_region + /// Creates a memory region structure that can be used with {create/remove}_user_memory_region /// fn make_user_memory_region( &self, @@ -259,14 +259,29 @@ impl vm::Vm for KvmVm { } } /// - /// Creates/modifies a guest physical memory slot. + /// Creates a guest physical memory region. /// - fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> vm::Result<()> { + fn create_user_memory_region(&self, user_memory_region: MemoryRegion) -> vm::Result<()> { // Safe because guest regions are guaranteed not to overlap. unsafe { self.fd .set_user_memory_region(user_memory_region) - .map_err(|e| vm::HypervisorVmError::SetUserMemory(e.into())) + .map_err(|e| vm::HypervisorVmError::CreateUserMemory(e.into())) + } + } + /// + /// Removes a guest physical memory region. + /// + fn remove_user_memory_region(&self, user_memory_region: MemoryRegion) -> vm::Result<()> { + let mut region = user_memory_region; + + // Setting the size to 0 means "remove" + region.memory_size = 0; + // Safe because guest regions are guaranteed not to overlap. + unsafe { + self.fd + .set_user_memory_region(region) + .map_err(|e| vm::HypervisorVmError::RemoveUserMemory(e.into())) } } /// diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 3c0120c13..059225126 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -798,11 +798,19 @@ impl vm::Vm for MshvVm { .map_err(|e| vm::HypervisorVmError::UnregisterIoEvent(e.into())) } - /// Creates/modifies a guest physical memory slot. - fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> vm::Result<()> { + /// Creates a guest physical memory region. + fn create_user_memory_region(&self, user_memory_region: MemoryRegion) -> vm::Result<()> { self.fd .map_user_memory(user_memory_region) - .map_err(|e| vm::HypervisorVmError::SetUserMemory(e.into()))?; + .map_err(|e| vm::HypervisorVmError::CreateUserMemory(e.into()))?; + Ok(()) + } + + /// Removes a guest physical memory region. + fn remove_user_memory_region(&self, user_memory_region: MemoryRegion) -> vm::Result<()> { + self.fd + .unmap_user_memory(user_memory_region) + .map_err(|e| vm::HypervisorVmError::RemoveUserMemory(e.into()))?; Ok(()) } diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index f2ba97a44..38a7e5c94 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -92,10 +92,15 @@ pub enum HypervisorVmError { #[error("Failed to set GSI routing: {0}")] SetGsiRouting(#[source] anyhow::Error), /// - /// Set user memory error + /// Create user memory error /// - #[error("Failed to set user memory: {0}")] - SetUserMemory(#[source] anyhow::Error), + #[error("Failed to create user memory: {0}")] + CreateUserMemory(#[source] anyhow::Error), + /// + /// Remove user memory region error + /// + #[error("Failed to remove user memory: {0}")] + RemoveUserMemory(#[source] anyhow::Error), /// /// Create device error /// @@ -218,7 +223,7 @@ pub trait Vm: Send + Sync { fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> Result<()>; /// Sets the GSI routing table entries, overwriting any previously set fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> Result<()>; - /// Creates a memory region structure that can be used with set_user_memory_region + /// Creates a memory region structure that can be used with {create/remove}_user_memory_region fn make_user_memory_region( &self, slot: u32, @@ -228,8 +233,10 @@ pub trait Vm: Send + Sync { readonly: bool, log_dirty_pages: bool, ) -> MemoryRegion; - /// Creates/modifies a guest physical memory slot. - fn set_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; + /// Creates a guest physical memory slot. + fn create_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; + /// Removes a guest physical memory slot. + fn remove_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; #[cfg(feature = "kvm")] /// Creates an emulated device in the kernel. fn create_device(&self, device: &mut CreateDevice) -> Result>; diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index 50f70ef99..eaa708559 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -679,7 +679,7 @@ impl VfioPciDevice { false, ); - vm.set_user_memory_region(mem_region) + vm.create_user_memory_region(mem_region) .map_err(|e| VfioPciError::MapRegionGuest(e.into()))?; // Update the region with memory mapped info. @@ -703,13 +703,13 @@ impl VfioPciDevice { let r = self.vm.make_user_memory_region( mem_slot, region.start.raw_value() + mmap_offset, - 0, + mmap_size as u64, host_addr as u64, false, false, ); - if let Err(e) = self.vm.set_user_memory_region(r) { + if let Err(e) = self.vm.remove_user_memory_region(r) { error!("Could not remove the userspace memory region: {}", e); } @@ -1137,14 +1137,14 @@ impl PciDevice for VfioPciDevice { let old_mem_region = self.vm.make_user_memory_region( mem_slot, old_base + mmap_offset, - 0, + mmap_size as u64, host_addr as u64, false, false, ); self.vm - .set_user_memory_region(old_mem_region) + .remove_user_memory_region(old_mem_region) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; // Insert new region @@ -1158,7 +1158,7 @@ impl PciDevice for VfioPciDevice { ); self.vm - .set_user_memory_region(new_mem_region) + .create_user_memory_region(new_mem_region) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; } } diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 2b4222e8c..3553578b8 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -727,20 +727,19 @@ impl DeviceRelocation for AddressManager { let mut virtio_dev = virtio_dev.lock().unwrap(); if let Some(mut shm_regions) = virtio_dev.get_shm_regions() { if shm_regions.addr.raw_value() == old_base { - // Remove old region from KVM by passing a size of 0. let mem_region = self.vm.make_user_memory_region( shm_regions.mem_slot, old_base, - 0, + shm_regions.len, shm_regions.host_addr, false, false, ); - self.vm.set_user_memory_region(mem_region).map_err(|e| { + self.vm.remove_user_memory_region(mem_region).map_err(|e| { io::Error::new( io::ErrorKind::Other, - format!("failed to set user memory region: {:?}", e), + format!("failed to remove user memory region: {:?}", e), ) })?; @@ -754,10 +753,10 @@ impl DeviceRelocation for AddressManager { false, ); - self.vm.set_user_memory_region(mem_region).map_err(|e| { + self.vm.create_user_memory_region(mem_region).map_err(|e| { io::Error::new( io::ErrorKind::Other, - format!("failed to set user memory regions: {:?}", e), + format!("failed to create user memory regions: {:?}", e), ) })?; diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index 5e6dd7209..a1a2cb1e8 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -176,8 +176,11 @@ pub enum Error { /// The requested hotplug memory addition is not a valid size InvalidSize, - /// Failed to set the user memory region. - SetUserMemoryRegion(hypervisor::HypervisorVmError), + /// Failed to create the user memory region. + CreateUserMemoryRegion(hypervisor::HypervisorVmError), + + /// Failed to remove the user memory region. + RemoveUserMemoryRegion(hypervisor::HypervisorVmError), /// Failed to EventFd. EventFdFail(io::Error), @@ -1212,8 +1215,8 @@ impl MemoryManager { ); self.vm - .set_user_memory_region(mem_region) - .map_err(Error::SetUserMemoryRegion)?; + .create_user_memory_region(mem_region) + .map_err(Error::CreateUserMemoryRegion)?; // Mark the pages as mergeable if explicitly asked for. if mergeable { @@ -1259,15 +1262,15 @@ impl MemoryManager { let mem_region = self.vm.make_user_memory_region( slot, guest_phys_addr, - 0, /* memory_size -- using 0 removes this slot */ + memory_size, userspace_addr, false, /* readonly -- don't care */ false, /* log dirty */ ); self.vm - .set_user_memory_region(mem_region) - .map_err(Error::SetUserMemoryRegion)?; + .remove_user_memory_region(mem_region) + .map_err(Error::RemoveUserMemoryRegion)?; // Mark the pages as unmergeable if there were previously marked as // mergeable. diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 553fa2fcf..cd7de6ae0 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -2551,7 +2551,7 @@ pub fn test_vm() { false, ); - vm.set_user_memory_region(mem_region) + vm.create_user_memory_region(mem_region) .expect("Cannot configure guest memory"); } mem.write_slice(&code, load_addr)