Skip to content

Commit c69c23f

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 dcc927c commit c69c23f

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
@@ -1140,6 +1140,8 @@ pub struct DeviceManager {
11401140
ivshmem_device: Option<Arc<Mutex<devices::IvshmemDevice>>>,
11411141
}
11421142

1143+
/// Create per-PCI-segment MMIO allocators over the range `[start, end]`.
1144+
/// Both `start` and `end` are inclusive addresses.
11431145
fn create_mmio_allocators(
11441146
start: u64,
11451147
end: u64,
@@ -1157,7 +1159,15 @@ fn create_mmio_allocators(
11571159
for segment_id in 0..num_pci_segments as u64 {
11581160
let weight = weights[segment_id as usize] as u64;
11591161
let mmio_start = start + i * pci_segment_mmio_size;
1160-
let mmio_size = pci_segment_mmio_size * weight;
1162+
let is_last = segment_id == num_pci_segments as u64 - 1;
1163+
// Give the last segment all remaining space so no addresses
1164+
// near the top of the physical address space are lost to
1165+
// alignment truncation.
1166+
let mmio_size = if is_last {
1167+
end - mmio_start + 1
1168+
} else {
1169+
pci_segment_mmio_size * weight
1170+
};
11611171
let allocator = Arc::new(Mutex::new(
11621172
AddressAllocator::new(GuestAddress(mmio_start), mmio_size).unwrap(),
11631173
));
@@ -1218,7 +1228,8 @@ impl DeviceManager {
12181228
}
12191229

12201230
let start_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0;
1221-
let end_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE;
1231+
let end_of_mmio32_area =
1232+
layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE - 1;
12221233
let pci_mmio32_allocators = create_mmio_allocators(
12231234
start_of_mmio32_area,
12241235
end_of_mmio32_area,
@@ -5739,7 +5750,7 @@ mod unit_tests {
57395750

57405751
#[test]
57415752
fn test_create_mmio_allocators() {
5742-
let res = create_mmio_allocators(0x100000, 0x400000, 1, &[1], 4 << 10);
5753+
let res = create_mmio_allocators(0x100000, 0x3fffff, 1, &[1], 4 << 10);
57435754
assert_eq!(res.len(), 1);
57445755
assert_eq!(
57455756
res[0].lock().unwrap().base(),
@@ -5750,7 +5761,7 @@ mod unit_tests {
57505761
vm_memory::GuestAddress(0x3fffff)
57515762
);
57525763

5753-
let res = create_mmio_allocators(0x100000, 0x400000, 2, &[1, 1], 4 << 10);
5764+
let res = create_mmio_allocators(0x100000, 0x3fffff, 2, &[1, 1], 4 << 10);
57545765
assert_eq!(res.len(), 2);
57555766
assert_eq!(
57565767
res[0].lock().unwrap().base(),
@@ -5769,7 +5780,7 @@ mod unit_tests {
57695780
vm_memory::GuestAddress(0x3fffff)
57705781
);
57715782

5772-
let res = create_mmio_allocators(0x100000, 0x400000, 2, &[2, 1], 4 << 10);
5783+
let res = create_mmio_allocators(0x100000, 0x3fffff, 2, &[2, 1], 4 << 10);
57735784
assert_eq!(res.len(), 2);
57745785
assert_eq!(
57755786
res[0].lock().unwrap().base(),

0 commit comments

Comments
 (0)