diff mbox series

[v3,06/10] iommu/sva: Search mm by PASID

Message ID 20180920170046.20154-7-jean-philippe.brucker@arm.com
State Not Applicable
Headers show
Series Shared Virtual Addressing for the IOMMU | expand

Commit Message

Jean-Philippe Brucker Sept. 20, 2018, 5 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.

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

Comments

Baolu Lu Sept. 25, 2018, 4:59 a.m. UTC | #1
Hi,

On 09/21/2018 01:00 AM, Jean-Philippe Brucker wrote:
> 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 <jean-philippe.brucker@arm.com>
> ---
>   drivers/iommu/iommu-sva.c | 26 ++++++++++++++++++++++++++
>   include/linux/iommu.h     |  7 +++++++
>   2 files changed, 33 insertions(+)
> 
> diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
> index 5ff8967cb213..ee86f00ee1b9 100644
> --- a/drivers/iommu/iommu-sva.c
> +++ b/drivers/iommu/iommu-sva.c
> @@ -636,6 +636,32 @@ void iommu_sva_unbind_device_all(struct device *dev)
>   }
>   EXPORT_SYMBOL_GPL(iommu_sva_unbind_device_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);

The same thing here. We can't guarantee that a pointer of mm_struct type
is associated with a pasid value when pasid is also used for other
purposes. If hardware reports a bad pasid, this function might run into
problem.

Best regards,
Lu Baolu

> +	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);
> +
>   /**
>    * iommu_sva_init_device() - Initialize Shared Virtual Addressing for a device
>    * @dev: the device
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index 429f3dc37a35..a457650b80de 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -987,6 +987,8 @@ extern int __iommu_sva_bind_device(struct device *dev, struct mm_struct *mm,
>   				   void *drvdata);
>   extern int __iommu_sva_unbind_device(struct device *dev, int pasid);
>   extern void iommu_sva_unbind_device_all(struct device *dev);
> +extern struct mm_struct *iommu_sva_find(int pasid);
> +
>   #else /* CONFIG_IOMMU_SVA */
>   static inline int iommu_sva_init_device(struct device *dev,
>   					unsigned long features,
> @@ -1016,6 +1018,11 @@ static inline int __iommu_sva_unbind_device(struct device *dev, int pasid)
>   static inline void iommu_sva_unbind_device_all(struct device *dev)
>   {
>   }
> +
> +static inline struct mm_struct *iommu_sva_find(int pasid)
> +{
> +	return NULL;
> +}
>   #endif /* CONFIG_IOMMU_SVA */
>   
>   #endif /* __LINUX_IOMMU_H */
>
diff mbox series

Patch

diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index 5ff8967cb213..ee86f00ee1b9 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -636,6 +636,32 @@  void iommu_sva_unbind_device_all(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(iommu_sva_unbind_device_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);
+
 /**
  * iommu_sva_init_device() - Initialize Shared Virtual Addressing for a device
  * @dev: the device
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 429f3dc37a35..a457650b80de 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -987,6 +987,8 @@  extern int __iommu_sva_bind_device(struct device *dev, struct mm_struct *mm,
 				   void *drvdata);
 extern int __iommu_sva_unbind_device(struct device *dev, int pasid);
 extern void iommu_sva_unbind_device_all(struct device *dev);
+extern struct mm_struct *iommu_sva_find(int pasid);
+
 #else /* CONFIG_IOMMU_SVA */
 static inline int iommu_sva_init_device(struct device *dev,
 					unsigned long features,
@@ -1016,6 +1018,11 @@  static inline int __iommu_sva_unbind_device(struct device *dev, int pasid)
 static inline void iommu_sva_unbind_device_all(struct device *dev)
 {
 }
+
+static inline struct mm_struct *iommu_sva_find(int pasid)
+{
+	return NULL;
+}
 #endif /* CONFIG_IOMMU_SVA */
 
 #endif /* __LINUX_IOMMU_H */