aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-12 14:28:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-12 14:28:57 -0400
commitc39f3bc659b6f32e0e88113ec359a504be259e4f (patch)
tree2eb1ddf4f039dda7fed72f57162df3561e78214a
parentdf5f4158415b6fc4a2d683c6fdc806be6da176bc (diff)
parentc83b2f20fdde578bded3dfc4405c5db7a039c694 (diff)
Merge git://git.infradead.org/intel-iommu
Pull VT-d hardware workarounds from David Woodhouse: "This contains a workaround for hardware issues which I *thought* were never going to be seen on production hardware. I'm glad I checked that before the 4.1 release... Firstly, PASID support is so broken on existing chips that we're just going to declare the old capability bit 28 as 'reserved' and change the VT-d spec to move PASID support to another bit. So any existing hardware doesn't support SVM; it only sets that (now) meaningless bit 28. That patch *wasn't* imperative for 4.1 because we don't have PASID support yet. But *even* the extended context tables are broken — if you just enable the wider tables and use none of the new bits in them, which is precisely what 4.1 does, you find that translations don't work. It's this problem which I thought was caught in time to be fixed before production, but wasn't. To avoid triggering this issue, we now *only* enable the extended context tables on hardware which also advertises "we have PASID support and we actually tested it this time" with the new PASID feature bit. In addition, I've added an 'intel_iommu=ecs_off' command line parameter to allow us to disable it manually if we need to" * git://git.infradead.org/intel-iommu: iommu/vt-d: Only enable extended context tables if PASID is supported iommu/vt-d: Change PASID support to bit 40 of Extended Capability Register
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--drivers/iommu/intel-iommu.c18
-rw-r--r--include/linux/intel-iommu.h3
3 files changed, 23 insertions, 4 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 61ab1628a057..6726139bd289 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1481,6 +1481,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
1481 By default, super page will be supported if Intel IOMMU 1481 By default, super page will be supported if Intel IOMMU
1482 has the capability. With this option, super page will 1482 has the capability. With this option, super page will
1483 not be supported. 1483 not be supported.
1484 ecs_off [Default Off]
1485 By default, extended context tables will be supported if
1486 the hardware advertises that it has support both for the
1487 extended tables themselves, and also PASID support. With
1488 this option set, extended tables will not be used even
1489 on hardware which claims to support them.
1484 1490
1485 intel_idle.max_cstate= [KNL,HW,ACPI,X86] 1491 intel_idle.max_cstate= [KNL,HW,ACPI,X86]
1486 0 disables intel_idle and fall back on acpi_idle. 1492 0 disables intel_idle and fall back on acpi_idle.
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 2ffe58969944..5ecfaf29933a 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -422,6 +422,14 @@ static int dmar_map_gfx = 1;
422static int dmar_forcedac; 422static int dmar_forcedac;
423static int intel_iommu_strict; 423static int intel_iommu_strict;
424static int intel_iommu_superpage = 1; 424static int intel_iommu_superpage = 1;
425static int intel_iommu_ecs = 1;
426
427/* We only actually use ECS when PASID support (on the new bit 40)
428 * is also advertised. Some early implementations — the ones with
429 * PASID support on bit 28 — have issues even when we *only* use
430 * extended root/context tables. */
431#define ecs_enabled(iommu) (intel_iommu_ecs && ecap_ecs(iommu->ecap) && \
432 ecap_pasid(iommu->ecap))
425 433
426int intel_iommu_gfx_mapped; 434int intel_iommu_gfx_mapped;
427EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); 435EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
@@ -465,6 +473,10 @@ static int __init intel_iommu_setup(char *str)
465 printk(KERN_INFO 473 printk(KERN_INFO
466 "Intel-IOMMU: disable supported super page\n"); 474 "Intel-IOMMU: disable supported super page\n");
467 intel_iommu_superpage = 0; 475 intel_iommu_superpage = 0;
476 } else if (!strncmp(str, "ecs_off", 7)) {
477 printk(KERN_INFO
478 "Intel-IOMMU: disable extended context table support\n");
479 intel_iommu_ecs = 0;
468 } 480 }
469 481
470 str += strcspn(str, ","); 482 str += strcspn(str, ",");
@@ -669,7 +681,7 @@ static inline struct context_entry *iommu_context_addr(struct intel_iommu *iommu
669 struct context_entry *context; 681 struct context_entry *context;
670 u64 *entry; 682 u64 *entry;
671 683
672 if (ecap_ecs(iommu->ecap)) { 684 if (ecs_enabled(iommu)) {
673 if (devfn >= 0x80) { 685 if (devfn >= 0x80) {
674 devfn -= 0x80; 686 devfn -= 0x80;
675 entry = &root->hi; 687 entry = &root->hi;
@@ -806,7 +818,7 @@ static void free_context_table(struct intel_iommu *iommu)
806 if (context) 818 if (context)
807 free_pgtable_page(context); 819 free_pgtable_page(context);
808 820
809 if (!ecap_ecs(iommu->ecap)) 821 if (!ecs_enabled(iommu))
810 continue; 822 continue;
811 823
812 context = iommu_context_addr(iommu, i, 0x80, 0); 824 context = iommu_context_addr(iommu, i, 0x80, 0);
@@ -1141,7 +1153,7 @@ static void iommu_set_root_entry(struct intel_iommu *iommu)
1141 unsigned long flag; 1153 unsigned long flag;
1142 1154
1143 addr = virt_to_phys(iommu->root_entry); 1155 addr = virt_to_phys(iommu->root_entry);
1144 if (ecap_ecs(iommu->ecap)) 1156 if (ecs_enabled(iommu))
1145 addr |= DMA_RTADDR_RTT; 1157 addr |= DMA_RTADDR_RTT;
1146 1158
1147 raw_spin_lock_irqsave(&iommu->register_lock, flag); 1159 raw_spin_lock_irqsave(&iommu->register_lock, flag);
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 796ef9645827..a240e61a7700 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -115,13 +115,14 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
115 * Extended Capability Register 115 * Extended Capability Register
116 */ 116 */
117 117
118#define ecap_pasid(e) ((e >> 40) & 0x1)
118#define ecap_pss(e) ((e >> 35) & 0x1f) 119#define ecap_pss(e) ((e >> 35) & 0x1f)
119#define ecap_eafs(e) ((e >> 34) & 0x1) 120#define ecap_eafs(e) ((e >> 34) & 0x1)
120#define ecap_nwfs(e) ((e >> 33) & 0x1) 121#define ecap_nwfs(e) ((e >> 33) & 0x1)
121#define ecap_srs(e) ((e >> 31) & 0x1) 122#define ecap_srs(e) ((e >> 31) & 0x1)
122#define ecap_ers(e) ((e >> 30) & 0x1) 123#define ecap_ers(e) ((e >> 30) & 0x1)
123#define ecap_prs(e) ((e >> 29) & 0x1) 124#define ecap_prs(e) ((e >> 29) & 0x1)
124#define ecap_pasid(e) ((e >> 28) & 0x1) 125/* PASID support used to be on bit 28 */
125#define ecap_dis(e) ((e >> 27) & 0x1) 126#define ecap_dis(e) ((e >> 27) & 0x1)
126#define ecap_nest(e) ((e >> 26) & 0x1) 127#define ecap_nest(e) ((e >> 26) & 0x1)
127#define ecap_mts(e) ((e >> 25) & 0x1) 128#define ecap_mts(e) ((e >> 25) & 0x1)