diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index ab775ba998..758647931f 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -1416,7 +1416,8 @@ pub struct VfioPciDevice { container: Arc, common: VfioCommon, iommu_attached: bool, - memory_slot: Arc u32 + Send + Sync>, + get_memory_slot: Arc u32 + Send + Sync>, + put_memory_slot: Arc, } impl VfioPciDevice { @@ -1431,7 +1432,8 @@ impl VfioPciDevice { legacy_interrupt_group: Option>, iommu_attached: bool, bdf: PciBdf, - memory_slot: Arc u32 + Send + Sync>, + get_memory_slot: Arc u32 + Send + Sync>, + put_memory_slot: Arc, snapshot: Option, x_nv_gpudirect_clique: Option, ) -> Result { @@ -1457,7 +1459,8 @@ impl VfioPciDevice { container, common, iommu_attached, - memory_slot, + get_memory_slot, + put_memory_slot, }; Ok(vfio_pci_device) @@ -1635,7 +1638,7 @@ impl VfioPciDevice { } let user_memory_region = UserMemoryRegion { - slot: (self.memory_slot)(), + slot: (self.get_memory_slot)(), start: region.start.0 + area.offset, size: area.size, host_addr: host_addr as u64, @@ -1699,6 +1702,8 @@ impl VfioPciDevice { error!("Could not remove the userspace memory region: {}", e); } + (self.put_memory_slot)(user_memory_region.slot); + // SAFETY: FFI call with correct arguments let ret = unsafe { libc::munmap( diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 4c9b65fd30..e0f7010a76 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -3422,6 +3422,7 @@ impl DeviceManager { }; let memory_manager = self.memory_manager.clone(); + let memory_manager2 = self.memory_manager.clone(); let vfio_pci_device = VfioPciDevice::new( vfio_name.clone(), @@ -3433,6 +3434,7 @@ impl DeviceManager { device_cfg.iommu, pci_device_bdf, Arc::new(move || memory_manager.lock().unwrap().allocate_memory_slot()), + Arc::new(move |x| memory_manager2.lock().unwrap().free_memory_slot(x)), vm_migration::snapshot_from_id(self.snapshot.as_ref(), vfio_name.as_str()), device_cfg.x_nv_gpudirect_clique, ) diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index 267bba5863..d9718aaa94 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -163,6 +163,7 @@ pub struct MemoryManager { boot_guest_memory: GuestMemoryMmap, guest_memory: GuestMemoryAtomic, next_memory_slot: u32, + memory_slots: Vec, start_of_device_area: GuestAddress, end_of_device_area: GuestAddress, end_of_ram_area: GuestAddress, @@ -1206,6 +1207,7 @@ impl MemoryManager { boot_guest_memory, guest_memory, next_memory_slot, + memory_slots: Vec::new(), start_of_device_area, end_of_device_area, end_of_ram_area, @@ -1729,12 +1731,29 @@ impl MemoryManager { self.end_of_device_area } + pub fn get_available_memory_slot(&self) -> u32 { + for i in &self.memory_slots { + if !self.memory_slots.contains(&(i + 1)) { + return *i + 1; + } + } + + *self.memory_slots.last().unwrap_or(&0) + } + pub fn allocate_memory_slot(&mut self) -> u32 { - let slot_id = self.next_memory_slot; - self.next_memory_slot += 1; + let slot_id = self.get_available_memory_slot(); + debug!("got memory slot id {}", slot_id); + self.memory_slots.push(slot_id); + self.memory_slots.sort(); slot_id } + pub fn free_memory_slot(&mut self, slot: u32) { + debug!("free memory slot {:?}", slot); + self.memory_slots.retain(|&x| x != slot); + } + pub fn create_userspace_mapping( &mut self, guest_phys_addr: u64,