diff mbox series

[4/4] vpci: resolve possible clash while removing BAR overlaps

Message ID 20220216151628.1610777-5-andr2000@gmail.com (mailing list archive)
State New, archived
Headers show
Series Yet another pci/vpci locking re-work | expand

Commit Message

Oleksandr Andrushchenko Feb. 16, 2022, 3:16 p.m. UTC
From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>

modify_bars checks if the mapping of the BAR memory has already been
done when mapping other device's BARs or, while unmapping, are still
in use by other devices.

With the existing locking scheme it is possible that there are other
devices trying to do the same in parallel with us, but on other CPUs
as we only hold a read lock without acquiring _pcidevs_lock recursive
lock.

To prevent that upgrade the read lock to normal pcidevs_lock during
BAR overlapping check.

Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
 xen/drivers/vpci/header.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff mbox series

Patch

diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c
index 75e972740106..c80a8bb5e3e0 100644
--- a/xen/drivers/vpci/header.c
+++ b/xen/drivers/vpci/header.c
@@ -281,7 +281,11 @@  static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, bool rom_only)
     /*
      * Check for overlaps with other BARs. Note that only BARs that are
      * currently mapped (enabled) are checked for overlaps.
+     * We are holding pcidevs_read_lock here, but we need to access
+     * different devices at a time. So, upgrade our current read lock to normal
+     * pcidevs_lock.
      */
+    pcidevs_lock();
     for_each_pdev ( pdev->domain, tmp )
     {
         if ( tmp == pdev )
@@ -321,10 +325,12 @@  static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, bool rom_only)
                 printk(XENLOG_G_WARNING "Failed to remove [%lx, %lx]: %d\n",
                        start, end, rc);
                 rangeset_destroy(mem);
+                pcidevs_unlock();
                 return rc;
             }
         }
     }
+    pcidevs_unlock();
 
     ASSERT(dev);