mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: device_manager: Use externally-supplied iommufd FD
Signed-off-by: Bo Chen <bchen@crusoe.ai> Assisted-by: Claude:Opus-4.7
This commit is contained in:
@@ -3892,7 +3892,7 @@ impl DeviceManager {
|
|||||||
.try_clone()
|
.try_clone()
|
||||||
.map_err(DeviceManagerError::VfioCreate)?;
|
.map_err(DeviceManagerError::VfioCreate)?;
|
||||||
|
|
||||||
let iommufd = self
|
let iommufd_on = self
|
||||||
.config
|
.config
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -3900,11 +3900,40 @@ impl DeviceManager {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|p| p.iommufd);
|
.is_some_and(|p| p.iommufd);
|
||||||
|
|
||||||
if iommufd {
|
if iommufd_on {
|
||||||
#[cfg(feature = "kvm")]
|
#[cfg(feature = "kvm")]
|
||||||
{
|
{
|
||||||
info!("Using vfio cdev mode with iommufd.");
|
let iommufd_fd = self
|
||||||
let iommufd = IommuFd::new().map_err(DeviceManagerError::IommufdCreate)?;
|
.config
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.platform
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|p| p.iommufd_fd);
|
||||||
|
let iommufd = match iommufd_fd {
|
||||||
|
Some(fd) => {
|
||||||
|
info!("Using vfio cdev mode with externally-supplied iommufd fd: {fd}.");
|
||||||
|
// Dup so the IommuFd owns its own File; the
|
||||||
|
// caller-supplied fd is kept alive across reboot
|
||||||
|
// via VmConfig::preserved_fds.
|
||||||
|
// SAFETY: FFI call to dup. Trivially safe.
|
||||||
|
let dup_fd = unsafe { libc::dup(fd) };
|
||||||
|
if dup_fd < 0 {
|
||||||
|
return Err(DeviceManagerError::VfioDupFd(io::Error::last_os_error()));
|
||||||
|
}
|
||||||
|
// SAFETY: dup_fd is valid and can be owned by this File
|
||||||
|
let file = unsafe { File::from_raw_fd(dup_fd) };
|
||||||
|
// SAFETY: fd is a valid open iommufd
|
||||||
|
unsafe {
|
||||||
|
self.config.lock().unwrap().add_preserved_fds(vec![fd]);
|
||||||
|
}
|
||||||
|
IommuFd::new_from_fd(file)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
info!("Using vfio cdev mode with iommufd.");
|
||||||
|
IommuFd::new().map_err(DeviceManagerError::IommufdCreate)?
|
||||||
|
}
|
||||||
|
};
|
||||||
let vfio_iommufd = VfioIommufd::new(Arc::new(iommufd), None, Some(Arc::new(dup)))
|
let vfio_iommufd = VfioIommufd::new(Arc::new(iommufd), None, Some(Arc::new(dup)))
|
||||||
.map_err(DeviceManagerError::VfioCreate)?;
|
.map_err(DeviceManagerError::VfioCreate)?;
|
||||||
Ok(Arc::new(vfio_iommufd))
|
Ok(Arc::new(vfio_iommufd))
|
||||||
@@ -3933,15 +3962,26 @@ impl DeviceManager {
|
|||||||
fd: i32,
|
fd: i32,
|
||||||
vfio_ops: Arc<dyn VfioOps>,
|
vfio_ops: Arc<dyn VfioOps>,
|
||||||
) -> DeviceManagerResult<(VfioDevice, PathBuf)> {
|
) -> DeviceManagerResult<(VfioDevice, PathBuf)> {
|
||||||
assert!(
|
let already_bound = {
|
||||||
self.config
|
let config = self.config.lock().unwrap();
|
||||||
.lock()
|
assert!(
|
||||||
.unwrap()
|
config.platform.as_ref().is_some_and(|p| p.iommufd),
|
||||||
.platform
|
"DeviceConfig::validate enforces iommufd when fd is set",
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
config
|
||||||
|
.platform
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|p| p.iommufd_fd.is_some()),
|
||||||
|
"DeviceConfig::validate enforces iommufd_fd when device fd is set",
|
||||||
|
);
|
||||||
|
// If a cdev fd was preserved on a prior boot, it is already bound
|
||||||
|
// to an iommufd instance
|
||||||
|
config
|
||||||
|
.preserved_fds
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|p| p.iommufd),
|
.is_some_and(|s| s.contains(&fd))
|
||||||
"DeviceConfig::validate enforces iommufd when fd is set",
|
};
|
||||||
);
|
|
||||||
|
|
||||||
// SAFETY: FFI call to dup. Trivially safe.
|
// SAFETY: FFI call to dup. Trivially safe.
|
||||||
let dup_fd = unsafe { libc::dup(fd) };
|
let dup_fd = unsafe { libc::dup(fd) };
|
||||||
@@ -3950,8 +3990,11 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
// SAFETY: dup_fd is a freshly-opened fd owned by this File.
|
// SAFETY: dup_fd is a freshly-opened fd owned by this File.
|
||||||
let file = unsafe { File::from_raw_fd(dup_fd) };
|
let file = unsafe { File::from_raw_fd(dup_fd) };
|
||||||
let vfio_device =
|
let vfio_device = if already_bound {
|
||||||
VfioDevice::new_from_fd(file, vfio_ops).map_err(DeviceManagerError::VfioCreate)?;
|
VfioDevice::new_from_bound_fd(file, vfio_ops).map_err(DeviceManagerError::VfioCreate)?
|
||||||
|
} else {
|
||||||
|
VfioDevice::new_from_fd(file, vfio_ops).map_err(DeviceManagerError::VfioCreate)?
|
||||||
|
};
|
||||||
|
|
||||||
// SAFETY: fd is a valid open vfio cdev FD; the VfioDevice only
|
// SAFETY: fd is a valid open vfio cdev FD; the VfioDevice only
|
||||||
// holds a dup, so VmConfig can safely take ownership of the
|
// holds a dup, so VmConfig can safely take ownership of the
|
||||||
|
|||||||
Reference in New Issue
Block a user