Merge pull request #11540 from Apokleos/coldplug-vfio-clh

runtime-rs: Add vfio support with coldplug for cloud-hypervisor
This commit is contained in:
Alex Lyn 2025-07-11 10:33:59 +08:00 committed by GitHub
commit f22272b8f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 4 deletions

View File

@ -109,6 +109,7 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
let fs = n.shared_fs_devices;
let net = n.network_devices;
let host_devices = n.host_devices;
let cpus = CpusConfig::try_from((cfg.cpu_info, guest_protection_to_use.clone()))
.map_err(VmConfigError::CPUError)?;
@ -197,6 +198,7 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
payload,
fs,
net,
devices: host_devices,
pmem,
disks,
vsock: Some(vsock),

View File

@ -491,6 +491,7 @@ pub struct NamedHypervisorConfig {
pub shared_fs_devices: Option<Vec<FsConfig>>,
pub network_devices: Option<Vec<NetConfig>>,
pub host_devices: Option<Vec<DeviceConfig>>,
// Set to the available guest protection *iff* BOTH of the following
// conditions are true:

View File

@ -61,6 +61,7 @@ impl CloudHypervisorInner {
match device {
DeviceType::ShareFs(_) => 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!(
sl!(),
@ -365,9 +366,14 @@ impl CloudHypervisorInner {
pub(crate) async fn get_shared_devices(
&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 network_devices = Vec::<NetConfig>::new();
let mut host_devices = Vec::<DeviceConfig>::new();
while let Some(dev) = self.pending_devices.pop() {
match dev {
@ -382,11 +388,38 @@ impl CloudHypervisorInner {
let net_config = NetConfig::try_from(net_device.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,
}
}
Ok((Some(shared_fs_devices), Some(network_devices)))
Ok((
Some(shared_fs_devices),
Some(network_devices),
Some(host_devices),
))
}
}

View File

@ -185,8 +185,7 @@ impl CloudHypervisorInner {
}
async fn boot_vm(&mut self) -> Result<()> {
let (shared_fs_devices, network_devices) = self.get_shared_devices().await?;
let (shared_fs_devices, network_devices, host_devices) = self.get_shared_devices().await?;
let socket = self
.api_socket
.as_ref()
@ -215,6 +214,7 @@ impl CloudHypervisorInner {
guest_protection_to_use: self.guest_protection_to_use.clone(),
shared_fs_devices,
network_devices,
host_devices,
};
let cfg = VmConfig::try_from(named_cfg)?;