Skip to content

Commit 1c4f88b

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Shared virtual address in scalable mode
This patch enables the current SVA (Shared Virtual Address) implementation to work in the scalable mode. Cc: Ashok Raj <ashok.raj@intel.com> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com> Cc: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Sanjay Kumar <sanjay.k.kumar@intel.com> Signed-off-by: Liu Yi L <yi.l.liu@intel.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Ashok Raj <ashok.raj@intel.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 437f35e commit 1c4f88b

File tree

5 files changed

+20
-88
lines changed

5 files changed

+20
-88
lines changed

drivers/iommu/intel-iommu.c

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5257,18 +5257,6 @@ static void intel_iommu_put_resv_regions(struct device *dev,
52575257
}
52585258

52595259
#ifdef CONFIG_INTEL_IOMMU_SVM
5260-
static inline unsigned long intel_iommu_get_pts(struct device *dev)
5261-
{
5262-
int pts, max_pasid;
5263-
5264-
max_pasid = intel_pasid_get_dev_max_id(dev);
5265-
pts = find_first_bit((unsigned long *)&max_pasid, MAX_NR_PASID_BITS);
5266-
if (pts < 5)
5267-
return 0;
5268-
5269-
return pts - 5;
5270-
}
5271-
52725260
int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
52735261
{
52745262
struct device_domain_info *info;
@@ -5300,33 +5288,7 @@ int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sd
53005288
sdev->sid = PCI_DEVID(info->bus, info->devfn);
53015289

53025290
if (!(ctx_lo & CONTEXT_PASIDE)) {
5303-
if (iommu->pasid_state_table)
5304-
context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table);
5305-
context[1].lo = (u64)virt_to_phys(info->pasid_table->table) |
5306-
intel_iommu_get_pts(sdev->dev);
5307-
5308-
wmb();
5309-
/* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both
5310-
* extended to permit requests-with-PASID if the PASIDE bit
5311-
* is set. which makes sense. For CONTEXT_TT_PASS_THROUGH,
5312-
* however, the PASIDE bit is ignored and requests-with-PASID
5313-
* are unconditionally blocked. Which makes less sense.
5314-
* So convert from CONTEXT_TT_PASS_THROUGH to one of the new
5315-
* "guest mode" translation types depending on whether ATS
5316-
* is available or not. Annoyingly, we can't use the new
5317-
* modes *unless* PASIDE is set. */
5318-
if ((ctx_lo & CONTEXT_TT_MASK) == (CONTEXT_TT_PASS_THROUGH << 2)) {
5319-
ctx_lo &= ~CONTEXT_TT_MASK;
5320-
if (info->ats_supported)
5321-
ctx_lo |= CONTEXT_TT_PT_PASID_DEV_IOTLB << 2;
5322-
else
5323-
ctx_lo |= CONTEXT_TT_PT_PASID << 2;
5324-
}
53255291
ctx_lo |= CONTEXT_PASIDE;
5326-
if (iommu->pasid_state_table)
5327-
ctx_lo |= CONTEXT_DINVE;
5328-
if (info->pri_supported)
5329-
ctx_lo |= CONTEXT_PRS;
53305292
context[0].lo = ctx_lo;
53315293
wmb();
53325294
iommu->flush.flush_context(iommu, sdev->did, sdev->sid,

drivers/iommu/intel-pasid.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ static inline void pasid_clear_entry(struct pasid_entry *pe)
286286
WRITE_ONCE(pe->val[7], 0);
287287
}
288288

289-
void intel_pasid_clear_entry(struct device *dev, int pasid)
289+
static void intel_pasid_clear_entry(struct device *dev, int pasid)
290290
{
291291
struct pasid_entry *pe;
292292

drivers/iommu/intel-pasid.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ void intel_pasid_free_table(struct device *dev);
5858
struct pasid_table *intel_pasid_get_table(struct device *dev);
5959
int intel_pasid_get_dev_max_id(struct device *dev);
6060
struct pasid_entry *intel_pasid_get_entry(struct device *dev, int pasid);
61-
void intel_pasid_clear_entry(struct device *dev, int pasid);
6261
int intel_pasid_setup_first_level(struct intel_iommu *iommu,
6362
struct device *dev, pgd_t *pgd,
6463
int pasid, u16 did, int flags);

drivers/iommu/intel-svm.c

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@
2929

3030
#include "intel-pasid.h"
3131

32-
#define PASID_ENTRY_P BIT_ULL(0)
33-
#define PASID_ENTRY_FLPM_5LP BIT_ULL(9)
34-
#define PASID_ENTRY_SRE BIT_ULL(11)
35-
3632
static irqreturn_t prq_event_thread(int irq, void *d);
3733

3834
struct pasid_state_entry {
@@ -248,20 +244,6 @@ static void intel_invalidate_range(struct mmu_notifier *mn,
248244
(end - start + PAGE_SIZE - 1) >> VTD_PAGE_SHIFT, 0, 0);
249245
}
250246

251-
252-
static void intel_flush_pasid_dev(struct intel_svm *svm, struct intel_svm_dev *sdev, int pasid)
253-
{
254-
struct qi_desc desc;
255-
256-
desc.qw0 = QI_PC_TYPE | QI_PC_DID(sdev->did) |
257-
QI_PC_PASID_SEL | QI_PC_PASID(pasid);
258-
desc.qw1 = 0;
259-
desc.qw2 = 0;
260-
desc.qw3 = 0;
261-
262-
qi_submit_sync(&desc, svm->iommu);
263-
}
264-
265247
static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
266248
{
267249
struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
@@ -281,8 +263,7 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
281263
*/
282264
rcu_read_lock();
283265
list_for_each_entry_rcu(sdev, &svm->devs, list) {
284-
intel_pasid_clear_entry(sdev->dev, svm->pasid);
285-
intel_flush_pasid_dev(svm, sdev, svm->pasid);
266+
intel_pasid_tear_down_entry(svm->iommu, sdev->dev, svm->pasid);
286267
intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
287268
}
288269
rcu_read_unlock();
@@ -301,11 +282,9 @@ static LIST_HEAD(global_svm_list);
301282
int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ops *ops)
302283
{
303284
struct intel_iommu *iommu = intel_svm_device_to_iommu(dev);
304-
struct pasid_entry *entry;
305285
struct intel_svm_dev *sdev;
306286
struct intel_svm *svm = NULL;
307287
struct mm_struct *mm = NULL;
308-
u64 pasid_entry_val;
309288
int pasid_max;
310289
int ret;
311290

@@ -414,22 +393,22 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
414393
kfree(sdev);
415394
goto out;
416395
}
417-
pasid_entry_val = (u64)__pa(mm->pgd) | PASID_ENTRY_P;
418-
} else
419-
pasid_entry_val = (u64)__pa(init_mm.pgd) |
420-
PASID_ENTRY_P | PASID_ENTRY_SRE;
421-
if (cpu_feature_enabled(X86_FEATURE_LA57))
422-
pasid_entry_val |= PASID_ENTRY_FLPM_5LP;
423-
424-
entry = intel_pasid_get_entry(dev, svm->pasid);
425-
WRITE_ONCE(entry->val[0], pasid_entry_val);
426-
427-
/*
428-
* Flush PASID cache when a PASID table entry becomes
429-
* present.
430-
*/
431-
if (cap_caching_mode(iommu->cap))
432-
intel_flush_pasid_dev(svm, sdev, svm->pasid);
396+
}
397+
398+
spin_lock(&iommu->lock);
399+
ret = intel_pasid_setup_first_level(iommu, dev,
400+
mm ? mm->pgd : init_mm.pgd,
401+
svm->pasid, FLPT_DEFAULT_DID,
402+
mm ? 0 : PASID_FLAG_SUPERVISOR_MODE);
403+
spin_unlock(&iommu->lock);
404+
if (ret) {
405+
if (mm)
406+
mmu_notifier_unregister(&svm->notifier, mm);
407+
intel_pasid_free_id(svm->pasid);
408+
kfree(svm);
409+
kfree(sdev);
410+
goto out;
411+
}
433412

434413
list_add_tail(&svm->list, &global_svm_list);
435414
}
@@ -475,10 +454,9 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
475454
* to use. We have a *shared* PASID table, because it's
476455
* large and has to be physically contiguous. So it's
477456
* hard to be as defensive as we might like. */
478-
intel_flush_pasid_dev(svm, sdev, svm->pasid);
457+
intel_pasid_tear_down_entry(iommu, dev, svm->pasid);
479458
intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
480459
kfree_rcu(sdev, rcu);
481-
intel_pasid_clear_entry(dev, svm->pasid);
482460

483461
if (list_empty(&svm->devs)) {
484462
intel_pasid_free_id(svm->pasid);

include/linux/intel-iommu.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,7 @@
5454
#define CONTEXT_TT_MULTI_LEVEL 0
5555
#define CONTEXT_TT_DEV_IOTLB 1
5656
#define CONTEXT_TT_PASS_THROUGH 2
57-
/* Extended context entry types */
58-
#define CONTEXT_TT_PT_PASID 4
59-
#define CONTEXT_TT_PT_PASID_DEV_IOTLB 5
60-
#define CONTEXT_TT_MASK (7ULL << 2)
61-
62-
#define CONTEXT_DINVE (1ULL << 8)
63-
#define CONTEXT_PRS (1ULL << 9)
64-
#define CONTEXT_PASIDE (1ULL << 11)
57+
#define CONTEXT_PASIDE BIT_ULL(3)
6558

6659
/*
6760
* Intel IOMMU register specification per version 1.0 public spec.

0 commit comments

Comments
 (0)