Skip to content

Commit

Permalink
vmm: fix memory slot over KVM_USER_MEM_SLOTS
Browse files Browse the repository at this point in the history
When adding vfio passthrough devices cloud hypervisor allocate a new
memory slot in map_mmio_regions. As we +1 each time as new memory slot,
it will fail as the memory slot over KVM_USER_MEM_SLOTS in kernel when
calling KVM_SET_USER_MEMORY_REGION ioctl.

This patch introduces a vector to save the memory slots allocated, and
return the minimal available memory slot to caller to fix this issue.

Signed-off-by: Yi Wang <foxywang@tencent.com>
  • Loading branch information
up2wing committed Nov 21, 2024
1 parent 3c05626 commit 727b514
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 6 deletions.
13 changes: 9 additions & 4 deletions pci/src/vfio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1416,7 +1416,8 @@ pub struct VfioPciDevice {
container: Arc<VfioContainer>,
common: VfioCommon,
iommu_attached: bool,
memory_slot: Arc<dyn Fn() -> u32 + Send + Sync>,
get_memory_slot: Arc<dyn Fn() -> u32 + Send + Sync>,
put_memory_slot: Arc<dyn Fn(u32) + Send + Sync>,
}

impl VfioPciDevice {
Expand All @@ -1431,7 +1432,8 @@ impl VfioPciDevice {
legacy_interrupt_group: Option<Arc<dyn InterruptSourceGroup>>,
iommu_attached: bool,
bdf: PciBdf,
memory_slot: Arc<dyn Fn() -> u32 + Send + Sync>,
get_memory_slot: Arc<dyn Fn() -> u32 + Send + Sync>,
put_memory_slot: Arc<dyn Fn(u32) + Send + Sync>,
snapshot: Option<Snapshot>,
x_nv_gpudirect_clique: Option<u8>,
) -> Result<Self, VfioPciError> {
Expand All @@ -1457,7 +1459,8 @@ impl VfioPciDevice {
container,
common,
iommu_attached,
memory_slot,
get_memory_slot,
put_memory_slot,
};

Ok(vfio_pci_device)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions vmm/src/device_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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,
)
Expand Down
23 changes: 21 additions & 2 deletions vmm/src/memory_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ pub struct MemoryManager {
boot_guest_memory: GuestMemoryMmap,
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
next_memory_slot: u32,
memory_slots: Vec<u32>,
start_of_device_area: GuestAddress,
end_of_device_area: GuestAddress,
end_of_ram_area: GuestAddress,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 727b514

Please sign in to comment.