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

[PATCH v6 6/9] xen/arm: smmuv3: Add PCI devices support for SMMUv3


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
  • Date: Thu, 9 Nov 2023 13:27:09 -0500
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lists.xenproject.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0)
  • 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=rQYTJpj4QbN4iIjk7+Mt55dnJorFy1YCp47ylKDnXSk=; b=iaiGESe5Y8SRtyxByoPwACufDSgba40N0IGaw1lHob7R8f2YWkMwMZh3GO7PVD3qTKmYTI+clXyK7ipJgz77kxzbbu/N9wOdTdMZdE1vpt7BDZ34/YXVnuik1lNkUU+JmtHF08O350K2N3/gPhWUDaus1k3c1pLF8tAhlmAt+KWpP7ChGk0mjWOeC2aALQh43ZGNbG+z4AbqeyccFfyyXipkBRqdxdmAWLVZUdFzsmWQRnUBNmfMl0ERWaDqv/Ewu+CzTf/T7ZGfY7dzsTkS52cpNRiRjgkR1o/qUWZ1sudmyawkp/gR6Z9HFhgwTZj+wQRLmgBVsZUUglY9YuaS+g==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Hs6rCOBEHwqsKXNWwKQGnU+p1HVRsQshj2iL2SbqjfzD28SvEOaa1t6WASy0BAecQ4J7OwZNCHImC2OmwAta+K4LLJwSz3u+oXbysVjJKIBznA9LISEfT1u+1v+m2FkHo5sunuvgh2mu4A04a2b68UThdwy5Qqz2kiph+nfGZLTUTlCK1zKWw1s68mh7anwwoA3GdY/oWJ/4aQMAiErOWNbIh2JwoYUvOE+d6e457DLZ2KqSYlwDQEGmII9sstBKUv6+2cnzYfh3WWc7ikp6UKUvwfHn51VXvqOnaZDIizYnxg6+VSH21oh0EhBnFxWIhxXs+eUFQK1aW5j3hB2ogA==
  • Cc: Rahul Singh <rahul.singh@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
  • Delivery-date: Thu, 09 Nov 2023 18:29:45 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

From: Rahul Singh <rahul.singh@xxxxxxx>

Signed-off-by: Rahul Singh <rahul.singh@xxxxxxx>
Signed-off-by: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
---
v5->v6:
* check for hardware_domain == NULL (dom0less test case)
* locking: assign pdev->domain before list_add()

v4->v5:
* deassign from hwdom
* add TODO regarding locking
* fixup after dropping ("xen/arm: Move is_protected flag to struct device")

v3->v4:
* no change

v2->v3:
* rebase
* invoke iommu_add_pci_sideband_ids() from add_device hook

v1->v2:
* ignore add_device/assign_device/reassign_device calls for phantom functions
  (i.e. devfn != pdev->devfn)

downstream->v1:
* rebase
* move 2 replacements of 
s/dt_device_set_protected(dev_to_dt(dev))/device_set_protected(dev)/
  from this commit to ("xen/arm: Move is_protected flag to struct device")
  so as to not break ability to bisect
* adjust patch title (remove stray space)
* arm_smmu_(de)assign_dev: return error instead of crashing system
* remove arm_smmu_remove_device() stub
* update condition in arm_smmu_reassign_dev
* style fixup

(cherry picked from commit 7ed6c3ab250d899fe6e893a514278e406a2893e8 from
 the downstream branch poc/pci-passthrough from
 https://gitlab.com/xen-project/people/bmarquis/xen-arm-poc.git)
---
 xen/drivers/passthrough/arm/smmu-v3.c | 131 ++++++++++++++++++++++++--
 1 file changed, 121 insertions(+), 10 deletions(-)

diff --git a/xen/drivers/passthrough/arm/smmu-v3.c 
b/xen/drivers/passthrough/arm/smmu-v3.c
index cdbb505134b7..ac6532e29b02 100644
--- a/xen/drivers/passthrough/arm/smmu-v3.c
+++ b/xen/drivers/passthrough/arm/smmu-v3.c
@@ -1469,14 +1469,34 @@ static bool arm_smmu_sid_in_range(struct 
arm_smmu_device *smmu, u32 sid)
 }
 /* Forward declaration */
 static struct arm_smmu_device *arm_smmu_get_by_dev(const struct device *dev);
+static int arm_smmu_assign_dev(struct domain *d, u8 devfn, struct device *dev,
+                              u32 flag);
+static int arm_smmu_deassign_dev(struct domain *d, uint8_t devfn,
+                                struct device *dev);
 
 static int arm_smmu_add_device(u8 devfn, struct device *dev)
 {
        int i, ret;
        struct arm_smmu_device *smmu;
        struct arm_smmu_master *master;
-       struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+       struct iommu_fwspec *fwspec;
+
+#ifdef CONFIG_HAS_PCI
+       if ( dev_is_pci(dev) )
+       {
+               struct pci_dev *pdev = dev_to_pci(dev);
+               int ret;
+
+               if ( devfn != pdev->devfn )
+                       return 0;
+
+               ret = iommu_add_pci_sideband_ids(pdev);
+               if ( ret < 0 )
+                       iommu_fwspec_free(dev);
+       }
+#endif
 
+       fwspec = dev_iommu_fwspec_get(dev);
        if (!fwspec)
                return -ENODEV;
 
@@ -1521,17 +1541,35 @@ static int arm_smmu_add_device(u8 devfn, struct device 
*dev)
         */
        arm_smmu_enable_pasid(master);
 
-       if (dt_device_is_protected(dev_to_dt(dev))) {
-               dev_err(dev, "Already added to SMMUv3\n");
-               return -EEXIST;
-       }
+       if ( !dev_is_pci(dev) )
+       {
+               if (dt_device_is_protected(dev_to_dt(dev))) {
+                       dev_err(dev, "Already added to SMMUv3\n");
+                       return -EEXIST;
+               }
 
-       /* Let Xen know that the master device is protected by an IOMMU. */
-       dt_device_set_protected(dev_to_dt(dev));
+               /* Let Xen know that the master device is protected by an 
IOMMU. */
+               dt_device_set_protected(dev_to_dt(dev));
+       }
 
        dev_info(dev, "Added master device (SMMUv3 %s StreamIds %u)\n",
                        dev_name(fwspec->iommu_dev), fwspec->num_ids);
 
+#ifdef CONFIG_HAS_PCI
+       if ( dev_is_pci(dev) )
+       {
+               struct pci_dev *pdev = dev_to_pci(dev);
+
+               /*
+                * During PHYSDEVOP_pci_device_add, Xen does not assign the
+                * device, so we must do it here.
+                */
+               ret = arm_smmu_assign_dev(pdev->domain, devfn, dev, 0);
+               if (ret)
+                       goto err_free_master;
+       }
+#endif
+
        return 0;
 
 err_free_master:
@@ -2621,6 +2659,61 @@ static int arm_smmu_assign_dev(struct domain *d, u8 
devfn,
        struct arm_smmu_domain *smmu_domain;
        struct arm_smmu_xen_domain *xen_domain = dom_iommu(d)->arch.priv;
 
+#ifdef CONFIG_HAS_PCI
+       if ( dev_is_pci(dev) && !is_hardware_domain(d) )
+       {
+               struct pci_dev *pdev = dev_to_pci(dev);
+
+               printk(XENLOG_INFO "Assigning device %04x:%02x:%02x.%u to 
dom%d\n",
+                       pdev->seg, pdev->bus, PCI_SLOT(devfn),
+                       PCI_FUNC(devfn), d->domain_id);
+
+               if ( devfn != pdev->devfn || pdev->domain == d )
+                       return 0;
+
+               ASSERT(pcidevs_locked());
+
+               /* TODO: acquire pci_lock */
+#if 0
+               write_lock(&pdev->domain->pci_lock);
+#endif
+               list_del(&pdev->domain_list);
+#if 0
+               write_unlock(&pdev->domain->pci_lock);
+#endif
+
+               pdev->domain = d;
+
+#if 0
+               write_lock(&d->pci_lock);
+#endif
+               list_add(&pdev->domain_list, &d->pdev_list);
+#if 0
+               write_unlock(&d->pci_lock);
+#endif
+
+               if ( hardware_domain )
+               {
+                       io_domain = arm_smmu_get_domain(hardware_domain, dev);
+
+                       /*
+                        * Xen may not deassign the device from hwdom before
+                        * assigning it elsewhere.
+                        */
+                       if ( io_domain )
+                       {
+                               ret = arm_smmu_deassign_dev(hardware_domain, 
devfn, dev);
+                               if ( ret )
+                                       return ret;
+                       }
+               }
+
+               /* dom_io is used as a sentinel for quarantined devices */
+               if ( d == dom_io )
+                       return 0;
+       }
+#endif
+
        spin_lock(&xen_domain->lock);
 
        /*
@@ -2654,7 +2747,7 @@ out:
        return ret;
 }
 
-static int arm_smmu_deassign_dev(struct domain *d, struct device *dev)
+static int arm_smmu_deassign_dev(struct domain *d, uint8_t devfn, struct 
device *dev)
 {
        struct iommu_domain *io_domain = arm_smmu_get_domain(d, dev);
        struct arm_smmu_xen_domain *xen_domain = dom_iommu(d)->arch.priv;
@@ -2666,6 +2759,24 @@ static int arm_smmu_deassign_dev(struct domain *d, 
struct device *dev)
                return -ESRCH;
        }
 
+#ifdef CONFIG_HAS_PCI
+       if ( dev_is_pci(dev) )
+       {
+               struct pci_dev *pdev = dev_to_pci(dev);
+
+               printk(XENLOG_INFO "Deassigning device %04x:%02x:%02x.%u from 
dom%d\n",
+                       pdev->seg, pdev->bus, PCI_SLOT(devfn),
+                       PCI_FUNC(devfn), d->domain_id);
+
+               if ( devfn != pdev->devfn )
+                       return 0;
+
+               /* dom_io is used as a sentinel for quarantined devices */
+               if ( d == dom_io )
+                       return 0;
+       }
+#endif
+
        spin_lock(&xen_domain->lock);
 
        arm_smmu_detach_dev(master);
@@ -2685,13 +2796,13 @@ static int arm_smmu_reassign_dev(struct domain *s, 
struct domain *t,
        int ret = 0;
 
        /* Don't allow remapping on other domain than hwdom */
-       if ( t && !is_hardware_domain(t) )
+       if ( t && !is_hardware_domain(t) && (t != dom_io) )
                return -EPERM;
 
        if (t == s)
                return 0;
 
-       ret = arm_smmu_deassign_dev(s, dev);
+       ret = arm_smmu_deassign_dev(s, devfn, dev);
        if (ret)
                return ret;
 
-- 
2.42.0




 


Rackspace

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