The PASID-granular 2nd level address translation makes it possible
to isolate and protect a mediated device exposed by a real device
which support PCI PASID features. This patch adds support to allocate
a domain for a mediated device. A default pasid value will be
allocated as well for the mediated device. This will be used by the
mediated device attached to this domain for non-SVM DMA transactions.

Cc: Ashok Raj <[email protected]>
Cc: Jacob Pan <[email protected]>
Cc: Kevin Tian <[email protected]>
Cc: Liu Yi L <[email protected]>
Signed-off-by: Sanjay Kumar <[email protected]>
Signed-off-by: Lu Baolu <[email protected]>
---
 drivers/iommu/intel-iommu.c | 17 ++++++++++++++++-
 include/linux/intel-iommu.h |  5 +++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index fc3ac1c..3ede34a 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1926,6 +1926,9 @@ static void domain_exit(struct dmar_domain *domain)
        domain_remove_dev_info(domain);
        rcu_read_unlock();
 
+       if (domain->default_pasid > 0)
+               intel_pasid_free_id(domain->default_pasid);
+
        /* destroy iovas */
        put_iova_domain(&domain->iovad);
 
@@ -2519,11 +2522,23 @@ static struct dmar_domain 
*dmar_insert_one_dev_info(struct intel_iommu *iommu,
                }
        }
 
+       if (dev && dev_is_mdev(dev) && domain->default_pasid <= 0) {
+               int max = intel_pasid_get_dev_max_id(dev_mdev_parent(dev));
+
+               domain->default_pasid = intel_pasid_alloc_id(domain, PASID_MIN,
+                                                            max, GFP_KERNEL);
+               if (domain->default_pasid < 0) {
+                       free_devinfo_mem(info);
+                       return NULL;
+               }
+       }
+
        spin_lock_irqsave(&device_domain_lock, flags);
        if (dev)
                found = find_domain(dev);
 
-       if (!found) {
+       /* A mediated device never has an DMA alias. Ignore searching. */
+       if (!found && !dev_is_mdev(dev)) {
                struct device_domain_info *info2;
                info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, 
devfn);
                if (info2) {
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 7efc632..9f5dcf6 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -423,6 +423,11 @@ struct dmar_domain {
                                           2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
        u64             max_addr;       /* maximum mapped address */
 
+       int             default_pasid;  /*
+                                        * The default pasid used for non-SVM
+                                        * traffic on mediated devices.
+                                        */
+
        struct iommu_domain domain;     /* generic domain data structure for
                                           iommu core */
 };
-- 
2.7.4

_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to