[RFC PATCH 02/10] iommu/vt-d: Alloc domain for a mediated device

From: Lu Baolu
Date: Sun Jul 22 2018 - 02:11:18 EST


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 <ashok.raj@xxxxxxxxx>
Cc: Jacob Pan <jacob.jun.pan@xxxxxxxxxxxxxxx>
Cc: Kevin Tian <kevin.tian@xxxxxxxxx>
Cc: Liu Yi L <yi.l.liu@xxxxxxxxx>
Signed-off-by: Sanjay Kumar <sanjay.k.kumar@xxxxxxxxx>
Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
---
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