(
&mut self,
device_cfg: &mut DeviceConfig,
)
| 3812 | } |
| 3813 | |
| 3814 | fn add_vfio_device( |
| 3815 | &mut self, |
| 3816 | device_cfg: &mut DeviceConfig, |
| 3817 | ) -> DeviceManagerResult<(PciBdf, String)> { |
| 3818 | let vfio_name = if let Some(id) = &device_cfg.pci_common.id { |
| 3819 | id.clone() |
| 3820 | } else { |
| 3821 | let id = self.next_device_name(VFIO_DEVICE_NAME_PREFIX)?; |
| 3822 | device_cfg.pci_common.id = Some(id.clone()); |
| 3823 | id |
| 3824 | }; |
| 3825 | |
| 3826 | let (pci_segment_id, pci_device_bdf, resources) = self.pci_resources( |
| 3827 | &vfio_name, |
| 3828 | device_cfg.pci_common.pci_segment, |
| 3829 | device_cfg.pci_common.pci_device_id, |
| 3830 | )?; |
| 3831 | |
| 3832 | let mut needs_dma_mapping = false; |
| 3833 | |
| 3834 | // Here we create a new VfioOps for two reasons: |
| 3835 | // 1) This is the first VFIO device, meaning we need a new VfioOps |
| 3836 | // which will be shared with other VFIO devices. |
| 3837 | // 2) The new VFIO device is attached to a vIOMMU, meaning we must |
| 3838 | // create a dedicated VfioOps. In the vIOMMU use case, we can't |
| 3839 | // let all devices share the same VfioOps since we couldn't |
| 3840 | // map/unmap memory for each device independently. That's simply |
| 3841 | // because the map/unmap operations happen at the VfioOps level. |
| 3842 | // |
| 3843 | // Note: this is a limitation of the legacy VFIO interface using |
| 3844 | // container/group. The VFIO cdev and iommufd do not have such a |
| 3845 | // limitation, and this will be revised once we have VFIO cdev and |
| 3846 | // iommufd support. |
| 3847 | let vfio_ops = if device_cfg.pci_common.iommu { |
| 3848 | let vfio_ops = self.create_vfio_ops()?; |
| 3849 | |
| 3850 | let vfio_mapping = Arc::new(VfioDmaMapping::new( |
| 3851 | Arc::clone(&vfio_ops), |
| 3852 | Arc::new(self.memory_manager.lock().unwrap().guest_memory()), |
| 3853 | Arc::clone(&self.mmio_regions), |
| 3854 | )); |
| 3855 | |
| 3856 | if let Some(iommu) = &self.iommu_device { |
| 3857 | iommu |
| 3858 | .lock() |
| 3859 | .unwrap() |
| 3860 | .add_external_mapping(pci_device_bdf.into(), vfio_mapping); |
| 3861 | } else { |
| 3862 | return Err(DeviceManagerError::MissingVirtualIommu); |
| 3863 | } |
| 3864 | |
| 3865 | vfio_ops |
| 3866 | } else if let Some(vfio_ops) = &self.vfio_ops { |
| 3867 | Arc::clone(vfio_ops) |
| 3868 | } else { |
| 3869 | let vfio_ops = self.create_vfio_ops()?; |
| 3870 | needs_dma_mapping = true; |
| 3871 | self.vfio_ops = Some(Arc::clone(&vfio_ops)); |
no test coverage detected