vmm: drop device_tree mutex before acquiring pci_bus mutex

AddressManager::move_bar() acquires the device_tree mutex.
The function is called from PciConfigIo::config_space_write()/
PciConfigMmio::config_space_write() while the pci_bus mutex
is acquired.
The functions DeviceManager::pci_resources()/eject_device()
acquire these mutexes in reverse order, which leads to a deadlock.

Fixes: #6775

Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
This commit is contained in:
Alexandru Matei 2024-10-02 12:30:50 +03:00 committed by Rob Bradford
parent 0dc3634b7b
commit c891dcb947

View File

@ -3857,12 +3857,18 @@ impl DeviceManager {
) -> DeviceManagerResult<(u16, PciBdf, Option<Vec<Resource>>)> {
// Look for the id in the device tree. If it can be found, that means
// the device is being restored, otherwise it's created from scratch.
Ok(
let (pci_device_bdf, resources) =
if let Some(node) = self.device_tree.lock().unwrap().get(id) {
info!("Restoring virtio-pci {} resources", id);
let pci_device_bdf: PciBdf = node
.pci_bdf
.ok_or(DeviceManagerError::MissingDeviceNodePciBdf)?;
(Some(pci_device_bdf), Some(node.resources.clone()))
} else {
(None, None)
};
Ok(if let Some(pci_device_bdf) = pci_device_bdf {
let pci_segment_id = pci_device_bdf.segment();
self.pci_segments[pci_segment_id as usize]
@ -3872,14 +3878,12 @@ impl DeviceManager {
.get_device_id(pci_device_bdf.device() as usize)
.map_err(DeviceManagerError::GetPciDeviceId)?;
(pci_segment_id, pci_device_bdf, Some(node.resources.clone()))
(pci_segment_id, pci_device_bdf, resources)
} else {
let pci_device_bdf =
self.pci_segments[pci_segment_id as usize].next_device_bdf()?;
let pci_device_bdf = self.pci_segments[pci_segment_id as usize].next_device_bdf()?;
(pci_segment_id, pci_device_bdf, None)
},
)
})
}
#[cfg(target_arch = "x86_64")]
@ -4098,6 +4102,7 @@ impl DeviceManager {
.put_device_id(device_id as usize)
.map_err(DeviceManagerError::PutPciDeviceId)?;
let (pci_device_handle, id) = {
// Remove the device from the device tree along with its children.
let mut device_tree = self.device_tree.lock().unwrap();
let pci_device_node = device_tree
@ -4123,6 +4128,9 @@ impl DeviceManager {
device_tree.remove(child);
}
(pci_device_handle, id)
};
let mut iommu_attached = false;
if let Some((_, iommu_attached_devices)) = &self.iommu_attached_devices {
if iommu_attached_devices.contains(&pci_device_bdf) {