Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
On Thu, Apr 15, 2021 at 01:33:24PM +0800, Lu Baolu wrote: > Hi Jason, > > On 4/14/21 7:26 PM, Jason Gunthorpe wrote: > > On Wed, Apr 14, 2021 at 02:22:09PM +0800, Lu Baolu wrote: > > > > > I still worry about supervisor pasid allocation. > > > > > > If we use iommu_sva_alloc_pasid() to allocate a supervisor pasid, which > > > mm should the pasid be set? I've ever thought about passing _mm to > > > iommu_sva_alloc_pasid(). But if you add "mm != current->mm", this seems > > > not to work. Or do you prefer a separated interface for supervisor pasid > > > allocation/free? > > > > Without a mm_struct it is not SVA, so don't use SVA APIs for whatever > > a 'supervisor pasid' is > > The supervisor PASID has its mm_struct. The only difference is that the > device will set priv=1 in its DMA transactions with the PASID. Soemthing like init_mm should not be used with 'SVA' Jason ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Jason, On 4/14/21 7:26 PM, Jason Gunthorpe wrote: On Wed, Apr 14, 2021 at 02:22:09PM +0800, Lu Baolu wrote: I still worry about supervisor pasid allocation. If we use iommu_sva_alloc_pasid() to allocate a supervisor pasid, which mm should the pasid be set? I've ever thought about passing _mm to iommu_sva_alloc_pasid(). But if you add "mm != current->mm", this seems not to work. Or do you prefer a separated interface for supervisor pasid allocation/free? Without a mm_struct it is not SVA, so don't use SVA APIs for whatever a 'supervisor pasid' is The supervisor PASID has its mm_struct. The only difference is that the device will set priv=1 in its DMA transactions with the PASID. Best regards, baolu ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
On Wed, Apr 14, 2021 at 02:22:09PM +0800, Lu Baolu wrote: > I still worry about supervisor pasid allocation. > > If we use iommu_sva_alloc_pasid() to allocate a supervisor pasid, which > mm should the pasid be set? I've ever thought about passing _mm to > iommu_sva_alloc_pasid(). But if you add "mm != current->mm", this seems > not to work. Or do you prefer a separated interface for supervisor pasid > allocation/free? Without a mm_struct it is not SVA, so don't use SVA APIs for whatever a 'supervisor pasid' is Jason ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Jacob, On 4/14/21 8:09 AM, Jacob Pan wrote: Hi Jean, On Fri, 9 Apr 2021 11:03:05 -0700, Jacob Pan wrote: problems: * We don't have a use-case for binding the mm of a remote process (and it's supposedly difficult for device drivers to do it securely). So OK, we remove the mm argument from iommu_sva_bind_device() and use the current mm. But the IOMMU driver isn't going to do get_task_mm(current) every time it needs the mm being bound, it will take it from iommu_sva_bind_device(). Likewise iommu_sva_alloc_pasid() shouldn't need to bother with get_task_mm(). * cgroup accounting for IOASIDs needs to be on the current task. Removing the mm parameter from iommu_sva_alloc_pasid() doesn't help with that. Sure it indicates that iommu_sva_alloc_pasid() needs a specific task context but that's only for cgroup purpose, and I'd rather pass the cgroup down from iommu_sva_bind_device() anyway (but am fine with keeping it within ioasid_alloc() for now). Plus it's an internal helper, easy for us to check that the callers are doing the right thing. With the above split, we really just have one allocation function: ioasid_alloc(), so it can manage current cgroup accounting within. Would this work? After a few attempts, I don't think the split can work better. I will restore the mm parameter and add a warning if mm != current->mm. I still worry about supervisor pasid allocation. If we use iommu_sva_alloc_pasid() to allocate a supervisor pasid, which mm should the pasid be set? I've ever thought about passing _mm to iommu_sva_alloc_pasid(). But if you add "mm != current->mm", this seems not to work. Or do you prefer a separated interface for supervisor pasid allocation/free? Best regards, baolu Thanks, Jacob ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Jean, On Fri, 9 Apr 2021 11:03:05 -0700, Jacob Pan wrote: > > problems: > > > > * We don't have a use-case for binding the mm of a remote process (and > > it's supposedly difficult for device drivers to do it securely). So > > OK, we remove the mm argument from iommu_sva_bind_device() and use the > > current mm. But the IOMMU driver isn't going to do > > get_task_mm(current) every time it needs the mm being bound, it will > > take it from iommu_sva_bind_device(). Likewise iommu_sva_alloc_pasid() > > shouldn't need to bother with get_task_mm(). > > > > * cgroup accounting for IOASIDs needs to be on the current task. > > Removing the mm parameter from iommu_sva_alloc_pasid() doesn't help > > with that. Sure it indicates that iommu_sva_alloc_pasid() needs a > > specific task context but that's only for cgroup purpose, and I'd > > rather pass the cgroup down from iommu_sva_bind_device() anyway (but am > > fine with keeping it within ioasid_alloc() for now). Plus it's an > > internal helper, easy for us to check that the callers are doing the > > right thing. > With the above split, we really just have one allocation function: > ioasid_alloc(), so it can manage current cgroup accounting within. Would > this work? After a few attempts, I don't think the split can work better. I will restore the mm parameter and add a warning if mm != current->mm. Thanks, Jacob ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Lu, On Fri, 9 Apr 2021 20:45:22 +0800, Lu Baolu wrote: > > -int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t > > max) +int iommu_sva_alloc_pasid(ioasid_t min, ioasid_t max) > > { > > int ret = 0; > > ioasid_t pasid; > > + struct mm_struct *mm; > > > > if (min == INVALID_IOASID || max == INVALID_IOASID || > > min == 0 || max < min) > > return -EINVAL; > > > > mutex_lock(_sva_lock); > > + mm = get_task_mm(current); > > How could we allocate a supervisor PASID through iommu_sva_alloc_pasid() > if we always use current->mm here? I don't think you can. But I guess the current callers of this function do not need supervisor PASID. In reply to Jean, I suggest we split this function into mm->pasid assignment and keep using ioasid_alloc() directly, then supervisor PASID is caller's bind choice. Thanks, Jacob ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Jean-Philippe, On Fri, 9 Apr 2021 12:11:47 +0200, Jean-Philippe Brucker wrote: > On Thu, Apr 08, 2021 at 10:08:56AM -0700, Jacob Pan wrote: > > diff --git a/drivers/iommu/iommu-sva-lib.c > > b/drivers/iommu/iommu-sva-lib.c index bd41405..bd99f6b 100644 > > --- a/drivers/iommu/iommu-sva-lib.c > > +++ b/drivers/iommu/iommu-sva-lib.c > > @@ -12,27 +12,33 @@ static DECLARE_IOASID_SET(iommu_sva_pasid); > > > > /** > > * iommu_sva_alloc_pasid - Allocate a PASID for the mm > > - * @mm: the mm > > * @min: minimum PASID value (inclusive) > > * @max: maximum PASID value (inclusive) > > * > > - * Try to allocate a PASID for this mm, or take a reference to the > > existing one > > - * provided it fits within the [@min, @max] range. On success the > > PASID is > > - * available in mm->pasid, and must be released with > > iommu_sva_free_pasid(). > > + * Try to allocate a PASID for the current mm, or take a reference to > > the > > + * existing one provided it fits within the [@min, @max] range. On > > success > > + * the PASID is available in the current mm->pasid, and must be > > released with > > + * iommu_sva_free_pasid(). > > * @min must be greater than 0, because 0 indicates an unused > > mm->pasid. * > > * Returns 0 on success and < 0 on error. > > */ > > -int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t > > max) +int iommu_sva_alloc_pasid(ioasid_t min, ioasid_t max) > > { > > int ret = 0; > > ioasid_t pasid; > > + struct mm_struct *mm; > > > > if (min == INVALID_IOASID || max == INVALID_IOASID || > > min == 0 || max < min) > > return -EINVAL; > > > > mutex_lock(_sva_lock); > > + mm = get_task_mm(current); > > + if (!mm) { > > + ret = -EINVAL; > > + goto out_unlock; > > + } > > I still think it would be more elegant to keep the choice of context in > iommu_sva_bind_device() and pass it down to leaf functions such as > iommu_sva_alloc_pasid(). The patch is trying to solve two separate I agree if iommu_sva_alloc_pasid() is a leaf function, but it is a public function, e.g. called by smmu code: /* Allocate a PASID for this mm if necessary */ ret = iommu_sva_alloc_pasid(1, (1U << master->ssid_bits) - 1); If we give mm as parameter, it will give callers the illusion that this mm doesn't have to be current->mm. Should we make it into a leaf function by splitting iommu_sva_alloc_pasid() into two parts? 1. iommu_sva_assign_pasid() //a new leaf helper function does mm->pasid assignment 2. ioasid_alloc() in iommu_sva_bind_device(), we do: 1. handle = driver ops->sva_bind(dev, mm, flags); 2. pasid = sva_get_pasid(handle); 3. iommu_sva_assign_pasid(mm, pasid) In vendor driver sva_bind(), it just use ioasid_alloc directly with custom range. e.g. arm-smmu-v3-sva.c - ret = iommu_sva_alloc_pasid(1, (1U << master->ssid_bits) - 1); + ret = ioasid_alloc(_sva_pasid, 1, (1U << master->ssid_bits); > problems: > > * We don't have a use-case for binding the mm of a remote process (and > it's supposedly difficult for device drivers to do it securely). So OK, > we remove the mm argument from iommu_sva_bind_device() and use the > current mm. But the IOMMU driver isn't going to do get_task_mm(current) > every time it needs the mm being bound, it will take it from > iommu_sva_bind_device(). Likewise iommu_sva_alloc_pasid() shouldn't need > to bother with get_task_mm(). > > * cgroup accounting for IOASIDs needs to be on the current task. Removing > the mm parameter from iommu_sva_alloc_pasid() doesn't help with that. > Sure it indicates that iommu_sva_alloc_pasid() needs a specific task > context but that's only for cgroup purpose, and I'd rather pass the > cgroup down from iommu_sva_bind_device() anyway (but am fine with > keeping it within ioasid_alloc() for now). Plus it's an internal helper, > easy for us to check that the callers are doing the right thing. > With the above split, we really just have one allocation function: ioasid_alloc(), so it can manage current cgroup accounting within. Would this work? > > if (mm->pasid) { > > if (mm->pasid >= min && mm->pasid <= max) > > ioasid_get(mm->pasid); > > @@ -45,22 +51,32 @@ int iommu_sva_alloc_pasid(struct mm_struct *mm, > > ioasid_t min, ioasid_t max) else > > mm->pasid = pasid; > > } > > + mmput(mm); > > +out_unlock: > > mutex_unlock(_sva_lock); > > return ret; > > } > > EXPORT_SYMBOL_GPL(iommu_sva_alloc_pasid); > > > > /** > > - * iommu_sva_free_pasid - Release the mm's PASID > > + * iommu_sva_free_pasid - Release the current mm's PASID > > * @mm: the mm > > * > > * Drop one reference to a PASID allocated with iommu_sva_alloc_pasid() > > */ > > -void iommu_sva_free_pasid(struct mm_struct *mm) > > +void iommu_sva_free_pasid(void) > > { > > + struct mm_struct *mm; > > + > > mutex_lock(_sva_lock); > > +
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi, On 2021/4/9 1:08, Jacob Pan wrote: /** * iommu_sva_alloc_pasid - Allocate a PASID for the mm - * @mm: the mm * @min: minimum PASID value (inclusive) * @max: maximum PASID value (inclusive) * - * Try to allocate a PASID for this mm, or take a reference to the existing one - * provided it fits within the [@min, @max] range. On success the PASID is - * available in mm->pasid, and must be released with iommu_sva_free_pasid(). + * Try to allocate a PASID for the current mm, or take a reference to the + * existing one provided it fits within the [@min, @max] range. On success + * the PASID is available in the current mm->pasid, and must be released with + * iommu_sva_free_pasid(). * @min must be greater than 0, because 0 indicates an unused mm->pasid. * * Returns 0 on success and < 0 on error. */ -int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) +int iommu_sva_alloc_pasid(ioasid_t min, ioasid_t max) { int ret = 0; ioasid_t pasid; + struct mm_struct *mm; if (min == INVALID_IOASID || max == INVALID_IOASID || min == 0 || max < min) return -EINVAL; mutex_lock(_sva_lock); + mm = get_task_mm(current); How could we allocate a supervisor PASID through iommu_sva_alloc_pasid() if we always use current->mm here? + if (!mm) { + ret = -EINVAL; + goto out_unlock; + } if (mm->pasid) { if (mm->pasid >= min && mm->pasid <= max) ioasid_get(mm->pasid); @@ -45,22 +51,32 @@ int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) else mm->pasid = pasid; } + mmput(mm); +out_unlock: mutex_unlock(_sva_lock); return ret; } EXPORT_SYMBOL_GPL(iommu_sva_alloc_pasid); Best regards, baolu ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
On Thu, Apr 08, 2021 at 10:08:56AM -0700, Jacob Pan wrote: > diff --git a/drivers/iommu/iommu-sva-lib.c b/drivers/iommu/iommu-sva-lib.c > index bd41405..bd99f6b 100644 > --- a/drivers/iommu/iommu-sva-lib.c > +++ b/drivers/iommu/iommu-sva-lib.c > @@ -12,27 +12,33 @@ static DECLARE_IOASID_SET(iommu_sva_pasid); > > /** > * iommu_sva_alloc_pasid - Allocate a PASID for the mm > - * @mm: the mm > * @min: minimum PASID value (inclusive) > * @max: maximum PASID value (inclusive) > * > - * Try to allocate a PASID for this mm, or take a reference to the existing > one > - * provided it fits within the [@min, @max] range. On success the PASID is > - * available in mm->pasid, and must be released with iommu_sva_free_pasid(). > + * Try to allocate a PASID for the current mm, or take a reference to the > + * existing one provided it fits within the [@min, @max] range. On success > + * the PASID is available in the current mm->pasid, and must be released with > + * iommu_sva_free_pasid(). > * @min must be greater than 0, because 0 indicates an unused mm->pasid. > * > * Returns 0 on success and < 0 on error. > */ > -int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) > +int iommu_sva_alloc_pasid(ioasid_t min, ioasid_t max) > { > int ret = 0; > ioasid_t pasid; > + struct mm_struct *mm; > > if (min == INVALID_IOASID || max == INVALID_IOASID || > min == 0 || max < min) > return -EINVAL; > > mutex_lock(_sva_lock); > + mm = get_task_mm(current); > + if (!mm) { > + ret = -EINVAL; > + goto out_unlock; > + } I still think it would be more elegant to keep the choice of context in iommu_sva_bind_device() and pass it down to leaf functions such as iommu_sva_alloc_pasid(). The patch is trying to solve two separate problems: * We don't have a use-case for binding the mm of a remote process (and it's supposedly difficult for device drivers to do it securely). So OK, we remove the mm argument from iommu_sva_bind_device() and use the current mm. But the IOMMU driver isn't going to do get_task_mm(current) every time it needs the mm being bound, it will take it from iommu_sva_bind_device(). Likewise iommu_sva_alloc_pasid() shouldn't need to bother with get_task_mm(). * cgroup accounting for IOASIDs needs to be on the current task. Removing the mm parameter from iommu_sva_alloc_pasid() doesn't help with that. Sure it indicates that iommu_sva_alloc_pasid() needs a specific task context but that's only for cgroup purpose, and I'd rather pass the cgroup down from iommu_sva_bind_device() anyway (but am fine with keeping it within ioasid_alloc() for now). Plus it's an internal helper, easy for us to check that the callers are doing the right thing. > if (mm->pasid) { > if (mm->pasid >= min && mm->pasid <= max) > ioasid_get(mm->pasid); > @@ -45,22 +51,32 @@ int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t > min, ioasid_t max) > else > mm->pasid = pasid; > } > + mmput(mm); > +out_unlock: > mutex_unlock(_sva_lock); > return ret; > } > EXPORT_SYMBOL_GPL(iommu_sva_alloc_pasid); > > /** > - * iommu_sva_free_pasid - Release the mm's PASID > + * iommu_sva_free_pasid - Release the current mm's PASID > * @mm: the mm > * > * Drop one reference to a PASID allocated with iommu_sva_alloc_pasid() > */ > -void iommu_sva_free_pasid(struct mm_struct *mm) > +void iommu_sva_free_pasid(void) > { > + struct mm_struct *mm; > + > mutex_lock(_sva_lock); > + mm = get_task_mm(current); > + if (!mm) > + goto out_unlock; > + More importantly, could we at least dissociate free_pasid() from the current process? Otherwise drivers can't clean up from a workqueue (as amdkfd does) or from an rcu callback. Given that iommu_sva_unbind_device() takes the SVA handle owned by whomever did bind(), there shouldn't be any security issue. For the cgroup problem, ioasid.c could internally keep track of the cgroup used during allocation rather than assuming the context of ioasid_put() is the same as ioasid_get() > if (ioasid_put(mm->pasid)) > mm->pasid = 0; > + mmput(mm); > +out_unlock: > mutex_unlock(_sva_lock); > } > EXPORT_SYMBOL_GPL(iommu_sva_free_pasid); > diff --git a/drivers/iommu/iommu-sva-lib.h b/drivers/iommu/iommu-sva-lib.h > index b40990a..278b8b4 100644 > --- a/drivers/iommu/iommu-sva-lib.h > +++ b/drivers/iommu/iommu-sva-lib.h > @@ -8,8 +8,8 @@ > #include > #include > > -int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max); > -void iommu_sva_free_pasid(struct mm_struct *mm); > +int iommu_sva_alloc_pasid(ioasid_t min, ioasid_t max); > +void iommu_sva_free_pasid(void); > struct mm_struct *iommu_sva_find(ioasid_t pasid); > > #endif /* _IOMMU_SVA_LIB_H */ > diff --git a/drivers/iommu/iommu.c
[PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
The mm parameter in iommu_sva_bind_device() is intended for privileged process perform bind() on behalf of other processes. This use case has yet to be materialized, let alone potential security implications of adding kernel hooks without explicit user consent. In addition, with the agreement that IOASID allocation shall be subject cgroup limit. It will be inline with misc cgroup proposal if IOASID allocation as part of the SVA bind is limited to the current task. Link: https://lore.kernel.org/linux-iommu/20210303160205.151d114e@jacob-builder/ Link: https://lore.kernel.org/linux-iommu/YFhiMLR35WWMW%2FHu@myrica/ Signed-off-by: Jacob Pan --- drivers/dma/idxd/cdev.c | 2 +- drivers/dma/idxd/init.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 6 ++--- drivers/iommu/iommu-sva-lib.c | 30 +++-- drivers/iommu/iommu-sva-lib.h | 4 ++-- drivers/iommu/iommu.c | 16 - drivers/misc/uacce/uacce.c | 2 +- include/linux/iommu.h | 7 +++--- 8 files changed, 45 insertions(+), 24 deletions(-) diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c index 21ec82b..8c3347c 100644 --- a/drivers/dma/idxd/cdev.c +++ b/drivers/dma/idxd/cdev.c @@ -103,7 +103,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) filp->private_data = ctx; if (device_pasid_enabled(idxd)) { - sva = iommu_sva_bind_device(dev, current->mm, 0); + sva = iommu_sva_bind_device(dev, 0); if (IS_ERR(sva)) { rc = PTR_ERR(sva); dev_err(dev, "pasid allocation failed: %d\n", rc); diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index cdc85f1..a583f79 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -306,7 +306,7 @@ static int idxd_enable_system_pasid(struct idxd_device *idxd) flags = IOMMU_SVA_BIND_SUPERVISOR; - sva = iommu_sva_bind_device(>pdev->dev, NULL, flags); + sva = iommu_sva_bind_device(>pdev->dev, flags); if (IS_ERR(sva)) { dev_warn(>pdev->dev, "iommu sva bind failed: %ld\n", PTR_ERR(sva)); diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c index 23e287e..bdd5c79 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c @@ -329,7 +329,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) return ERR_PTR(-ENOMEM); /* Allocate a PASID for this mm if necessary */ - ret = iommu_sva_alloc_pasid(mm, 1, (1U << master->ssid_bits) - 1); + ret = iommu_sva_alloc_pasid(1, (1U << master->ssid_bits) - 1); if (ret) goto err_free_bond; @@ -347,7 +347,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) return >sva; err_free_pasid: - iommu_sva_free_pasid(mm); + iommu_sva_free_pasid(); err_free_bond: kfree(bond); return ERR_PTR(ret); @@ -377,7 +377,7 @@ void arm_smmu_sva_unbind(struct iommu_sva *handle) if (refcount_dec_and_test(>refs)) { list_del(>list); arm_smmu_mmu_notifier_put(bond->smmu_mn); - iommu_sva_free_pasid(bond->mm); + iommu_sva_free_pasid(); kfree(bond); } mutex_unlock(_lock); diff --git a/drivers/iommu/iommu-sva-lib.c b/drivers/iommu/iommu-sva-lib.c index bd41405..bd99f6b 100644 --- a/drivers/iommu/iommu-sva-lib.c +++ b/drivers/iommu/iommu-sva-lib.c @@ -12,27 +12,33 @@ static DECLARE_IOASID_SET(iommu_sva_pasid); /** * iommu_sva_alloc_pasid - Allocate a PASID for the mm - * @mm: the mm * @min: minimum PASID value (inclusive) * @max: maximum PASID value (inclusive) * - * Try to allocate a PASID for this mm, or take a reference to the existing one - * provided it fits within the [@min, @max] range. On success the PASID is - * available in mm->pasid, and must be released with iommu_sva_free_pasid(). + * Try to allocate a PASID for the current mm, or take a reference to the + * existing one provided it fits within the [@min, @max] range. On success + * the PASID is available in the current mm->pasid, and must be released with + * iommu_sva_free_pasid(). * @min must be greater than 0, because 0 indicates an unused mm->pasid. * * Returns 0 on success and < 0 on error. */ -int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) +int iommu_sva_alloc_pasid(ioasid_t min, ioasid_t max) { int ret = 0; ioasid_t pasid; + struct mm_struct *mm; if (min == INVALID_IOASID || max == INVALID_IOASID || min == 0 || max < min) return -EINVAL; mutex_lock(_sva_lock); + mm =