mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vfio: Create VFIO implementation of ExternalDmaMapping
With this implementation of the trait ExternalDmaMapping, we now have the tool to provide to the virtual IOMMU to trigger the map/unmap on behalf of the guest. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
committed by
Samuel Ortiz
parent
3598e603d5
commit
837bcbc6ba
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -970,6 +970,7 @@ dependencies = [
|
|||||||
"pci 0.1.0",
|
"pci 0.1.0",
|
||||||
"vfio-bindings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vfio-bindings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vm-allocator 0.1.0",
|
"vm-allocator 0.1.0",
|
||||||
|
"vm-device 0.1.0",
|
||||||
"vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)",
|
"vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)",
|
||||||
"vmm-sys-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vmm-sys-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ log = "0.4.8"
|
|||||||
pci = { path = "../pci" }
|
pci = { path = "../pci" }
|
||||||
vfio-bindings = "0.1.0"
|
vfio-bindings = "0.1.0"
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
|
vm-device = { path = "../vm-device" }
|
||||||
vmm-sys-util = "0.1.1"
|
vmm-sys-util = "0.1.1"
|
||||||
|
|
||||||
[dependencies.vm-memory]
|
[dependencies.vm-memory]
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ extern crate log;
|
|||||||
extern crate pci;
|
extern crate pci;
|
||||||
extern crate vfio_bindings;
|
extern crate vfio_bindings;
|
||||||
extern crate vm_allocator;
|
extern crate vm_allocator;
|
||||||
|
extern crate vm_device;
|
||||||
extern crate vm_memory;
|
extern crate vm_memory;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate vmm_sys_util;
|
extern crate vmm_sys_util;
|
||||||
@@ -24,7 +25,7 @@ mod vfio_pci;
|
|||||||
|
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
|
||||||
pub use vfio_device::{VfioDevice, VfioError};
|
pub use vfio_device::{VfioContainer, VfioDevice, VfioDmaMapping, VfioError};
|
||||||
pub use vfio_pci::{VfioPciDevice, VfioPciError};
|
pub use vfio_pci::{VfioPciDevice, VfioPciError};
|
||||||
|
|
||||||
// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
|
// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ use std::mem;
|
|||||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||||
use std::os::unix::prelude::FileExt;
|
use std::os::unix::prelude::FileExt;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::result;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use vfio_bindings::bindings::vfio::*;
|
use vfio_bindings::bindings::vfio::*;
|
||||||
use vfio_ioctls::*;
|
use vfio_ioctls::*;
|
||||||
use vm_memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion};
|
use vm_device::ExternalDmaMapping;
|
||||||
|
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
use vmm_sys_util::ioctl::*;
|
use vmm_sys_util::ioctl::*;
|
||||||
|
|
||||||
@@ -506,6 +508,68 @@ impl VfioDeviceInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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<VfioContainer>,
|
||||||
|
memory: Arc<RwLock<GuestMemoryMmap>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VfioDmaMapping {
|
||||||
|
pub fn new(container: Arc<VfioContainer>, memory: Arc<RwLock<GuestMemoryMmap>>) -> Self {
|
||||||
|
VfioDmaMapping { container, memory }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExternalDmaMapping for VfioDmaMapping {
|
||||||
|
fn map(&self, iova: u64, gpa: u64, size: u64) -> result::Result<(), io::Error> {
|
||||||
|
let user_addr = if let Some(addr) = self
|
||||||
|
.memory
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.get_host_address(GuestAddress(gpa))
|
||||||
|
{
|
||||||
|
addr as u64
|
||||||
|
} else {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!(
|
||||||
|
"failed to convert guest address 0x{:x} into \
|
||||||
|
host user virtual address",
|
||||||
|
gpa
|
||||||
|
),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
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{:x}, gpa 0x{:x}, size 0x{:x}: {:?}",
|
||||||
|
iova, gpa, size, e
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmap(&self, iova: u64, size: u64) -> 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{:x}, size 0x{:x}: {:?}",
|
||||||
|
iova, size, e
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Vfio device for exposing regions which could be read/write to kernel vfio device.
|
/// Vfio device for exposing regions which could be read/write to kernel vfio device.
|
||||||
pub struct VfioDevice {
|
pub struct VfioDevice {
|
||||||
device: File,
|
device: File,
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ serde = {version = ">=1.0.27", features = ["rc"] }
|
|||||||
serde_derive = ">=1.0.27"
|
serde_derive = ">=1.0.27"
|
||||||
serde_json = ">=1.0.9"
|
serde_json = ">=1.0.9"
|
||||||
vfio = { path = "../vfio", optional = true }
|
vfio = { path = "../vfio", optional = true }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.1.1"
|
vmm-sys-util = "0.1.1"
|
||||||
signal-hook = "0.1.10"
|
signal-hook = "0.1.10"
|
||||||
threadpool = "1.0"
|
threadpool = "1.0"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ use std::ptr::null_mut;
|
|||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
#[cfg(feature = "pci_support")]
|
#[cfg(feature = "pci_support")]
|
||||||
use vfio::{VfioDevice, VfioPciDevice, VfioPciError};
|
use vfio::{VfioDevice, VfioDmaMapping, VfioPciDevice, VfioPciError};
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::SystemAllocator;
|
||||||
#[cfg(feature = "mmio_support")]
|
#[cfg(feature = "mmio_support")]
|
||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
@@ -998,15 +998,18 @@ impl DeviceManager {
|
|||||||
// global device ID.
|
// global device ID.
|
||||||
let device_id = pci.next_device_id() << 3;
|
let device_id = pci.next_device_id() << 3;
|
||||||
|
|
||||||
if device_cfg.iommu {
|
|
||||||
iommu_attached_list.push(device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
let vfio_device =
|
let vfio_device =
|
||||||
VfioDevice::new(&device_cfg.path, device_fd.clone(), vm_info.memory.clone())
|
VfioDevice::new(&device_cfg.path, device_fd.clone(), vm_info.memory.clone())
|
||||||
.map_err(DeviceManagerError::VfioCreate)?;
|
.map_err(DeviceManagerError::VfioCreate)?;
|
||||||
|
|
||||||
let _vfio_container = vfio_device.get_container();
|
if device_cfg.iommu {
|
||||||
|
let _vfio_mapping = VfioDmaMapping::new(
|
||||||
|
vfio_device.get_container(),
|
||||||
|
Arc::clone(vm_info.memory),
|
||||||
|
);
|
||||||
|
|
||||||
|
iommu_attached_list.push(device_id);
|
||||||
|
}
|
||||||
|
|
||||||
let mut vfio_pci_device = VfioPciDevice::new(vm_info.vm_fd, allocator, vfio_device)
|
let mut vfio_pci_device = VfioPciDevice::new(vm_info.vm_fd, allocator, vfio_device)
|
||||||
.map_err(DeviceManagerError::VfioPciCreate)?;
|
.map_err(DeviceManagerError::VfioPciCreate)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user