summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2015-10-15 08:59:14 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2015-10-15 10:35:32 -0400
commit569e4f7782fb92d0e1b395b5fb01de642dd74dcf (patch)
treeef6aabacf8524f4adbcf7b0b9fbc0c2d3c2b282a
parent0204a49609824163092c32a8aeb073f7e9acc76d (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.c6
-rw-r--r--include/linux/intel-iommu.h1
-rw-r--r--include/linux/intel-svm.h11
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