diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 0ae852644..77ef0cc42 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1140,6 +1140,8 @@ pub struct DeviceManager { ivshmem_device: Option>>, } +/// Create per-PCI-segment MMIO allocators over the range `[start, end]`. +/// Both `start` and `end` are inclusive addresses. fn create_mmio_allocators( start: u64, end: u64, @@ -1157,7 +1159,15 @@ fn create_mmio_allocators( for segment_id in 0..num_pci_segments as u64 { let weight = weights[segment_id as usize] as u64; let mmio_start = start + i * pci_segment_mmio_size; - let mmio_size = pci_segment_mmio_size * weight; + let is_last = segment_id == num_pci_segments as u64 - 1; + // Give the last segment all remaining space so no addresses + // near the top of the physical address space are lost to + // alignment truncation. + let mmio_size = if is_last { + end - mmio_start + 1 + } else { + pci_segment_mmio_size * weight + }; let allocator = Arc::new(Mutex::new( AddressAllocator::new(GuestAddress(mmio_start), mmio_size).unwrap(), )); @@ -1218,7 +1228,8 @@ impl DeviceManager { } let start_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0; - let end_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE; + let end_of_mmio32_area = + layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE - 1; let pci_mmio32_allocators = create_mmio_allocators( start_of_mmio32_area, end_of_mmio32_area, @@ -5739,7 +5750,7 @@ mod unit_tests { #[test] fn test_create_mmio_allocators() { - let res = create_mmio_allocators(0x100000, 0x400000, 1, &[1], 4 << 10); + let res = create_mmio_allocators(0x100000, 0x3fffff, 1, &[1], 4 << 10); assert_eq!(res.len(), 1); assert_eq!( res[0].lock().unwrap().base(), @@ -5750,7 +5761,7 @@ mod unit_tests { vm_memory::GuestAddress(0x3fffff) ); - let res = create_mmio_allocators(0x100000, 0x400000, 2, &[1, 1], 4 << 10); + let res = create_mmio_allocators(0x100000, 0x3fffff, 2, &[1, 1], 4 << 10); assert_eq!(res.len(), 2); assert_eq!( res[0].lock().unwrap().base(), @@ -5769,7 +5780,7 @@ mod unit_tests { vm_memory::GuestAddress(0x3fffff) ); - let res = create_mmio_allocators(0x100000, 0x400000, 2, &[2, 1], 4 << 10); + let res = create_mmio_allocators(0x100000, 0x3fffff, 2, &[2, 1], 4 << 10); assert_eq!(res.len(), 2); assert_eq!( res[0].lock().unwrap().base(),