mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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>
This commit is contained in:
@@ -1140,6 +1140,8 @@ pub struct DeviceManager {
|
||||
ivshmem_device: Option<Arc<Mutex<devices::IvshmemDevice>>>,
|
||||
}
|
||||
|
||||
/// 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(),
|
||||
|
||||
Reference in New Issue
Block a user