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@xxxxxxx> --- drivers/iommu/iommu-sva.c | 26 ++++++++++++++++++++++++++ include/linux/iommu.h | 6 ++++++ 2 files changed, 32 insertions(+) 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 */ -- 2.15.1