From b7573c82e4d756f192b2ccd0c2d1b660e267ac1f Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Sat, 18 May 2019 22:09:22 +0800 Subject: [PATCH] iommu/sva: Search mm by PASID hulk inclusion category: feature bugzilla: 14369 CVE: NA ------------------- 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. Signed-off-by: Jean-Philippe Brucker Signed-off-by: Fang Lijun Reviewed-by: Hanjun Guo Reviewed-by: Zhen Lei Signed-off-by: Yang Yingliang --- 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 6c3a99d00766..1303c3559fa7 100644 --- a/drivers/iommu/iommu-sva.c +++ b/drivers/iommu/iommu-sva.c @@ -737,3 +737,29 @@ void __iommu_sva_unbind_dev_all(struct device *dev) } } EXPORT_SYMBOL_GPL(__iommu_sva_unbind_dev_all); + +/** + * iommu_sva_find() - Find mm associated to the given PASID + * @pasid: Process Address Space ID assigned to the mm + * + * 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 d82ff3ebd6f3..e1bb02d13065 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -1009,6 +1009,7 @@ extern int __iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, extern int __iommu_sva_unbind_device(struct device *dev, int pasid); extern void __iommu_sva_unbind_dev_all(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, @@ -1038,6 +1039,11 @@ static inline int __iommu_sva_unbind_device(struct device *dev, int pasid) static inline void __iommu_sva_unbind_dev_all(struct device *dev) { } + +static inline struct mm_struct *iommu_sva_find(int pasid) +{ + return NULL; +} #endif /* CONFIG_IOMMU_SVA */ #ifdef CONFIG_IOMMU_DEBUGFS -- GitLab