summaryrefslogtreecommitdiff
path: root/drivers/vfio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index c9bb2290d39d..b31107803362 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -522,6 +522,23 @@ static int vfio_basic_config_read(struct vfio_pci_device *vdev, int pos,
return count;
}
+/* Test whether BARs match the value we think they should contain */
+static bool vfio_need_bar_restore(struct vfio_pci_device *vdev)
+{
+ int i = 0, pos = PCI_BASE_ADDRESS_0, ret;
+ u32 bar;
+
+ for (; pos <= PCI_BASE_ADDRESS_5; i++, pos += 4) {
+ if (vdev->rbar[i]) {
+ ret = pci_user_read_config_dword(vdev->pdev, pos, &bar);
+ if (ret || vdev->rbar[i] != bar)
+ return true;
+ }
+ }
+
+ return false;
+}
+
static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
@@ -560,7 +577,8 @@ static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos,
* SR-IOV devices will trigger this, but we catch them later
*/
if ((new_mem && virt_mem && !phys_mem) ||
- (new_io && virt_io && !phys_io))
+ (new_io && virt_io && !phys_io) ||
+ vfio_need_bar_restore(vdev))
vfio_bar_restore(vdev);
}