From b475965632bc2c8afda4522c2bd635dde24d3b73 Mon Sep 17 00:00:00 2001 From: Jianyong Wu Date: Fri, 19 May 2023 08:06:37 +0000 Subject: [PATCH] vfio: align memory region size and address to PAGE_SIZE In current implementation, memory region used in vfio is assumed to align to 4k which may cause error when the PAGE_SIZE is not 4k, like on Arm, it can be 16k and 64k. Remove this assumption and align memory resource used by vfio to PAGE_SIZE then vfio can run on host with 64k PAGE_SIZE. Fixes: #5292 Signed-off-by: Jianyong Wu (cherry picked from commit eca75dcfc9babbf8479ad3963ddddaca20cccd00) --- pci/src/vfio.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index de2948b33..c1a00b756 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -12,6 +12,7 @@ use crate::{ use anyhow::anyhow; use byteorder::{ByteOrder, LittleEndian}; use hypervisor::HypervisorVmError; +use libc::{sysconf, _SC_PAGESIZE}; use std::any::Any; use std::collections::{BTreeMap, HashMap}; use std::io; @@ -571,7 +572,12 @@ impl VfioCommon { PciBarRegionType::Memory64BitRegion => { // BAR allocation must be naturally aligned mmio_allocator - .allocate(restored_bar_addr, region_size, Some(region_size)) + .allocate( + restored_bar_addr, + region_size, + // SAFETY: FFI call. Trivially safe. + Some(unsafe { sysconf(_SC_PAGESIZE) as GuestUsize }), + ) .ok_or(PciDeviceError::IoAllocationFailed(region_size))? } }; @@ -1278,8 +1284,10 @@ impl VfioPciDevice { self.iommu_attached } - fn align_4k(address: u64) -> u64 { - (address + 0xfff) & 0xffff_ffff_ffff_f000 + fn align_page_size(address: u64) -> u64 { + // SAFETY: FFI call. Trivially safe. + let page_size = unsafe { sysconf(_SC_PAGESIZE) as u64 }; + (address + page_size - 1) & !(page_size - 1) } fn is_4k_aligned(address: u64) -> bool { @@ -1339,6 +1347,7 @@ impl VfioPciDevice { let mut sparse_areas = Vec::new(); let mut current_offset = 0; for (range_offset, range_size) in inter_ranges { + let range_offset = Self::align_page_size(range_offset); if range_offset > current_offset { sparse_areas.push(VfioRegionSparseMmapArea { offset: current_offset, @@ -1346,13 +1355,13 @@ impl VfioPciDevice { }); } - current_offset = Self::align_4k(range_offset + range_size); + current_offset = Self::align_page_size(range_offset + range_size); } if region_size > current_offset { sparse_areas.push(VfioRegionSparseMmapArea { - offset: current_offset, - size: region_size - current_offset, + offset: Self::align_page_size(current_offset), + size: Self::align_page_size(region_size - current_offset), }); }