From 50bac1694f5bb305f00f02dc257896536eac5e0f Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 13 Dec 2024 12:55:33 +0100 Subject: [PATCH] vmm: support PCI I/O regions on all architectures While non-Intel CPU architectures don't have a special concept of IO address space, support for PCI I/O regions is still needed to be able to handle PCI devices that use them. With this change, I'm able to pass through an e1000e device from QEMU to a cloud-hypervisor VM on aarch64 and use it in the cloud-hypervisor guest. Previously, it would hit the unimplemented!(). Signed-off-by: Alyssa Ross --- pci/src/bus.rs | 5 +---- pci/src/vfio.rs | 7 ------ vm-allocator/src/system.rs | 12 ++++------ vmm/src/device_manager.rs | 46 ++++++++++++++------------------------ vmm/src/memory_manager.rs | 10 ++------- vmm/src/vm.rs | 2 -- 6 files changed, 24 insertions(+), 58 deletions(-) diff --git a/pci/src/bus.rs b/pci/src/bus.rs index 906d8f683..d522f18ce 100644 --- a/pci/src/bus.rs +++ b/pci/src/bus.rs @@ -125,19 +125,16 @@ impl PciBus { pub fn register_mapping( &self, dev: Arc, - #[cfg(target_arch = "x86_64")] io_bus: &Bus, + io_bus: &Bus, mmio_bus: &Bus, bars: Vec, ) -> Result<()> { for bar in bars { match bar.region_type() { PciBarRegionType::IoRegion => { - #[cfg(target_arch = "x86_64")] io_bus .insert(dev.clone(), bar.addr(), bar.size()) .map_err(PciRootError::PioInsert)?; - #[cfg(not(target_arch = "x86_64"))] - error!("I/O region is not supported"); } PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => { mmio_bus diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index cd468e8dc..7308c0ca6 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -713,11 +713,7 @@ impl VfioCommon { let bar_addr = match region_type { PciBarRegionType::IoRegion => { - #[cfg(not(target_arch = "x86_64"))] - unimplemented!(); - // The address needs to be 4 bytes aligned. - #[cfg(target_arch = "x86_64")] allocator .lock() .unwrap() @@ -795,10 +791,7 @@ impl VfioCommon { for region in self.mmio_regions.iter() { match region.type_ { PciBarRegionType::IoRegion => { - #[cfg(target_arch = "x86_64")] allocator.free_io_addresses(region.start, region.length); - #[cfg(not(target_arch = "x86_64"))] - error!("I/O region is not supported"); } PciBarRegionType::Memory32BitRegion => { mmio32_allocator.free(region.start, region.length); diff --git a/vm-allocator/src/system.rs b/vm-allocator/src/system.rs index adb75185b..0fd159617 100644 --- a/vm-allocator/src/system.rs +++ b/vm-allocator/src/system.rs @@ -26,8 +26,8 @@ use crate::page_size::get_page_size; /// # use vm_allocator::SystemAllocator; /// # use vm_memory::{Address, GuestAddress, GuestUsize}; /// let mut allocator = SystemAllocator::new( -/// #[cfg(target_arch = "x86_64")] GuestAddress(0x1000), -/// #[cfg(target_arch = "x86_64")] 0x10000, +/// GuestAddress(0x1000), +/// 0x10000, /// GuestAddress(0x10000000), 0x10000000, /// #[cfg(target_arch = "x86_64")] vec![GsiApic::new(5, 19)]).unwrap(); /// #[cfg(target_arch = "x86_64")] @@ -46,7 +46,6 @@ use crate::page_size::get_page_size; /// /// ``` pub struct SystemAllocator { - #[cfg(target_arch = "x86_64")] io_address_space: AddressAllocator, platform_mmio_address_space: AddressAllocator, gsi_allocator: GsiAllocator, @@ -63,14 +62,13 @@ impl SystemAllocator { /// * `apics` - (X86) Vector of APIC's. /// pub fn new( - #[cfg(target_arch = "x86_64")] io_base: GuestAddress, - #[cfg(target_arch = "x86_64")] io_size: GuestUsize, + io_base: GuestAddress, + io_size: GuestUsize, platform_mmio_base: GuestAddress, platform_mmio_size: GuestUsize, #[cfg(target_arch = "x86_64")] apics: Vec, ) -> Option { Some(SystemAllocator { - #[cfg(target_arch = "x86_64")] io_address_space: AddressAllocator::new(io_base, io_size)?, platform_mmio_address_space: AddressAllocator::new( platform_mmio_base, @@ -93,7 +91,6 @@ impl SystemAllocator { self.gsi_allocator.allocate_gsi().ok() } - #[cfg(target_arch = "x86_64")] /// Reserves a section of `size` bytes of IO address space. pub fn allocate_io_addresses( &mut self, @@ -119,7 +116,6 @@ impl SystemAllocator { ) } - #[cfg(target_arch = "x86_64")] /// Free an IO address range. /// We can only free a range if it matches exactly an already allocated range. pub fn free_io_addresses(&mut self, address: GuestAddress, size: GuestUsize) { diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 03ab7c244..8b3c20e57 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -536,7 +536,6 @@ impl Console { pub(crate) struct AddressManager { pub(crate) allocator: Arc>, - #[cfg(target_arch = "x86_64")] pub(crate) io_bus: Arc, pub(crate) mmio_bus: Arc, pub(crate) vm: Arc, @@ -556,33 +555,24 @@ impl DeviceRelocation for AddressManager { ) -> std::result::Result<(), std::io::Error> { match region_type { PciBarRegionType::IoRegion => { - #[cfg(target_arch = "x86_64")] - { - // Update system allocator - self.allocator - .lock() - .unwrap() - .free_io_addresses(GuestAddress(old_base), len as GuestUsize); + // Update system allocator + self.allocator + .lock() + .unwrap() + .free_io_addresses(GuestAddress(old_base), len as GuestUsize); - self.allocator - .lock() - .unwrap() - .allocate_io_addresses( - Some(GuestAddress(new_base)), - len as GuestUsize, - None, - ) - .ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "failed allocating new IO range") - })?; + self.allocator + .lock() + .unwrap() + .allocate_io_addresses(Some(GuestAddress(new_base)), len as GuestUsize, None) + .ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "failed allocating new IO range") + })?; - // Update PIO bus - self.io_bus - .update_range(old_base, len, new_base, len) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - } - #[cfg(target_arch = "aarch64")] - error!("I/O region is not supported"); + // Update PIO bus + self.io_bus + .update_range(old_base, len, new_base, len) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; } PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => { let allocators = if region_type == PciBarRegionType::Memory32BitRegion { @@ -992,7 +982,7 @@ fn create_mmio_allocators( impl DeviceManager { #[allow(clippy::too_many_arguments)] pub fn new( - #[cfg(target_arch = "x86_64")] io_bus: Arc, + io_bus: Arc, mmio_bus: Arc, vm: Arc, config: Arc>, @@ -1072,7 +1062,6 @@ impl DeviceManager { let address_manager = Arc::new(AddressManager { allocator: memory_manager.lock().unwrap().allocator(), - #[cfg(target_arch = "x86_64")] io_bus, mmio_bus, vm: vm.clone(), @@ -3512,7 +3501,6 @@ impl DeviceManager { pci_bus .register_mapping( bus_device, - #[cfg(target_arch = "x86_64")] self.address_manager.io_bus.as_ref(), self.address_manager.mmio_bus.as_ref(), bars.clone(), diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index 1b684716b..a4bc741fc 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -1159,14 +1159,8 @@ impl MemoryManager { let allocator = Arc::new(Mutex::new( SystemAllocator::new( - #[cfg(target_arch = "x86_64")] - { - GuestAddress(0) - }, - #[cfg(target_arch = "x86_64")] - { - 1 << 16 - }, + GuestAddress(0), + 1 << 16, start_of_platform_device_area, PLATFORM_DEVICE_AREA_SIZE, #[cfg(target_arch = "x86_64")] diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 450af5e45..e8a538300 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -531,7 +531,6 @@ impl Vm { let stop_on_boot = false; let memory = memory_manager.lock().unwrap().guest_memory(); - #[cfg(target_arch = "x86_64")] let io_bus = Arc::new(Bus::new()); let mmio_bus = Arc::new(Bus::new()); @@ -622,7 +621,6 @@ impl Vm { let dynamic = true; let device_manager = DeviceManager::new( - #[cfg(target_arch = "x86_64")] io_bus, mmio_bus, vm.clone(),