iommu-sva-lib.c (1883B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Helpers for IOMMU drivers implementing SVA 4 */ 5#include <linux/mutex.h> 6#include <linux/sched/mm.h> 7 8#include "iommu-sva-lib.h" 9 10static DEFINE_MUTEX(iommu_sva_lock); 11static DECLARE_IOASID_SET(iommu_sva_pasid); 12 13/** 14 * iommu_sva_alloc_pasid - Allocate a PASID for the mm 15 * @mm: the mm 16 * @min: minimum PASID value (inclusive) 17 * @max: maximum PASID value (inclusive) 18 * 19 * Try to allocate a PASID for this mm, or take a reference to the existing one 20 * provided it fits within the [@min, @max] range. On success the PASID is 21 * available in mm->pasid and will be available for the lifetime of the mm. 22 * 23 * Returns 0 on success and < 0 on error. 24 */ 25int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) 26{ 27 int ret = 0; 28 ioasid_t pasid; 29 30 if (min == INVALID_IOASID || max == INVALID_IOASID || 31 min == 0 || max < min) 32 return -EINVAL; 33 34 mutex_lock(&iommu_sva_lock); 35 /* Is a PASID already associated with this mm? */ 36 if (pasid_valid(mm->pasid)) { 37 if (mm->pasid < min || mm->pasid >= max) 38 ret = -EOVERFLOW; 39 goto out; 40 } 41 42 pasid = ioasid_alloc(&iommu_sva_pasid, min, max, mm); 43 if (!pasid_valid(pasid)) 44 ret = -ENOMEM; 45 else 46 mm_pasid_set(mm, pasid); 47out: 48 mutex_unlock(&iommu_sva_lock); 49 return ret; 50} 51EXPORT_SYMBOL_GPL(iommu_sva_alloc_pasid); 52 53/* ioasid_find getter() requires a void * argument */ 54static bool __mmget_not_zero(void *mm) 55{ 56 return mmget_not_zero(mm); 57} 58 59/** 60 * iommu_sva_find() - Find mm associated to the given PASID 61 * @pasid: Process Address Space ID assigned to the mm 62 * 63 * On success a reference to the mm is taken, and must be released with mmput(). 64 * 65 * Returns the mm corresponding to this PASID, or an error if not found. 66 */ 67struct mm_struct *iommu_sva_find(ioasid_t pasid) 68{ 69 return ioasid_find(&iommu_sva_pasid, pasid, __mmget_not_zero); 70} 71EXPORT_SYMBOL_GPL(iommu_sva_find);