Dry-run validation that [`prepare_pci_for_passthrough`] would accept this BDF right now. Performs every pre-bind check without touching `driver_override` or any other kernel state. Intended for `ValidateSandboxCreate` and similar pre-flight paths where the caller wants a typed error before committing to side effects. The IOMMU-peer check is inherently racy: a peer's driver state can change betwe
(sysfs: &SysfsRoot, bdf: &str)
| 280 | /// Callers should treat a successful validation as best-effort and still be |
| 281 | /// prepared for the prepare call to fail. |
| 282 | pub fn validate_pci_for_passthrough(sysfs: &SysfsRoot, bdf: &str) -> Result<(), VfioError> { |
| 283 | validate_bdf(bdf)?; |
| 284 | |
| 285 | let device = sysfs.pci_device_ref(bdf); |
| 286 | if !device.exists() { |
| 287 | return Err(VfioError::DeviceNotFound { |
| 288 | bdf: bdf.to_string(), |
| 289 | }); |
| 290 | } |
| 291 | |
| 292 | let iommu_group = device.iommu_group()?; |
| 293 | let group_devices = sysfs.iommu_group_devices(iommu_group)?; |
| 294 | let peers: Vec<String> = group_devices.into_iter().filter(|d| d != bdf).collect(); |
| 295 | |
| 296 | // Refuse to silently auto-bind companions for non-GPU devices. The |
| 297 | // operator must declare every BDF in the IOMMU group eligible and bind them |
| 298 | // through separate calls (or use prepare_pci_group_for_passthrough). |
| 299 | for peer in &peers { |
| 300 | let peer_drv = crate::bind::current_driver_name(sysfs, peer); |
| 301 | if peer_drv.as_deref() != Some("vfio-pci") { |
| 302 | return Err(VfioError::IommuGroupConflict { |
| 303 | bdf: bdf.to_string(), |
| 304 | group: iommu_group, |
| 305 | peers: peers.clone(), |
| 306 | }); |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | Ok(()) |
| 311 | } |
| 312 | |
| 313 | /// Bind an arbitrary VFIO-capable `PCIe` device to `vfio-pci`, returning an RAII |
| 314 | /// guard that restores it to the host driver on drop. |