pci: vfio_user: Simplify 'unmap_mmio_regions()'
Instead of always creating a single large mmap for the MMIO region of a
BAR, we create multiple mmaps for the BARs that need multiple kvm user
memory regions. In this way, we can simplify 'unmap_mmio_regions()' (by
reusing information kept from 'MmioRegion::user_memory_region').
@@ -164,14 +164,26 @@ impl VfioUserPciDevice {
prot |= libc::PROT_WRITE;
}
+ let mmaps = if sparse_areas.is_empty() {
+ vec![vfio_region_sparse_mmap_area {
+ offset: 0,
+ size: mmio_region.length,
+ }]
+ } else {
+ sparse_areas
+ };
+
+ let mut user_memory_regions = Vec::new();
+ for s in mmaps.iter() {
let host_addr = unsafe {
libc::mmap(
null_mut(),
- mmio_region.length as usize,
+ s.size as usize,
prot,
libc::MAP_SHARED,
file_offset.as_ref().unwrap().file().as_raw_fd(),
- file_offset.as_ref().unwrap().start() as libc::off_t,
+ file_offset.as_ref().unwrap().start() as libc::off_t
+ + s.offset as libc::off_t,
)
};
@@ -183,26 +195,13 @@ impl VfioUserPciDevice {
continue;
}
- let mut user_memory_regions = Vec::new();
- if sparse_areas.is_empty() {
- user_memory_regions.push(UserMemoryRegion {
- slot: mem_slot(),
- start: mmio_region.start.0,
- size: mmio_region.length as u64,
- host_addr: host_addr as u64,
- })
- } else {
- for s in sparse_areas.iter() {
- user_memory_regions.push(UserMemoryRegion {
+ let user_memory_region = UserMemoryRegion {
slot: mem_slot(),
start: mmio_region.start.0 + s.offset,
size: s.size,
- host_addr: host_addr as u64 + s.offset,
- });
- }
+ host_addr: host_addr as u64,
};
- for user_memory_region in user_memory_regions.iter() {
let mem_region = vm.make_user_memory_region(
user_memory_region.slot,
user_memory_region.start,
@@ -214,10 +213,10 @@ impl VfioUserPciDevice {
vm.create_user_memory_region(mem_region)
.map_err(VfioUserPciDeviceError::MapRegionGuest)?;
+
+ user_memory_regions.push(user_memory_region);
}
- mmio_region.host_addr = Some(host_addr as u64);
- mmio_region.mmap_size = Some(mmio_region.length as usize);
mmio_region.user_memory_regions = user_memory_regions;
}
}
@@ -241,12 +240,14 @@ impl VfioUserPciDevice {
if let Err(e) = self.vm.remove_user_memory_region(r) {
error!("Could not remove the userspace memory region: {}", e);
}
- }
- if let (Some(host_addr), Some(mmap_size)) =
- (mmio_region.host_addr, mmio_region.mmap_size)
- {
- let ret = unsafe { libc::munmap(host_addr as *mut libc::c_void, mmap_size) };
+ // Remove mmaps
+ let ret = unsafe {
+ libc::munmap(
+ user_memory_region.host_addr as *mut libc::c_void,
+ user_memory_region.size as usize,
+ )
+ };
if ret != 0 {
error!(
"Could not unmap region {}, error:{}",
