diff --git a/Cargo.lock b/Cargo.lock index bc927af8c..7c03c0876 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1097,6 +1097,23 @@ dependencies = [ "libc", ] +[[package]] +name = "iommufd-bindings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7de3a04f6fd55f171a6682852f7aa360bb848a85e0c610513349e006b3c139" + +[[package]] +name = "iommufd-ioctls" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eabd3414d9c4e716c9a198fbfac484625f088c075605372daf037edfe336e18" +dependencies = [ + "iommufd-bindings", + "thiserror", + "vmm-sys-util", +] + [[package]] name = "ipnetwork" version = "0.20.0" @@ -2291,6 +2308,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4b1d98dff7f0d219278e406323e7eda4d426447bd203c7828189baf0d8c07b7" dependencies = [ "byteorder", + "iommufd-bindings", + "iommufd-ioctls", "kvm-bindings", "kvm-ioctls", "libc", @@ -2521,6 +2540,7 @@ dependencies = [ "hypervisor", "igvm", "igvm_defs", + "iommufd-ioctls", "landlock", "libc", "linux-loader", diff --git a/Cargo.toml b/Cargo.toml index 6ce471501..92a52f81a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ resolver = "3" [workspace.dependencies] # rust-vmm crates acpi_tables = "0.2.0" +iommufd-ioctls = "0.1.0" kvm-bindings = "0.14.0" kvm-ioctls = "0.24.0" linux-loader = "0.13.2" diff --git a/vmm/Cargo.toml b/vmm/Cargo.toml index ab0278e6d..1fe5e0e47 100644 --- a/vmm/Cargo.toml +++ b/vmm/Cargo.toml @@ -17,8 +17,10 @@ ivshmem = ["devices/ivshmem"] kvm = [ "arch/kvm", "hypervisor/kvm", + "iommufd-ioctls", "pci/kvm", "vfio-ioctls/kvm", + "vfio-ioctls/vfio_cdev", "virtio-devices/kvm", "vm-device/kvm", ] @@ -55,6 +57,7 @@ hex = { version = "0.4.3", optional = true } hypervisor = { path = "../hypervisor" } igvm = { workspace = true, optional = true } igvm_defs = { workspace = true, optional = true } +iommufd-ioctls = { workspace = true, optional = true } landlock = "0.4.4" libc = { workspace = true } linux-loader = { workspace = true, features = ["bzimage", "elf", "pe"] } diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index edb8b76af..a797a7bc8 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -76,6 +76,8 @@ use event_monitor::event; use hypervisor::IoEventAddress; #[cfg(target_arch = "aarch64")] use hypervisor::arch::aarch64::regs::AARCH64_PMU_IRQ; +#[cfg(feature = "kvm")] +use iommufd_ioctls::IommuFd; use libc::{ MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW, tcsetattr, termios, @@ -90,6 +92,8 @@ use seccompiler::SeccompAction; use serde::{Deserialize, Serialize}; use thiserror::Error; use tracer::trace_scoped; +#[cfg(feature = "kvm")] +use vfio_ioctls::VfioIommufd; use vfio_ioctls::{VfioContainer, VfioDevice, VfioDeviceFd, VfioOps}; use virtio_devices::transport::{VirtioPciDevice, VirtioPciDeviceActivator, VirtioTransport}; use virtio_devices::vhost_user::VhostUserConfig; @@ -361,6 +365,15 @@ pub enum DeviceManagerError { #[error("Error getting pty peer")] GetPtyPeer(#[source] vmm_sys_util::errno::Error), + /// Cannot create iommufd + #[cfg(feature = "kvm")] + #[error("Cannot create iommufd")] + IommufdCreate(#[source] iommufd_ioctls::IommufdError), + + /// iommufd is not supported + #[error("iommufd is not supported without the kvm feature")] + IommufdNotSupported, + /// Cannot create a VFIO device #[error("Cannot create a VFIO device")] VfioCreate(#[source] vfio_ioctls::VfioError), @@ -3803,9 +3816,31 @@ impl DeviceManager { .try_clone() .map_err(DeviceManagerError::VfioCreate)?; - Ok(Arc::new( - VfioContainer::new(Some(Arc::new(dup))).map_err(DeviceManagerError::VfioCreate)?, - )) + let iommufd = self + .config + .lock() + .unwrap() + .platform + .as_ref() + .is_some_and(|p| p.iommufd); + + if iommufd { + #[cfg(feature = "kvm")] + { + info!("Using vfio cdev mode with iommufd."); + let iommufd = IommuFd::new().map_err(DeviceManagerError::IommufdCreate)?; + let vfio_iommufd = VfioIommufd::new(Arc::new(iommufd), None, Some(Arc::new(dup))) + .map_err(DeviceManagerError::VfioCreate)?; + Ok(Arc::new(vfio_iommufd)) + } + #[cfg(not(feature = "kvm"))] + Err(DeviceManagerError::IommufdNotSupported) + } else { + info!("Using vfio legacy mode with vfio container/group."); + Ok(Arc::new( + VfioContainer::new(Some(Arc::new(dup))).map_err(DeviceManagerError::VfioCreate)?, + )) + } } fn add_vfio_device(