(&mut self, pci_segment_id: u16, device_id: u8)
| 4777 | } |
| 4778 | |
| 4779 | pub fn eject_device(&mut self, pci_segment_id: u16, device_id: u8) -> DeviceManagerResult<()> { |
| 4780 | info!("Ejecting device_id = {device_id} on segment_id={pci_segment_id}"); |
| 4781 | |
| 4782 | // Convert the device ID into the corresponding b/d/f. |
| 4783 | let pci_device_bdf = PciBdf::new(pci_segment_id, 0, device_id, 0); |
| 4784 | |
| 4785 | // Give the PCI device ID back to the PCI bus. |
| 4786 | self.pci_segments[pci_segment_id as usize] |
| 4787 | .pci_bus |
| 4788 | .lock() |
| 4789 | .unwrap() |
| 4790 | .free_device_id(device_id) |
| 4791 | .map_err(DeviceManagerError::FreePciDeviceId)?; |
| 4792 | |
| 4793 | let (pci_device_handle, id) = { |
| 4794 | // Remove the device from the device tree along with its children. |
| 4795 | let mut device_tree = self.device_tree.lock().unwrap(); |
| 4796 | let pci_device_node = device_tree |
| 4797 | .remove_node_by_pci_bdf(pci_device_bdf) |
| 4798 | .ok_or(DeviceManagerError::MissingPciDevice)?; |
| 4799 | |
| 4800 | // For VFIO and vfio-user the PCI device id is the id. |
| 4801 | // For virtio we overwrite it later as we want the id of the |
| 4802 | // underlying device. |
| 4803 | let mut id = pci_device_node.id; |
| 4804 | let pci_device_handle = pci_device_node |
| 4805 | .pci_device_handle |
| 4806 | .ok_or(DeviceManagerError::MissingPciDevice)?; |
| 4807 | if matches!(pci_device_handle, PciDeviceHandle::Virtio(_)) { |
| 4808 | // The virtio-pci device has a single child |
| 4809 | if !pci_device_node.children.is_empty() { |
| 4810 | assert_eq!(pci_device_node.children.len(), 1); |
| 4811 | let child_id = &pci_device_node.children[0]; |
| 4812 | id.clone_from(child_id); |
| 4813 | } |
| 4814 | } |
| 4815 | for child in pci_device_node.children.iter() { |
| 4816 | device_tree.remove(child); |
| 4817 | } |
| 4818 | |
| 4819 | (pci_device_handle, id) |
| 4820 | }; |
| 4821 | |
| 4822 | let mut iommu_attached = false; |
| 4823 | if let Some((_, iommu_attached_devices)) = &self.iommu_attached_devices |
| 4824 | && iommu_attached_devices.contains(&pci_device_bdf) |
| 4825 | { |
| 4826 | iommu_attached = true; |
| 4827 | } |
| 4828 | |
| 4829 | let (pci_device, bus_device, virtio_device, remove_dma_handler) = match pci_device_handle { |
| 4830 | // VirtioMemMappingSource::Container cleanup is handled by |
| 4831 | // cleanup_vfio_ops when the last VFIO device is removed. |
| 4832 | PciDeviceHandle::Vfio(vfio_pci_device) => { |
| 4833 | // Remove this device's MMIO regions from the DeviceManager's |
| 4834 | // mmio_regions list. We match on UserMemoryRegion slot numbers |
| 4835 | // rather than MmioRegion start addresses because move_bar() |
| 4836 | // updates the device's region addresses but not the |
no test coverage detected