diff mbox

[06/37] iommu/sva: Search mm by PASID

Message ID 20180212183352.22730-7-jean-philippe.brucker@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jean-Philippe Brucker Feb. 12, 2018, 6:33 p.m. UTC
The fault handler will need to find an mm given its PASID. This is the
reason we have an IDR for storing address spaces, so hook it up. A future
optimization could find the io_mm from the struct device passed to the
fault handler, since it's readily accessible.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
---
 drivers/iommu/iommu-sva.c | 26 ++++++++++++++++++++++++++
 include/linux/iommu.h     |  6 ++++++
 2 files changed, 32 insertions(+)
diff mbox

Patch

diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index 9108adb54ec7..4bc2a8c12465 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -10,6 +10,7 @@ 
 #include <linux/idr.h>
 #include <linux/iommu.h>
 #include <linux/mmu_notifier.h>
+#include <linux/sched/mm.h>
 #include <linux/slab.h>
 #include <linux/sched/mm.h>
 #include <linux/spinlock.h>
@@ -770,3 +771,28 @@  int iommu_unregister_mm_exit_handler(struct device *dev)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iommu_unregister_mm_exit_handler);
+
+/*
+ * iommu_sva_find() - Find mm associated to the given PASID
+ *
+ * Returns the mm corresponding to this PASID, or NULL if not found. A reference
+ * to the mm is taken, and must be released with mmput().
+ */
+struct mm_struct *iommu_sva_find(int pasid)
+{
+	struct io_mm *io_mm;
+	struct mm_struct *mm = NULL;
+
+	spin_lock(&iommu_sva_lock);
+	io_mm = idr_find(&iommu_pasid_idr, pasid);
+	if (io_mm && io_mm_get_locked(io_mm)) {
+		if (mmget_not_zero(io_mm->mm))
+			mm = io_mm->mm;
+
+		io_mm_put_locked(io_mm);
+	}
+	spin_unlock(&iommu_sva_lock);
+
+	return mm;
+}
+EXPORT_SYMBOL_GPL(iommu_sva_find);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index afec7b1d3301..226ab4f3ae0e 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -958,6 +958,7 @@  extern int iommu_register_mm_exit_handler(struct device *dev,
 					  iommu_mm_exit_handler_t handler);
 extern int iommu_unregister_mm_exit_handler(struct device *dev);
 
+extern struct mm_struct *iommu_sva_find(int pasid);
 #else /* CONFIG_IOMMU_SVA */
 static inline int iommu_sva_device_init(struct device *dev,
 					unsigned long features,
@@ -997,6 +998,11 @@  static inline int iommu_unregister_mm_exit_handler(struct device *dev)
 {
 	return -ENODEV;
 }
+
+static inline struct mm_struct *iommu_sva_find(int pasid)
+{
+	return NULL;
+}
 #endif /* CONFIG_IOMMU_SVA */
 
 #endif /* __LINUX_IOMMU_H */