From 653087d7a31dd86978c68e3ba67892a3198d6746 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Tue, 9 Jun 2020 13:58:26 +0200 Subject: [PATCH] vmm: Reduce MMIO address space by 4KiB In order to workaround a Linux bug that happens when we place devices at the end of the physical address space on recent hardware (52 bits limit) we reduce the MMIO address space by one 4k page. This way, nothing gets allocated in the last 4k of the address space, which is negligible given the amount of space in the address space. Signed-off-by: Sebastien Boeuf --- vmm/src/memory_manager.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index 07b06d2c9..463e9798f 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -139,6 +139,13 @@ const LENGTH_OFFSET_HIGH: u64 = 0xC; const STATUS_OFFSET: u64 = 0x14; const SELECTION_OFFSET: u64 = 0; +// The MMIO address space size is substracted with the size of a 4k page. This +// is done on purpose to workaround a Linux bug when the VMM allocates devices +// at the end of the addressable space. +fn mmio_address_space_size() -> u64 { + (1 << get_host_cpu_phys_bits()) - 0x1000 +} + impl BusDevice for MemoryManager { fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { if self.selected_slot < self.hotplug_slots.len() { @@ -257,7 +264,7 @@ impl MemoryManager { let guest_memory = GuestMemoryMmap::from_arc_regions(mem_regions).map_err(Error::GuestMemory)?; - let end_of_device_area = GuestAddress((1 << get_host_cpu_phys_bits()) - 1); + let end_of_device_area = GuestAddress(mmio_address_space_size() - 1); let mut start_of_device_area = MemoryManager::start_addr(guest_memory.last_addr(), false); @@ -295,13 +302,13 @@ impl MemoryManager { hotplug_slots.resize_with(HOTPLUG_COUNT, HotPlugState::default); #[cfg(target_arch = "x86_64")] - // Let's allocate 64 GiB of addressable MMIO space, starting at 0. + // Both MMIO and PIO address spaces start at address 0. let allocator = Arc::new(Mutex::new( SystemAllocator::new( GuestAddress(0), 1 << 16 as GuestUsize, GuestAddress(0), - 1 << get_host_cpu_phys_bits(), + mmio_address_space_size(), layout::MEM_32BIT_RESERVED_START, layout::MEM_32BIT_DEVICES_SIZE, vec![GsiApic::new(