mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-17 09:43:59 +08:00
vfio-pci: Release devices with BusMaster disabled
Our current open/release path looks like this: vfio_pci_open vfio_pci_enable pci_enable_device pci_save_state pci_store_saved_state vfio_pci_release vfio_pci_disable pci_disable_device pci_restore_state pci_enable_device() doesn't modify PCI_COMMAND_MASTER, so if a device comes to us with it enabled, it persists through the open and gets stored as part of the device saved state. We then restore that saved state when released, which can allow the device to attempt to continue to do DMA. When the group is disconnected from the domain, this will get caught by the IOMMU, but if there are other devices in the group, the device may continue running and interfere with the user. Even in the former case, IOMMUs don't necessarily behave well and a stream of blocked DMA can result in unpleasant behavior on the host. Explicitly disable Bus Master as we're enabling the device and slightly re-work release to make sure that pci_disable_device() is the last thing that touches the device. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
7f0d32e0c1
commit
9c22e660ce
@ -44,6 +44,9 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
|
||||
u16 cmd;
|
||||
u8 msix_pos;
|
||||
|
||||
/* Don't allow our initial saved state to include busmaster */
|
||||
pci_clear_master(pdev);
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -99,7 +102,8 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
|
||||
struct pci_dev *pdev = vdev->pdev;
|
||||
int bar;
|
||||
|
||||
pci_disable_device(pdev);
|
||||
/* Stop the device from further DMA */
|
||||
pci_clear_master(pdev);
|
||||
|
||||
vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE |
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER,
|
||||
@ -128,7 +132,7 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
|
||||
__func__, dev_name(&pdev->dev));
|
||||
|
||||
if (!vdev->reset_works)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
pci_save_state(pdev);
|
||||
}
|
||||
@ -151,6 +155,8 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
|
||||
}
|
||||
|
||||
pci_restore_state(pdev);
|
||||
out:
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static void vfio_pci_release(void *device_data)
|
||||
|
Loading…
Reference in New Issue
Block a user