runtime-rs: Add vfio support with coldplug for cloud-hypervisor

This PR adds support for adding a vfio device before starting the
cloud-hypervisor VM (or cold-plug vfio device).

This commit changes "pending_devices" for clh implementation via adding
DeviceType::Vfio() into pending_devices. And it will get shared host devices
after correctly handling vfio devices (Specially for primary device).

Signed-off-by: alex.lyn <alex.lyn@antgroup.com>
Signed-off-by: Fupan Li <fupan.lfp@antgroup.com>
This commit is contained in:
alex.lyn 2025-07-09 11:22:24 +08:00
parent 294b2c1c10
commit d37183d754
2 changed files with 36 additions and 3 deletions

View File

@ -61,6 +61,7 @@ impl CloudHypervisorInner {
match device { match device {
DeviceType::ShareFs(_) => self.pending_devices.insert(0, device.clone()), DeviceType::ShareFs(_) => self.pending_devices.insert(0, device.clone()),
DeviceType::Network(_) => self.pending_devices.insert(0, device.clone()), DeviceType::Network(_) => self.pending_devices.insert(0, device.clone()),
DeviceType::Vfio(_) => self.pending_devices.insert(0, device.clone()),
_ => { _ => {
debug!( debug!(
sl!(), sl!(),
@ -365,9 +366,14 @@ impl CloudHypervisorInner {
pub(crate) async fn get_shared_devices( pub(crate) async fn get_shared_devices(
&mut self, &mut self,
) -> Result<(Option<Vec<FsConfig>>, Option<Vec<NetConfig>>)> { ) -> Result<(
Option<Vec<FsConfig>>,
Option<Vec<NetConfig>>,
Option<Vec<DeviceConfig>>,
)> {
let mut shared_fs_devices = Vec::<FsConfig>::new(); let mut shared_fs_devices = Vec::<FsConfig>::new();
let mut network_devices = Vec::<NetConfig>::new(); let mut network_devices = Vec::<NetConfig>::new();
let mut host_devices = Vec::<DeviceConfig>::new();
while let Some(dev) = self.pending_devices.pop() { while let Some(dev) = self.pending_devices.pop() {
match dev { match dev {
@ -382,11 +388,38 @@ impl CloudHypervisorInner {
let net_config = NetConfig::try_from(net_device.config)?; let net_config = NetConfig::try_from(net_device.config)?;
network_devices.push(net_config); network_devices.push(net_config);
} }
DeviceType::Vfio(vfio_device) => {
// A device with multi-funtions, or a IOMMU group with one more
// devices, the Primary device is selected to be passed to VM.
// And the the first one is Primary device.
// safe here, devices is not empty.
let primary_device = vfio_device.devices.first().ok_or(anyhow!(
"Primary device list empty for vfio device {:?}",
vfio_device
))?;
let primary_device = primary_device.clone();
let sysfsdev = primary_device.sysfs_path.clone();
let device_config = DeviceConfig {
path: PathBuf::from(sysfsdev),
iommu: false,
..Default::default()
};
info!(
sl!(),
"get host_devices primary device {:?}", primary_device
);
host_devices.push(device_config);
}
_ => continue, _ => continue,
} }
} }
Ok((Some(shared_fs_devices), Some(network_devices))) Ok((
Some(shared_fs_devices),
Some(network_devices),
Some(host_devices),
))
} }
} }

View File

@ -185,7 +185,7 @@ impl CloudHypervisorInner {
} }
async fn boot_vm(&mut self) -> Result<()> { async fn boot_vm(&mut self) -> Result<()> {
let (shared_fs_devices, network_devices) = self.get_shared_devices().await?; let (shared_fs_devices, network_devices, _) = self.get_shared_devices().await?;
let socket = self let socket = self
.api_socket .api_socket