diff --git a/src/main.rs b/src/main.rs index 52191ed47..95eb699d8 100755 --- a/src/main.rs +++ b/src/main.rs @@ -204,7 +204,7 @@ fn create_app<'a, 'b>( .help("Direct device assignment parameter") .help( "Direct device assignment parameters \ - \"path=,iommu=on|off\"", + \"path=,iommu=on|off,id=\"", ) .takes_value(true) .min_values(1) diff --git a/vmm/src/api/openapi/cloud-hypervisor.yaml b/vmm/src/api/openapi/cloud-hypervisor.yaml index fc3e568c5..b49e6a37d 100644 --- a/vmm/src/api/openapi/cloud-hypervisor.yaml +++ b/vmm/src/api/openapi/cloud-hypervisor.yaml @@ -432,6 +432,8 @@ components: iommu: type: boolean default: false + id: + type: string VsockConfig: required: diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 05ffb31b9..fb045f68c 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -900,19 +900,28 @@ impl DeviceConfig { let mut path_str: &str = ""; let mut iommu_str: &str = ""; + let mut id_str: &str = ""; for param in params_list.iter() { if param.starts_with("path=") { path_str = ¶m[5..]; } else if param.starts_with("iommu=") { iommu_str = ¶m[6..]; + } else if param.starts_with("id=") { + id_str = ¶m[3..]; } } + let id = if !id_str.is_empty() { + Some(String::from(id_str)) + } else { + None + }; + Ok(DeviceConfig { path: PathBuf::from(path_str), iommu: parse_on_off(iommu_str)?, - id: None, + id, }) } } diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 6301a475d..3552c5ea3 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -252,6 +252,9 @@ pub enum DeviceManagerError { /// Could not give the PCI device ID back. #[cfg(feature = "pci_support")] PutPciDeviceId(pci::PciRootError), + + /// Incorrect device ID as it is already used by another device. + DeviceIdAlreadyInUse, } pub type DeviceManagerResult = result::Result; @@ -1554,8 +1557,17 @@ impl DeviceManager { ) .map_err(DeviceManagerError::AddPciDevice)?; - let vfio_name = self.next_device_name(VFIO_DEVICE_NAME_PREFIX)?; - device_cfg.id = Some(vfio_name.clone()); + let vfio_name = if let Some(id) = &device_cfg.id { + if self.pci_id_list.contains_key(id) { + return Err(DeviceManagerError::DeviceIdAlreadyInUse); + } + + id.clone() + } else { + let id = self.next_device_name(VFIO_DEVICE_NAME_PREFIX)?; + device_cfg.id = Some(id.clone()); + id + }; self.pci_id_list.insert(vfio_name, pci_device_bdf); Ok(pci_device_bdf)