Skip to content

Commit 6fb6283

Browse files
committed
vmm: extend last MMIO64 allocator to cover full range
The MMIO64 allocator size is computed with alignment truncation: size = (range / alignment) * alignment This loses up to one alignment unit (4 GiB) at the top of the address space. When a guest (Windows with virtio-win 0.1.285) programs a BAR near the top of the physical address space, the allocation fails because the address falls in the truncated gap. Give the last PCI segment allocator all remaining space up to the end of the device area, so no addresses are lost. The `end` parameter of create_mmio_allocators() is an inclusive address (the last valid byte). Fix the 32-bit caller and tests to pass inclusive values, consistent with the 64-bit caller which already uses the inclusive end_of_device_area(). Signed-off-by: CMGS <ilskdw@gmail.com>
1 parent 88bde66 commit 6fb6283

1 file changed

Lines changed: 16 additions & 5 deletions

File tree

vmm/src/device_manager.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,8 @@ pub struct DeviceManager {
11271127
ivshmem_device: Option<Arc<Mutex<devices::IvshmemDevice>>>,
11281128
}
11291129

1130+
/// Create per-PCI-segment MMIO allocators over the range `[start, end]`.
1131+
/// Both `start` and `end` are inclusive addresses.
11301132
fn create_mmio_allocators(
11311133
start: u64,
11321134
end: u64,
@@ -1144,7 +1146,15 @@ fn create_mmio_allocators(
11441146
for segment_id in 0..num_pci_segments as u64 {
11451147
let weight = weights[segment_id as usize] as u64;
11461148
let mmio_start = start + i * pci_segment_mmio_size;
1147-
let mmio_size = pci_segment_mmio_size * weight;
1149+
let is_last = segment_id == num_pci_segments as u64 - 1;
1150+
// Give the last segment all remaining space so no addresses
1151+
// near the top of the physical address space are lost to
1152+
// alignment truncation.
1153+
let mmio_size = if is_last {
1154+
end - mmio_start + 1
1155+
} else {
1156+
pci_segment_mmio_size * weight
1157+
};
11481158
let allocator = Arc::new(Mutex::new(
11491159
AddressAllocator::new(GuestAddress(mmio_start), mmio_size).unwrap(),
11501160
));
@@ -1205,7 +1215,8 @@ impl DeviceManager {
12051215
}
12061216

12071217
let start_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0;
1208-
let end_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE;
1218+
let end_of_mmio32_area =
1219+
layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE - 1;
12091220
let pci_mmio32_allocators = create_mmio_allocators(
12101221
start_of_mmio32_area,
12111222
end_of_mmio32_area,
@@ -5695,7 +5706,7 @@ mod unit_tests {
56955706

56965707
#[test]
56975708
fn test_create_mmio_allocators() {
5698-
let res = create_mmio_allocators(0x100000, 0x400000, 1, &[1], 4 << 10);
5709+
let res = create_mmio_allocators(0x100000, 0x3fffff, 1, &[1], 4 << 10);
56995710
assert_eq!(res.len(), 1);
57005711
assert_eq!(
57015712
res[0].lock().unwrap().base(),
@@ -5706,7 +5717,7 @@ mod unit_tests {
57065717
vm_memory::GuestAddress(0x3fffff)
57075718
);
57085719

5709-
let res = create_mmio_allocators(0x100000, 0x400000, 2, &[1, 1], 4 << 10);
5720+
let res = create_mmio_allocators(0x100000, 0x3fffff, 2, &[1, 1], 4 << 10);
57105721
assert_eq!(res.len(), 2);
57115722
assert_eq!(
57125723
res[0].lock().unwrap().base(),
@@ -5725,7 +5736,7 @@ mod unit_tests {
57255736
vm_memory::GuestAddress(0x3fffff)
57265737
);
57275738

5728-
let res = create_mmio_allocators(0x100000, 0x400000, 2, &[2, 1], 4 << 10);
5739+
let res = create_mmio_allocators(0x100000, 0x3fffff, 2, &[2, 1], 4 << 10);
57295740
assert_eq!(res.len(), 2);
57305741
assert_eq!(
57315742
res[0].lock().unwrap().base(),

0 commit comments

Comments
 (0)