From a5e2460d95e16958922e1461b105c296466bafa5 Mon Sep 17 00:00:00 2001 From: Andrew Carp Date: Thu, 21 Mar 2024 16:04:02 -0700 Subject: [PATCH] virtio-devices: Move VfioDmaMapping to be in the pci crate VfioUserDmaMapping is already in the pci crate, this moves VfioDmaMapping to match the behavior. This is a necessary change to allow the VfioDmaMapping trait to have access to MmioRegion memory without creating a circular dependency. The VfioDmaMapping trait needs to have access to mmio regions to map external devices over mmio (a follow-up commit). Signed-off-by: Andrew Carp --- pci/src/lib.rs | 2 +- pci/src/vfio.rs | 64 +++++++++++++++++++++++++++- vm-device/src/dma_mapping/mod.rs | 2 - vm-device/src/dma_mapping/vfio.rs | 70 ------------------------------- vmm/src/device_manager.rs | 5 +-- 5 files changed, 66 insertions(+), 77 deletions(-) delete mode 100644 vm-device/src/dma_mapping/vfio.rs diff --git a/pci/src/lib.rs b/pci/src/lib.rs index 4b24fcd03..3d4d7c40c 100644 --- a/pci/src/lib.rs +++ b/pci/src/lib.rs @@ -26,7 +26,7 @@ pub use self::device::{ }; pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig}; pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_CONFIG_ID, MSIX_TABLE_ENTRY_SIZE}; -pub use self::vfio::{VfioPciDevice, VfioPciError}; +pub use self::vfio::{VfioDmaMapping, VfioPciDevice, VfioPciError}; pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError}; use serde::de::Visitor; use std::fmt::{self, Display}; diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index 4502d1cb8..8c4c0d9b1 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -32,11 +32,12 @@ use vm_allocator::page_size::{ align_page_size_down, align_page_size_up, is_4k_aligned, is_4k_multiple, is_page_size_aligned, }; use vm_allocator::{AddressAllocator, SystemAllocator}; +use vm_device::dma_mapping::ExternalDmaMapping; use vm_device::interrupt::{ InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig, }; use vm_device::{BusDevice, Resource}; -use vm_memory::{Address, GuestAddress, GuestUsize}; +use vm_memory::{Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestUsize}; use vm_migration::{ Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped, }; @@ -1885,3 +1886,64 @@ impl Snapshottable for VfioPciDevice { } impl Transportable for VfioPciDevice {} impl Migratable for VfioPciDevice {} + +/// This structure implements the ExternalDmaMapping trait. It is meant to +/// be used when the caller tries to provide a way to update the mappings +/// associated with a specific VFIO container. +pub struct VfioDmaMapping { + container: Arc, + memory: Arc, +} + +impl VfioDmaMapping { + /// Create a DmaMapping object. + /// + /// # Parameters + /// * `container`: VFIO container object. + /// * `memory·: guest memory to mmap. + pub fn new(container: Arc, memory: Arc) -> Self { + VfioDmaMapping { container, memory } + } +} + +impl ExternalDmaMapping for VfioDmaMapping { + fn map(&self, iova: u64, gpa: u64, size: u64) -> std::result::Result<(), io::Error> { + let mem = self.memory.memory(); + let guest_addr = GuestAddress(gpa); + let user_addr = if mem.check_range(guest_addr, size as usize) { + mem.get_host_address(guest_addr).unwrap() as u64 + } else { + return Err(io::Error::new( + io::ErrorKind::Other, + format!( + "failed to convert guest address 0x{gpa:x} into \ + host user virtual address" + ), + )); + }; + + self.container + .vfio_dma_map(iova, size, user_addr) + .map_err(|e| { + io::Error::new( + io::ErrorKind::Other, + format!( + "failed to map memory for VFIO container, \ + iova 0x{iova:x}, gpa 0x{gpa:x}, size 0x{size:x}: {e:?}" + ), + ) + }) + } + + fn unmap(&self, iova: u64, size: u64) -> std::result::Result<(), io::Error> { + self.container.vfio_dma_unmap(iova, size).map_err(|e| { + io::Error::new( + io::ErrorKind::Other, + format!( + "failed to unmap memory for VFIO container, \ + iova 0x{iova:x}, size 0x{size:x}: {e:?}" + ), + ) + }) + } +} diff --git a/vm-device/src/dma_mapping/mod.rs b/vm-device/src/dma_mapping/mod.rs index 62b5ceb1c..134d8bdea 100644 --- a/vm-device/src/dma_mapping/mod.rs +++ b/vm-device/src/dma_mapping/mod.rs @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause -pub mod vfio; - /// Trait meant for triggering the DMA mapping update related to an external /// device not managed fully through virtio. It is dedicated to virtio-iommu /// in order to trigger the map update anytime the mapping is updated from the diff --git a/vm-device/src/dma_mapping/vfio.rs b/vm-device/src/dma_mapping/vfio.rs deleted file mode 100644 index aac86e30e..000000000 --- a/vm-device/src/dma_mapping/vfio.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright © 2021 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause - -use crate::dma_mapping::ExternalDmaMapping; -use std::io; -use std::sync::Arc; -use vfio_ioctls::VfioContainer; -use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemory}; - -/// This structure implements the ExternalDmaMapping trait. It is meant to -/// be used when the caller tries to provide a way to update the mappings -/// associated with a specific VFIO container. -pub struct VfioDmaMapping { - container: Arc, - memory: Arc, -} - -impl VfioDmaMapping { - /// Create a DmaMapping object. - /// - /// # Parameters - /// * `container`: VFIO container object. - /// * `memory·: guest memory to mmap. - pub fn new(container: Arc, memory: Arc) -> Self { - VfioDmaMapping { container, memory } - } -} - -impl ExternalDmaMapping for VfioDmaMapping { - fn map(&self, iova: u64, gpa: u64, size: u64) -> std::result::Result<(), io::Error> { - let mem = self.memory.memory(); - let guest_addr = GuestAddress(gpa); - let user_addr = if mem.check_range(guest_addr, size as usize) { - mem.get_host_address(guest_addr).unwrap() as u64 - } else { - return Err(io::Error::new( - io::ErrorKind::Other, - format!( - "failed to convert guest address 0x{gpa:x} into \ - host user virtual address" - ), - )); - }; - - self.container - .vfio_dma_map(iova, size, user_addr) - .map_err(|e| { - io::Error::new( - io::ErrorKind::Other, - format!( - "failed to map memory for VFIO container, \ - iova 0x{iova:x}, gpa 0x{gpa:x}, size 0x{size:x}: {e:?}" - ), - ) - }) - } - - fn unmap(&self, iova: u64, size: u64) -> std::result::Result<(), io::Error> { - self.container.vfio_dma_unmap(iova, size).map_err(|e| { - io::Error::new( - io::ErrorKind::Other, - format!( - "failed to unmap memory for VFIO container, \ - iova 0x{iova:x}, size 0x{size:x}: {e:?}" - ), - ) - }) - } -} diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index bad43d19f..bf31dc840 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -58,8 +58,8 @@ use libc::{ O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW, }; use pci::{ - DeviceRelocation, PciBarRegionType, PciBdf, PciDevice, VfioPciDevice, VfioUserDmaMapping, - VfioUserPciDevice, VfioUserPciDeviceError, + DeviceRelocation, PciBarRegionType, PciBdf, PciDevice, VfioDmaMapping, + VfioPciDevice, VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError, }; use rate_limiter::group::RateLimiterGroup; use seccompiler::SeccompAction; @@ -85,7 +85,6 @@ use virtio_devices::{ }; use virtio_devices::{Endpoint, IommuMapping}; use vm_allocator::{AddressAllocator, SystemAllocator}; -use vm_device::dma_mapping::vfio::VfioDmaMapping; use vm_device::dma_mapping::ExternalDmaMapping; use vm_device::interrupt::{ InterruptIndex, InterruptManager, LegacyIrqGroupConfig, MsiIrqGroupConfig,