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

[PATCH v2 1/3] PCI: simplify (and thus correct) pci_get_pdev{,_by_domain}()


  • To: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Jan Beulich <jbeulich@xxxxxxxx>
  • Date: Thu, 11 Aug 2022 12:51:30 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=suse.com; dmarc=pass action=none header.from=suse.com; dkim=pass header.d=suse.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=ROeaBlVhWUfxYWHNj4EnOD1wrL9+c+7pgHiRTazbgrg=; b=jp5FTLb3wOuNHXs/3SbsXcclq7evyYHXYoApHTpBz0A8McDqJSz92HsgnN+KdMwUq7kNd9dgVdxgYufj5UdNzjtF7QkOTPuYOjoMo9TzTYnNSQVl1EvN5Z/8bDbSlq5X7ZiK20OYhDK0h4bJWc5dYHVhOkRyRgBGhCUWT3079hZjhv89aQNlOMFBrs4+kZpb31fgmiH5nfnQVweaPe64NiOuYl/ygRt6I5qe9x5R0zMdxWQhwFdoswkpxnCk3TZzKp6+ZWkGN0TA/wTBNHs88T8siNOXQS9Wd+jaJ8ISV7o3OJZhI7VLOvd8tXzMBy0eTD3LTFESNFRUhh0aYbn9RA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JUTiU/4yF3eOiUwk5uqp5iM68a+BfYwxvTUtNKOBuWX8hXF23Lu3+P0TehvXqj+RE+AI/8UQJXgkgN+Lz6FqNalxRXPCVPIa/k3oSOppGrFBEgPA4aXUSaOil4iCBvU3q2F4hdzOe3c4LrZZBUv0yuEVDsfMTe14v8Um+sodKgGEkhjQwnLQZA8D6PVhxbczy62EVw4cgGEtX34T1YKIZ3TtLBvh450Z0K2tt6WhJxehzU3dB46HDw4XjIVGAlPk6KXVdtSvw2tiHWL1cjTsgW3zZhuNKXZX9kZaG78+Bqum49adfXIDXl3US8/45JcCB7uKyM40ZFeZVX68p1vRGA==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=suse.com;
  • Cc: Paul Durrant <paul@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Rahul Singh <Rahul.Singh@xxxxxxx>
  • Delivery-date: Thu, 11 Aug 2022 10:51:37 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

The last "wildcard" use of either function went away with f591755823a7
("IOMMU/PCI: don't let domain cleanup continue when device de-assignment
failed"). Don't allow them to be called this way anymore. Besides
simplifying the code this also fixes two bugs:

1) When seg != -1, the outer loops should have been terminated after the
   first iteration, or else a device with the same BDF but on another
   segment could be found / returned.

Reported-by: Rahul Singh <rahul.singh@xxxxxxx>

2) When seg == -1 calling get_pseg() is bogus. The function (taking a
   u16) would look for segment 0xffff, which might exist. If it exists,
   we might then find / return a wrong device.

In pci_get_pdev_by_domain() also switch from using the per-segment list
to using the per-domain one, with the exception of the hardware domain
(see the code comment there).

While there also constify "pseg" and drop "pdev"'s already previously
unnecessary initializer.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
v2: Full rework, with even the title changed.

--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -576,30 +576,19 @@ int __init pci_ro_device(int seg, int bu
     return 0;
 }
 
-struct pci_dev *pci_get_pdev(int seg, int bus, int devfn)
+struct pci_dev *pci_get_pdev(uint16_t seg, uint8_t bus, uint8_t devfn)
 {
-    struct pci_seg *pseg = get_pseg(seg);
-    struct pci_dev *pdev = NULL;
+    const struct pci_seg *pseg = get_pseg(seg);
+    struct pci_dev *pdev;
 
     ASSERT(pcidevs_locked());
-    ASSERT(seg != -1 || bus == -1);
-    ASSERT(bus != -1 || devfn == -1);
 
     if ( !pseg )
-    {
-        if ( seg == -1 )
-            radix_tree_gang_lookup(&pci_segments, (void **)&pseg, 0, 1);
-        if ( !pseg )
-            return NULL;
-    }
+        return NULL;
 
-    do {
-        list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
-            if ( (pdev->bus == bus || bus == -1) &&
-                 (pdev->devfn == devfn || devfn == -1) )
-                return pdev;
-    } while ( radix_tree_gang_lookup(&pci_segments, (void **)&pseg,
-                                     pseg->nr + 1, 1) );
+    list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
+        if ( pdev->bus == bus && pdev->devfn == devfn )
+            return pdev;
 
     return NULL;
 }
@@ -625,31 +614,33 @@ struct pci_dev *pci_get_real_pdev(int se
     return pdev;
 }
 
-struct pci_dev *pci_get_pdev_by_domain(const struct domain *d, int seg,
-                                       int bus, int devfn)
+struct pci_dev *pci_get_pdev_by_domain(const struct domain *d, uint16_t seg,
+                                       uint8_t bus, uint8_t devfn)
 {
-    struct pci_seg *pseg = get_pseg(seg);
-    struct pci_dev *pdev = NULL;
-
-    ASSERT(seg != -1 || bus == -1);
-    ASSERT(bus != -1 || devfn == -1);
+    struct pci_dev *pdev;
 
-    if ( !pseg )
+    /*
+     * The hardware domain owns the majority of the devices in the system.
+     * When there are multiple segments, traversing the per-segment list is
+     * likely going to be faster, whereas for a single segment the difference
+     * shouldn't be that large.
+     */
+    if ( is_hardware_domain(d) )
     {
-        if ( seg == -1 )
-            radix_tree_gang_lookup(&pci_segments, (void **)&pseg, 0, 1);
+        const struct pci_seg *pseg = get_pseg(seg);
+
         if ( !pseg )
             return NULL;
-    }
 
-    do {
         list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
-            if ( (pdev->bus == bus || bus == -1) &&
-                 (pdev->devfn == devfn || devfn == -1) &&
-                 (pdev->domain == d) )
+            if ( pdev->bus == bus && pdev->devfn == devfn &&
+                 pdev->domain == d )
+                return pdev;
+    }
+    else
+        list_for_each_entry ( pdev, &d->pdev_list, domain_list )
+            if ( pdev->bus == bus && pdev->devfn == devfn )
                 return pdev;
-    } while ( radix_tree_gang_lookup(&pci_segments, (void **)&pseg,
-                                     pseg->nr + 1, 1) );
 
     return NULL;
 }
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -177,10 +177,10 @@ int pci_add_device(u16 seg, u8 bus, u8 d
 int pci_remove_device(u16 seg, u8 bus, u8 devfn);
 int pci_ro_device(int seg, int bus, int devfn);
 int pci_hide_device(unsigned int seg, unsigned int bus, unsigned int devfn);
-struct pci_dev *pci_get_pdev(int seg, int bus, int devfn);
+struct pci_dev *pci_get_pdev(uint16_t seg, uint8_t bus, uint8_t devfn);
 struct pci_dev *pci_get_real_pdev(int seg, int bus, int devfn);
-struct pci_dev *pci_get_pdev_by_domain(const struct domain *, int seg,
-                                       int bus, int devfn);
+struct pci_dev *pci_get_pdev_by_domain(const struct domain *, uint16_t seg,
+                                       uint8_t bus, uint8_t devfn);
 void pci_check_disable_device(u16 seg, u8 bus, u8 devfn);
 
 uint8_t pci_conf_read8(pci_sbdf_t sbdf, unsigned int reg);




 


Rackspace

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