diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2015-10-15 08:59:14 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2015-10-15 10:35:32 -0400 |
commit | 569e4f7782fb92d0e1b395b5fb01de642dd74dcf (patch) | |
tree | ef6aabacf8524f4adbcf7b0b9fbc0c2d3c2b282a | |
parent | 0204a49609824163092c32a8aeb073f7e9acc76d (diff) |
iommu/vt-d: Implement SVM_FLAG_PRIVATE_PASID to allocate unique PASIDs
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r-- | drivers/iommu/intel-svm.c | 6 | ||||
-rw-r--r-- | include/linux/intel-iommu.h | 1 | ||||
-rw-r--r-- | include/linux/intel-svm.h | 11 |
3 files changed, 16 insertions, 2 deletions
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 006e95dd64ae..89d4d47d0ab3 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c | |||
@@ -285,11 +285,12 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ | |||
285 | pasid_max = 1 << 20; | 285 | pasid_max = 1 << 20; |
286 | 286 | ||
287 | mutex_lock(&pasid_mutex); | 287 | mutex_lock(&pasid_mutex); |
288 | if (pasid) { | 288 | if (pasid && !(flags & SVM_FLAG_PRIVATE_PASID)) { |
289 | int i; | 289 | int i; |
290 | 290 | ||
291 | idr_for_each_entry(&iommu->pasid_idr, svm, i) { | 291 | idr_for_each_entry(&iommu->pasid_idr, svm, i) { |
292 | if (svm->mm != current->mm) | 292 | if (svm->mm != current->mm || |
293 | (svm->flags & SVM_FLAG_PRIVATE_PASID)) | ||
293 | continue; | 294 | continue; |
294 | 295 | ||
295 | if (svm->pasid >= pasid_max) { | 296 | if (svm->pasid >= pasid_max) { |
@@ -355,6 +356,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ | |||
355 | svm->pasid = ret; | 356 | svm->pasid = ret; |
356 | svm->notifier.ops = &intel_mmuops; | 357 | svm->notifier.ops = &intel_mmuops; |
357 | svm->mm = get_task_mm(current); | 358 | svm->mm = get_task_mm(current); |
359 | svm->flags = flags; | ||
358 | INIT_LIST_HEAD_RCU(&svm->devs); | 360 | INIT_LIST_HEAD_RCU(&svm->devs); |
359 | ret = -ENOMEM; | 361 | ret = -ENOMEM; |
360 | if (!svm->mm || (ret = mmu_notifier_register(&svm->notifier, svm->mm))) { | 362 | if (!svm->mm || (ret = mmu_notifier_register(&svm->notifier, svm->mm))) { |
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 57be14fce640..821273ca4873 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
@@ -489,6 +489,7 @@ struct intel_svm { | |||
489 | struct mmu_notifier notifier; | 489 | struct mmu_notifier notifier; |
490 | struct mm_struct *mm; | 490 | struct mm_struct *mm; |
491 | struct intel_iommu *iommu; | 491 | struct intel_iommu *iommu; |
492 | int flags; | ||
492 | int pasid; | 493 | int pasid; |
493 | struct list_head devs; | 494 | struct list_head devs; |
494 | }; | 495 | }; |
diff --git a/include/linux/intel-svm.h b/include/linux/intel-svm.h index 239f8a13a332..dd94ab45a4db 100644 --- a/include/linux/intel-svm.h +++ b/include/linux/intel-svm.h | |||
@@ -31,6 +31,17 @@ struct svm_dev_ops { | |||
31 | #define SVM_REQ_EXEC (1<<1) | 31 | #define SVM_REQ_EXEC (1<<1) |
32 | #define SVM_REQ_PRIV (1<<0) | 32 | #define SVM_REQ_PRIV (1<<0) |
33 | 33 | ||
34 | |||
35 | /* | ||
36 | * The SVM_FLAG_PRIVATE_PASID flag requests a PASID which is *not* the "main" | ||
37 | * PASID for the current process. Even if a PASID already exists, a new one | ||
38 | * will be allocated. And the PASID allocated with SVM_FLAG_PRIVATE_PASID | ||
39 | * will not be given to subsequent callers. This facility allows a driver to | ||
40 | * disambiguate between multiple device contexts which access the same MM, | ||
41 | * if there is no other way to do so. It should be used sparingly, if at all. | ||
42 | */ | ||
43 | #define SVM_FLAG_PRIVATE_PASID (1<<0) | ||
44 | |||
34 | /** | 45 | /** |
35 | * intel_svm_bind_mm() - Bind the current process to a PASID | 46 | * intel_svm_bind_mm() - Bind the current process to a PASID |
36 | * @dev: Device to be granted acccess | 47 | * @dev: Device to be granted acccess |