diff --git a/vmm/src/config.rs b/vmm/src/config.rs index c9104007f..c2c943020 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -2206,45 +2206,23 @@ impl DeviceConfig { .add("x_nv_gpudirect_clique"); parser.parse(device).map_err(Error::ParseDevice)?; + let pci_common = PciDeviceCommonConfig::parse(device)?; let path = parser .get("path") .map(PathBuf::from) .ok_or(Error::ParseDevicePathMissing)?; - let iommu = parser - .convert::("iommu") - .map_err(Error::ParseDevice)? - .unwrap_or(Toggle(false)) - .0; - let id = parser.get("id"); - let pci_segment = parser - .convert::("pci_segment") - .map_err(Error::ParseDevice)? - .unwrap_or_default(); let x_nv_gpudirect_clique = parser .convert::("x_nv_gpudirect_clique") .map_err(Error::ParseDevice)?; Ok(DeviceConfig { + pci_common, path, - iommu, - id, - pci_segment, x_nv_gpudirect_clique, }) } pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> { - if let Some(platform_config) = vm_config.platform.as_ref() { - if self.pci_segment >= platform_config.num_pci_segments { - return Err(ValidationError::InvalidPciSegment(self.pci_segment)); - } - - if let Some(iommu_segments) = platform_config.iommu_segments.as_ref() - && iommu_segments.contains(&self.pci_segment) - && !self.iommu - { - return Err(ValidationError::OnIommuSegment(self.pci_segment)); - } - } + self.pci_common.validate(vm_config)?; if self.x_nv_gpudirect_clique.is_some() { let vfio_p2p_dma = vm_config.platform.as_ref().is_none_or(|p| p.vfio_p2p_dma); @@ -3120,9 +3098,9 @@ impl VmConfig { } device.validate(self)?; - self.iommu |= device.iommu; + self.iommu |= device.pci_common.iommu; - Self::validate_identifier(&mut id_list, &device.id)?; + Self::validate_identifier(&mut id_list, &device.pci_common.id)?; } } @@ -3454,7 +3432,7 @@ impl VmConfig { // Remove if VFIO device if let Some(devices) = self.devices.as_mut() { let len = devices.len(); - devices.retain(|dev| dev.id.as_ref().map(|id| id.as_ref()) != Some(id)); + devices.retain(|dev| dev.pci_common.id.as_ref().map(|id| id.as_ref()) != Some(id)); removed |= devices.len() != len; } @@ -4443,10 +4421,8 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" fn device_fixture() -> DeviceConfig { DeviceConfig { + pci_common: PciDeviceCommonConfig::default(), path: PathBuf::from("/path/to/device"), - id: None, - iommu: false, - pci_segment: 0, x_nv_gpudirect_clique: None, } } @@ -4463,7 +4439,10 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" assert_eq!( DeviceConfig::parse("path=/path/to/device,iommu=on")?, DeviceConfig { - iommu: true, + pci_common: PciDeviceCommonConfig { + iommu: true, + ..Default::default() + }, ..device_fixture() } ); @@ -4471,8 +4450,11 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" assert_eq!( DeviceConfig::parse("path=/path/to/device,iommu=on,id=mydevice0")?, DeviceConfig { - id: Some("mydevice0".to_owned()), - iommu: true, + pci_common: PciDeviceCommonConfig { + id: Some("mydevice0".to_owned()), + iommu: true, + ..Default::default() + }, ..device_fixture() } ); @@ -5308,8 +5290,11 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" ..platform_fixture() }); still_valid_config.devices = Some(vec![DeviceConfig { - iommu: true, - pci_segment: 1, + pci_common: PciDeviceCommonConfig { + iommu: true, + pci_segment: 1, + ..Default::default() + }, ..device_fixture() }]); still_valid_config.validate().unwrap(); @@ -5389,8 +5374,10 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" ..platform_fixture() }); invalid_config.devices = Some(vec![DeviceConfig { - iommu: false, - pci_segment: 1, + pci_common: PciDeviceCommonConfig { + pci_segment: 1, + ..Default::default() + }, ..device_fixture() }]); assert_eq!( diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 061c80f62..da03c6b55 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -3858,16 +3858,16 @@ impl DeviceManager { &mut self, device_cfg: &mut DeviceConfig, ) -> DeviceManagerResult<(PciBdf, String)> { - let vfio_name = if let Some(id) = &device_cfg.id { + let vfio_name = if let Some(id) = &device_cfg.pci_common.id { id.clone() } else { let id = self.next_device_name(VFIO_DEVICE_NAME_PREFIX)?; - device_cfg.id = Some(id.clone()); + device_cfg.pci_common.id = Some(id.clone()); id }; let (pci_segment_id, pci_device_bdf, resources) = - self.pci_resources(&vfio_name, device_cfg.pci_segment)?; + self.pci_resources(&vfio_name, device_cfg.pci_common.pci_segment)?; let mut needs_dma_mapping = false; @@ -3884,7 +3884,7 @@ impl DeviceManager { // container/group. The VFIO cdev and iommufd do not have such a // limitation, and this will be revised once we have VFIO cdev and // iommufd support. - let vfio_ops = if device_cfg.iommu { + let vfio_ops = if device_cfg.pci_common.iommu { let vfio_ops = self.create_vfio_ops()?; let vfio_mapping = Arc::new(VfioDmaMapping::new( @@ -3989,7 +3989,7 @@ impl DeviceManager { vfio_ops, self.msi_interrupt_manager.clone(), legacy_interrupt_group, - device_cfg.iommu, + device_cfg.pci_common.iommu, vfio_p2p_dma, pci_device_bdf, memory_manager.lock().unwrap().memory_slot_allocator(), @@ -4104,7 +4104,7 @@ impl DeviceManager { if let Some(device_list_cfg) = &mut devices { for device_cfg in device_list_cfg.iter_mut() { let (device_id, _) = self.add_passthrough_device(device_cfg)?; - if device_cfg.iommu && self.iommu_device.is_some() { + if device_cfg.pci_common.iommu && self.iommu_device.is_some() { iommu_attached_device_ids.push(device_id); } } @@ -4630,16 +4630,18 @@ impl DeviceManager { &mut self, device_cfg: &mut DeviceConfig, ) -> DeviceManagerResult { - self.validate_identifier(&device_cfg.id)?; + self.validate_identifier(&device_cfg.pci_common.id)?; - if device_cfg.iommu && !self.is_iommu_segment(device_cfg.pci_segment) { + if device_cfg.pci_common.iommu && !self.is_iommu_segment(device_cfg.pci_common.pci_segment) + { return Err(DeviceManagerError::InvalidIommuHotplug); } let (bdf, device_name) = self.add_passthrough_device(device_cfg)?; // Update the PCIU bitmap - self.pci_segments[device_cfg.pci_segment as usize].pci_devices_up |= 1 << bdf.device(); + self.pci_segments[device_cfg.pci_common.pci_segment as usize].pci_devices_up |= + 1 << bdf.device(); Ok(PciDeviceInfo { id: device_name, diff --git a/vmm/src/vm_config.rs b/vmm/src/vm_config.rs index 079dc1ac6..f6eb8af68 100644 --- a/vmm/src/vm_config.rs +++ b/vmm/src/vm_config.rs @@ -607,14 +607,10 @@ impl ApplyLandlock for DebugConsoleConfig { #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub struct DeviceConfig { + #[serde(flatten)] + pub pci_common: PciDeviceCommonConfig, pub path: PathBuf, #[serde(default)] - pub iommu: bool, - #[serde(default)] - pub id: Option, - #[serde(default)] - pub pci_segment: u16, - #[serde(default)] pub x_nv_gpudirect_clique: Option, }