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 <acarp@crusoeenergy.com>
This commit is contained in:
Andrew Carp 2024-03-21 16:04:02 -07:00
parent 44fbd60b7a
commit f50081df00
No known key found for this signature in database
5 changed files with 66 additions and 77 deletions

View File

@ -26,7 +26,7 @@ pub use self::device::{
}; };
pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig}; 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::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}; pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError};
use serde::de::Visitor; use serde::de::Visitor;
use std::fmt::{self, Display}; use std::fmt::{self, Display};

View File

@ -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, 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_allocator::{AddressAllocator, SystemAllocator};
use vm_device::dma_mapping::ExternalDmaMapping;
use vm_device::interrupt::{ use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig, InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
}; };
use vm_device::{BusDevice, Resource}; use vm_device::{BusDevice, Resource};
use vm_memory::{Address, GuestAddress, GuestUsize}; use vm_memory::{Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestUsize};
use vm_migration::{ use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped, Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
}; };
@ -1885,3 +1886,64 @@ impl Snapshottable for VfioPciDevice {
} }
impl Transportable for VfioPciDevice {} impl Transportable for VfioPciDevice {}
impl Migratable 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<M: GuestAddressSpace> {
container: Arc<VfioContainer>,
memory: Arc<M>,
}
impl<M: GuestAddressSpace> VfioDmaMapping<M> {
/// Create a DmaMapping object.
///
/// # Parameters
/// * `container`: VFIO container object.
/// * `memory·: guest memory to mmap.
pub fn new(container: Arc<VfioContainer>, memory: Arc<M>) -> Self {
VfioDmaMapping { container, memory }
}
}
impl<M: GuestAddressSpace + Sync + Send> ExternalDmaMapping for VfioDmaMapping<M> {
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:?}"
),
)
})
}
}

View File

@ -2,8 +2,6 @@
// //
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause // 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 /// Trait meant for triggering the DMA mapping update related to an external
/// device not managed fully through virtio. It is dedicated to virtio-iommu /// 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 /// in order to trigger the map update anytime the mapping is updated from the

View File

@ -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<M: GuestAddressSpace> {
container: Arc<VfioContainer>,
memory: Arc<M>,
}
impl<M: GuestAddressSpace> VfioDmaMapping<M> {
/// Create a DmaMapping object.
///
/// # Parameters
/// * `container`: VFIO container object.
/// * `memory·: guest memory to mmap.
pub fn new(container: Arc<VfioContainer>, memory: Arc<M>) -> Self {
VfioDmaMapping { container, memory }
}
}
impl<M: GuestAddressSpace + Sync + Send> ExternalDmaMapping for VfioDmaMapping<M> {
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:?}"
),
)
})
}
}

View File

@ -58,8 +58,8 @@ use libc::{
O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW, O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW,
}; };
use pci::{ use pci::{
DeviceRelocation, PciBarRegionType, PciBdf, PciDevice, VfioPciDevice, VfioUserDmaMapping, DeviceRelocation, PciBarRegionType, PciBdf, PciDevice, VfioDmaMapping,
VfioUserPciDevice, VfioUserPciDeviceError, VfioPciDevice, VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError,
}; };
use rate_limiter::group::RateLimiterGroup; use rate_limiter::group::RateLimiterGroup;
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
@ -85,7 +85,6 @@ use virtio_devices::{
}; };
use virtio_devices::{Endpoint, IommuMapping}; use virtio_devices::{Endpoint, IommuMapping};
use vm_allocator::{AddressAllocator, SystemAllocator}; use vm_allocator::{AddressAllocator, SystemAllocator};
use vm_device::dma_mapping::vfio::VfioDmaMapping;
use vm_device::dma_mapping::ExternalDmaMapping; use vm_device::dma_mapping::ExternalDmaMapping;
use vm_device::interrupt::{ use vm_device::interrupt::{
InterruptIndex, InterruptManager, LegacyIrqGroupConfig, MsiIrqGroupConfig, InterruptIndex, InterruptManager, LegacyIrqGroupConfig, MsiIrqGroupConfig,