diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index b50d5d13f..bc74bc84a 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -15,7 +15,7 @@ use anyhow::anyhow; use byteorder::{ByteOrder, LittleEndian}; use hypervisor::HypervisorVmError; use libc::{_SC_PAGESIZE, sysconf}; -use log::{error, info}; +use log::{debug, error, info}; use serde::{Deserialize, Serialize}; use thiserror::Error; use vfio_bindings::bindings::vfio::*; @@ -437,6 +437,10 @@ pub(crate) trait Vfio: Send + Sync { fn unmask_irq(&self, _irq_index: u32) -> Result<(), VfioError> { unimplemented!() } + + fn migration_flags(&self) -> Result, VfioError> { + Ok(None) + } } struct VfioDeviceWrapper { @@ -479,6 +483,12 @@ impl Vfio for VfioDeviceWrapper { .unmask_irq(irq_index) .map_err(VfioError::KernelVfio) } + + fn migration_flags(&self) -> Result, VfioError> { + self.device + .query_migration_support() + .map_err(VfioError::KernelVfio) + } } #[derive(Serialize, Deserialize)] @@ -503,6 +513,8 @@ pub(crate) struct VfioCommon { pub(crate) patches: HashMap, x_nv_gpudirect_clique: Option, x_exclude_mmap_bars: Vec, + #[allow(dead_code)] + pub(crate) migration_flags: Option, } #[derive(Default)] @@ -542,6 +554,27 @@ impl VfioCommon { pci_configuration_state, ); + let migration_flags = match vfio_wrapper.migration_flags() { + Ok(Some(flags)) => { + info!( + "VFIO device {bdf} supports migration v2 (flags=0x{flags:x}, \ + STOP_COPY={}, P2P={}, PRE_COPY={})", + flags & VFIO_MIGRATION_STOP_COPY as u64 != 0, + flags & VFIO_MIGRATION_P2P as u64 != 0, + flags & VFIO_MIGRATION_PRE_COPY as u64 != 0, + ); + Some(flags) + } + Ok(None) => { + debug!("VFIO device {bdf} does not support migration v2"); + None + } + Err(e) => { + debug!("VFIO device {bdf} migration probe failed, treating as non-migratable: {e}"); + None + } + }; + let mut vfio_common = VfioCommon { mmio_regions: Vec::new(), configuration, @@ -556,6 +589,7 @@ impl VfioCommon { patches: HashMap::new(), x_nv_gpudirect_clique: config.x_nv_gpudirect_clique, x_exclude_mmap_bars: config.x_exclude_mmap_bars, + migration_flags, }; let state: Option = snapshot diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index dc167f8cd..1bb18b01b 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -86,6 +86,7 @@ const VFIO_DEVICE_RESET: u64 = 0x3b6f; const VFIO_IOMMU_MAP_DMA: u64 = 0x3b71; const VFIO_IOMMU_UNMAP_DMA: u64 = 0x3b72; const VFIO_DEVICE_IOEVENTFD: u64 = 0x3b74; +const VFIO_DEVICE_FEATURE: u64 = 0x3b75; // See include/uapi/linux/kvm.h in the kernel code. #[cfg(feature = "kvm")] @@ -381,6 +382,7 @@ fn create_vmm_ioctl_seccomp_rule_common( and![Cond::new(1, ArgLen::Dword, Eq, VFIO_IOMMU_MAP_DMA)?], and![Cond::new(1, ArgLen::Dword, Eq, VFIO_IOMMU_UNMAP_DMA)?], and![Cond::new(1, ArgLen::Dword, Eq, VFIO_DEVICE_IOEVENTFD)?], + and![Cond::new(1, ArgLen::Dword, Eq, VFIO_DEVICE_FEATURE)?], and![Cond::new(1, ArgLen::Dword, Eq, VHOST_GET_FEATURES())?], and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_FEATURES())?], and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_OWNER())?],