Skip to content

Commit 765b6a9

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Enumerate the scalable mode capability
The Intel vt-d spec rev3.0 introduces a new translation mode called scalable mode, which enables PASID-granular translations for first level, second level, nested and pass-through modes. At the same time, the previous Extended Context (ECS) mode is deprecated (no production ever implements ECS). This patch adds enumeration for Scalable Mode and removes the deprecated ECS enumeration. It provides a boot time option to disable scalable mode even hardware claims to support it. 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> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 3569dd0 commit 765b6a9

File tree

3 files changed

+24
-53
lines changed

3 files changed

+24
-53
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,12 +1682,12 @@
16821682
By default, super page will be supported if Intel IOMMU
16831683
has the capability. With this option, super page will
16841684
not be supported.
1685-
ecs_off [Default Off]
1686-
By default, extended context tables will be supported if
1687-
the hardware advertises that it has support both for the
1688-
extended tables themselves, and also PASID support. With
1689-
this option set, extended tables will not be used even
1690-
on hardware which claims to support them.
1685+
sm_off [Default Off]
1686+
By default, scalable mode will be supported if the
1687+
hardware advertises that it has support for the scalable
1688+
mode translation. With this option set, scalable mode
1689+
will not be used even on hardware which claims to support
1690+
it.
16911691
tboot_noforce [Default Off]
16921692
Do not force the Intel IOMMU enabled under tboot.
16931693
By default, tboot will force Intel IOMMU on, which

drivers/iommu/intel-iommu.c

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -405,38 +405,16 @@ static int dmar_map_gfx = 1;
405405
static int dmar_forcedac;
406406
static int intel_iommu_strict;
407407
static int intel_iommu_superpage = 1;
408-
static int intel_iommu_ecs = 1;
409-
static int intel_iommu_pasid28;
408+
static int intel_iommu_sm = 1;
410409
static int iommu_identity_mapping;
411410

412411
#define IDENTMAP_ALL 1
413412
#define IDENTMAP_GFX 2
414413
#define IDENTMAP_AZALIA 4
415414

416-
/* Broadwell and Skylake have broken ECS support — normal so-called "second
417-
* level" translation of DMA requests-without-PASID doesn't actually happen
418-
* unless you also set the NESTE bit in an extended context-entry. Which of
419-
* course means that SVM doesn't work because it's trying to do nested
420-
* translation of the physical addresses it finds in the process page tables,
421-
* through the IOVA->phys mapping found in the "second level" page tables.
422-
*
423-
* The VT-d specification was retroactively changed to change the definition
424-
* of the capability bits and pretend that Broadwell/Skylake never happened...
425-
* but unfortunately the wrong bit was changed. It's ECS which is broken, but
426-
* for some reason it was the PASID capability bit which was redefined (from
427-
* bit 28 on BDW/SKL to bit 40 in future).
428-
*
429-
* So our test for ECS needs to eschew those implementations which set the old
430-
* PASID capabiity bit 28, since those are the ones on which ECS is broken.
431-
* Unless we are working around the 'pasid28' limitations, that is, by putting
432-
* the device into passthrough mode for normal DMA and thus masking the bug.
433-
*/
434-
#define ecs_enabled(iommu) (intel_iommu_ecs && ecap_ecs(iommu->ecap) && \
435-
(intel_iommu_pasid28 || !ecap_broken_pasid(iommu->ecap)))
436-
/* PASID support is thus enabled if ECS is enabled and *either* of the old
437-
* or new capability bits are set. */
438-
#define pasid_enabled(iommu) (ecs_enabled(iommu) && \
439-
(ecap_pasid(iommu->ecap) || ecap_broken_pasid(iommu->ecap)))
415+
#define sm_supported(iommu) (intel_iommu_sm && ecap_smts((iommu)->ecap))
416+
#define pasid_supported(iommu) (sm_supported(iommu) && \
417+
ecap_pasid((iommu)->ecap))
440418

441419
int intel_iommu_gfx_mapped;
442420
EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
@@ -516,15 +494,9 @@ static int __init intel_iommu_setup(char *str)
516494
} else if (!strncmp(str, "sp_off", 6)) {
517495
pr_info("Disable supported super page\n");
518496
intel_iommu_superpage = 0;
519-
} else if (!strncmp(str, "ecs_off", 7)) {
520-
printk(KERN_INFO
521-
"Intel-IOMMU: disable extended context table support\n");
522-
intel_iommu_ecs = 0;
523-
} else if (!strncmp(str, "pasid28", 7)) {
524-
printk(KERN_INFO
525-
"Intel-IOMMU: enable pre-production PASID support\n");
526-
intel_iommu_pasid28 = 1;
527-
iommu_identity_mapping |= IDENTMAP_GFX;
497+
} else if (!strncmp(str, "sm_off", 6)) {
498+
pr_info("Intel-IOMMU: disable scalable mode support\n");
499+
intel_iommu_sm = 0;
528500
} else if (!strncmp(str, "tboot_noforce", 13)) {
529501
printk(KERN_INFO
530502
"Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
@@ -771,7 +743,7 @@ struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
771743
u64 *entry;
772744

773745
entry = &root->lo;
774-
if (ecs_enabled(iommu)) {
746+
if (sm_supported(iommu)) {
775747
if (devfn >= 0x80) {
776748
devfn -= 0x80;
777749
entry = &root->hi;
@@ -913,7 +885,7 @@ static void free_context_table(struct intel_iommu *iommu)
913885
if (context)
914886
free_pgtable_page(context);
915887

916-
if (!ecs_enabled(iommu))
888+
if (!sm_supported(iommu))
917889
continue;
918890

919891
context = iommu_context_addr(iommu, i, 0x80, 0);
@@ -1265,8 +1237,6 @@ static void iommu_set_root_entry(struct intel_iommu *iommu)
12651237
unsigned long flag;
12661238

12671239
addr = virt_to_phys(iommu->root_entry);
1268-
if (ecs_enabled(iommu))
1269-
addr |= DMA_RTADDR_RTT;
12701240

12711241
raw_spin_lock_irqsave(&iommu->register_lock, flag);
12721242
dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
@@ -1755,7 +1725,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
17551725
free_context_table(iommu);
17561726

17571727
#ifdef CONFIG_INTEL_IOMMU_SVM
1758-
if (pasid_enabled(iommu)) {
1728+
if (pasid_supported(iommu)) {
17591729
if (ecap_prs(iommu->ecap))
17601730
intel_svm_finish_prq(iommu);
17611731
intel_svm_exit(iommu);
@@ -2464,8 +2434,8 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
24642434
dmar_find_matched_atsr_unit(pdev))
24652435
info->ats_supported = 1;
24662436

2467-
if (ecs_enabled(iommu)) {
2468-
if (pasid_enabled(iommu)) {
2437+
if (sm_supported(iommu)) {
2438+
if (pasid_supported(iommu)) {
24692439
int features = pci_pasid_features(pdev);
24702440
if (features >= 0)
24712441
info->pasid_supported = features | 1;
@@ -3277,7 +3247,7 @@ static int __init init_dmars(void)
32773247
* We need to ensure the system pasid table is no bigger
32783248
* than the smallest supported.
32793249
*/
3280-
if (pasid_enabled(iommu)) {
3250+
if (pasid_supported(iommu)) {
32813251
u32 temp = 2 << ecap_pss(iommu->ecap);
32823252

32833253
intel_pasid_max_id = min_t(u32, temp,
@@ -3338,7 +3308,7 @@ static int __init init_dmars(void)
33383308
if (!ecap_pass_through(iommu->ecap))
33393309
hw_pass_through = 0;
33403310
#ifdef CONFIG_INTEL_IOMMU_SVM
3341-
if (pasid_enabled(iommu))
3311+
if (pasid_supported(iommu))
33423312
intel_svm_init(iommu);
33433313
#endif
33443314
}
@@ -3442,7 +3412,7 @@ static int __init init_dmars(void)
34423412
iommu_flush_write_buffer(iommu);
34433413

34443414
#ifdef CONFIG_INTEL_IOMMU_SVM
3445-
if (pasid_enabled(iommu) && ecap_prs(iommu->ecap)) {
3415+
if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
34463416
ret = intel_svm_enable_prq(iommu);
34473417
if (ret)
34483418
goto free_iommu;
@@ -4331,7 +4301,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
43314301
goto out;
43324302

43334303
#ifdef CONFIG_INTEL_IOMMU_SVM
4334-
if (pasid_enabled(iommu))
4304+
if (pasid_supported(iommu))
43354305
intel_svm_init(iommu);
43364306
#endif
43374307

@@ -4348,7 +4318,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
43484318
iommu_flush_write_buffer(iommu);
43494319

43504320
#ifdef CONFIG_INTEL_IOMMU_SVM
4351-
if (pasid_enabled(iommu) && ecap_prs(iommu->ecap)) {
4321+
if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
43524322
ret = intel_svm_enable_prq(iommu);
43534323
if (ret)
43544324
goto disable_iommu;

include/linux/intel-iommu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@
177177
* Extended Capability Register
178178
*/
179179

180+
#define ecap_smts(e) (((e) >> 43) & 0x1)
180181
#define ecap_dit(e) ((e >> 41) & 0x1)
181182
#define ecap_pasid(e) ((e >> 40) & 0x1)
182183
#define ecap_pss(e) ((e >> 35) & 0x1f)

0 commit comments

Comments
 (0)