]>
Commit | Line | Data |
---|---|---|
cfc78dfd JPB |
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 | ||
10 | static DEFINE_MUTEX(iommu_sva_lock); | |
11 | static 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 | |
701fac40 | 21 | * available in mm->pasid and will be available for the lifetime of the mm. |
cfc78dfd JPB |
22 | * |
23 | * Returns 0 on success and < 0 on error. | |
24 | */ | |
25 | int 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); | |
701fac40 FY |
35 | /* Is a PASID already associated with this mm? */ |
36 | if (pasid_valid(mm->pasid)) { | |
37 | if (mm->pasid < min || mm->pasid >= max) | |
cfc78dfd | 38 | ret = -EOVERFLOW; |
701fac40 | 39 | goto out; |
cfc78dfd | 40 | } |
701fac40 FY |
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); | |
47 | out: | |
cfc78dfd JPB |
48 | mutex_unlock(&iommu_sva_lock); |
49 | return ret; | |
50 | } | |
51 | EXPORT_SYMBOL_GPL(iommu_sva_alloc_pasid); | |
52 | ||
cfc78dfd JPB |
53 | /* ioasid_find getter() requires a void * argument */ |
54 | static 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 | */ | |
67 | struct mm_struct *iommu_sva_find(ioasid_t pasid) | |
68 | { | |
69 | return ioasid_find(&iommu_sva_pasid, pasid, __mmget_not_zero); | |
70 | } | |
71 | EXPORT_SYMBOL_GPL(iommu_sva_find); |