[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH 07/10] xen: pci: add per-device locking


  • To: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Date: Wed, 31 Aug 2022 14:11:01 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=epam.com; dmarc=pass action=none header.from=epam.com; dkim=pass header.d=epam.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=yrA6DJoAo0xAR2GhIIjbwMHD+Xks+V3rsePQNzQTzjY=; b=mI9Cdiz4OPqEhyMisWELZYRfBGE1HbNL4dYo1RK2heqyZkWwGhSupCxMYbkLs0tC50yvzpC1hfWg0wc5doOAZaIPhi/uuf7R9qktQrbSLWfFdqfnY9czIEkZL/MEbVd0qs/JBoFPegdgaxAxp3PLv7xI8Jq6Snf8siALI6Ck0YiuttRXZoMfXOPqLZiTqmMYTTX7NaEYVplBgdYookjTnF4lOklL5+2GMZND9KKKTipiuhxlQ0xj4mlvRdJKAbKmq5HnMJa2iZdo0RP7CLfVvuR4Vu9KWVEd6w4uVox+FnPXn5UkOC7/9Vm1jsQKbvH11UBDTQ6oChVPqai2LGMqTg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=h4KV915eBKmPv6X9qhSpCZKtA7uIzlw5te+xYV8nGdVQB2hOLb9O36P43Bzr6P1xMn/os2hkQkVeFdtbvuWJmMvjeFQWh20gBKWZxPM1aiCc2VJe09OS2dqxjtk5SG7omJC3JWb37eIWR9qL+lwk2on+Ek1MhS+hgPSXFXplL7NUqra9E9GQNojd/zFuJnC7V6iWIK1B7WCZoE1Zskl2AtNfFcezUa22w2RPrCcXFXnFP0krbQ6EojsKgujDAKmgZBgIUIPR8736+ByAdxnHozmtGiRgKqkcBsfmBChPsFdVHUWWcJOHLewHDHNTB4wjOBd33M00oF+bQRQnItSGRA==
  • Cc: Oleksandr Andrushchenko <Oleksandr_Andrushchenko@xxxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, George Dunlap <george.dunlap@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Paul Durrant <paul@xxxxxxx>
  • Delivery-date: Wed, 31 Aug 2022 14:11:21 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHYvUN/+u7dK30KdkO8lqgvo0jPyQ==
  • Thread-topic: [RFC PATCH 07/10] xen: pci: add per-device locking

Spinlock in struct pci_device will be used to protect access to device
itself. Right now it is used mostly by MSI code.

Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
---
 xen/arch/x86/hvm/vmsi.c       |  6 +++++-
 xen/arch/x86/msi.c            | 16 ++++++++++++++++
 xen/drivers/passthrough/msi.c |  8 +++++++-
 xen/drivers/passthrough/pci.c |  2 ++
 xen/include/xen/pci.h         | 12 ++++++++++++
 5 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index 7fb1075673..c9e5f279c5 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -203,10 +203,14 @@ static struct msi_desc *msixtbl_addr_to_desc(
 
     nr_entry = (addr - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
 
+    pcidev_lock(entry->pdev);
     list_for_each_entry( desc, &entry->pdev->msi_list, list )
         if ( desc->msi_attrib.type == PCI_CAP_ID_MSIX &&
-             desc->msi_attrib.entry_nr == nr_entry )
+             desc->msi_attrib.entry_nr == nr_entry ) {
+           pcidev_unlock(entry->pdev);
             return desc;
+       }
+    pcidev_unlock(entry->pdev);
 
     return NULL;
 }
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index bccaccb98b..6b62c4f452 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -389,6 +389,7 @@ static bool msi_set_mask_bit(struct irq_desc *desc, bool 
host, bool guest)
     default:
         return 0;
     }
+
     entry->msi_attrib.host_masked = host;
     entry->msi_attrib.guest_masked = guest;
 
@@ -585,12 +586,17 @@ static struct msi_desc *find_msi_entry(struct pci_dev 
*dev,
 {
     struct msi_desc *entry;
 
+    pcidev_lock(dev);
     list_for_each_entry( entry, &dev->msi_list, list )
     {
         if ( entry->msi_attrib.type == cap_id &&
              (irq == -1 || entry->irq == irq) )
+       {
+           pcidev_unlock(dev);
             return entry;
+       }
     }
+    pcidev_unlock(dev);
 
     return NULL;
 }
@@ -661,7 +667,9 @@ static int msi_capability_init(struct pci_dev *dev,
         maskbits |= ~(uint32_t)0 >> (32 - dev->msi_maxvec);
         pci_conf_write32(dev->sbdf, mpos, maskbits);
     }
+    pcidev_lock(dev);
     list_add_tail(&entry->list, &dev->msi_list);
+    pcidev_unlock(dev);
 
     *desc = entry;
     /* Restore the original MSI enabled bits  */
@@ -946,7 +954,9 @@ static int msix_capability_init(struct pci_dev *dev,
 
        pcidev_get(dev);
 
+       pcidev_lock(dev);
         list_add_tail(&entry->list, &dev->msi_list);
+       pcidev_unlock(dev);
         *desc = entry;
     }
 
@@ -1231,11 +1241,13 @@ static void msi_free_irqs(struct pci_dev* dev)
 {
     struct msi_desc *entry, *tmp;
 
+    pcidev_lock(dev);
     list_for_each_entry_safe( entry, tmp, &dev->msi_list, list )
     {
         pci_disable_msi(entry);
         msi_free_irq(entry);
     }
+    pcidev_unlock(dev);
 }
 
 void pci_cleanup_msi(struct pci_dev *pdev)
@@ -1354,6 +1366,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
     if ( ret )
         return ret;
 
+    pcidev_lock(pdev);
     list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list )
     {
         unsigned int i = 0, nr = 1;
@@ -1371,6 +1384,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
             dprintk(XENLOG_ERR, "Restore MSI for %pp entry %u not set?\n",
                     &pdev->sbdf, i);
             spin_unlock_irqrestore(&desc->lock, flags);
+           pcidev_unlock(pdev);
             if ( type == PCI_CAP_ID_MSIX )
                 pci_conf_write16(pdev->sbdf, msix_control_reg(pos),
                                  control & ~PCI_MSIX_FLAGS_ENABLE);
@@ -1393,6 +1407,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
             if ( unlikely(!memory_decoded(pdev)) )
             {
                 spin_unlock_irqrestore(&desc->lock, flags);
+               pcidev_unlock(pdev);
                 pci_conf_write16(pdev->sbdf, msix_control_reg(pos),
                                  control & ~PCI_MSIX_FLAGS_ENABLE);
                 return -ENXIO;
@@ -1438,6 +1453,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
         pci_conf_write16(pdev->sbdf, msix_control_reg(pos),
                          control | PCI_MSIX_FLAGS_ENABLE);
 
+    pcidev_unlock(pdev);
     return 0;
 }
 
diff --git a/xen/drivers/passthrough/msi.c b/xen/drivers/passthrough/msi.c
index ce1a450f6f..98f4d2721a 100644
--- a/xen/drivers/passthrough/msi.c
+++ b/xen/drivers/passthrough/msi.c
@@ -22,6 +22,7 @@ int pdev_msi_init(struct pci_dev *pdev)
 {
     unsigned int pos;
 
+    pcidev_lock(pdev);
     INIT_LIST_HEAD(&pdev->msi_list);
 
     pos = pci_find_cap_offset(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
@@ -41,7 +42,10 @@ int pdev_msi_init(struct pci_dev *pdev)
         uint16_t ctrl;
 
         if ( !msix )
-            return -ENOMEM;
+        {
+             pcidev_unlock(pdev);
+             return -ENOMEM;
+        }
 
         spin_lock_init(&msix->table_lock);
 
@@ -51,6 +55,8 @@ int pdev_msi_init(struct pci_dev *pdev)
         pdev->msix = msix;
     }
 
+    pcidev_unlock(pdev);
+
     return 0;
 }
 
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index c8da80b981..c83397211b 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -1383,7 +1383,9 @@ static int cf_check _dump_pci_devices(struct pci_seg 
*pseg, void *arg)
             printk("%pd", pdev->domain);
         printk(" - node %-3d refcnt %d", (pdev->node != NUMA_NO_NODE) ? 
pdev->node : -1,
                atomic_read(&pdev->refcnt));
+        pcidev_lock(pdev);
         pdev_dump_msi(pdev);
+        pcidev_unlock(pdev);
         printk("\n");
     }
     spin_unlock(&pseg->alldevs_lock);
diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
index e71a180ef3..d0a7339d84 100644
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -106,6 +106,8 @@ struct pci_dev {
     uint8_t msi_maxvec;
     uint8_t phantom_stride;
 
+    /* Device lock */
+    spinlock_t lock;
     nodeid_t node; /* NUMA node */
 
     /* Device to be quarantined, don't automatically re-assign to dom0 */
@@ -235,6 +237,16 @@ int msixtbl_pt_register(struct domain *, struct pirq *, 
uint64_t gtable);
 void msixtbl_pt_unregister(struct domain *, struct pirq *);
 void msixtbl_pt_cleanup(struct domain *d);
 
+static inline void pcidev_lock(struct pci_dev *pdev)
+{
+    spin_lock(&pdev->lock);
+}
+
+static inline void pcidev_unlock(struct pci_dev *pdev)
+{
+    spin_unlock(&pdev->lock);
+}
+
 #ifdef CONFIG_HVM
 int arch_pci_clean_pirqs(struct domain *d);
 #else
-- 
2.36.1



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.