Commit c83b2f20 authored by David Woodhouse's avatar David Woodhouse

iommu/vt-d: Only enable extended context tables if PASID is supported

Although the extended tables are theoretically a completely orthogonal
feature to PASID and anything else that *uses* the newly-available bits,
some of the early hardware has problems even when all we do is enable
them and use only the same bits that were in the old context tables.

For now, there's no motivation to support extended tables unless we're
going to use PASID support to do SVM. So just don't use them unless
PASID support is advertised too. Also add a command-line bailout just in
case later chips also have issues.

The equivalent problem for PASID support has already been fixed with the
upcoming VT-d spec update and commit bd00c606 ("iommu/vt-d: Change
PASID support to bit 40 of Extended Capability Register"), because the
problematic platforms use the old definition of the PASID-capable bit,
which is now marked as reserved and meaningless.

So with this change, we'll magically start using ECS again only when we
see the new hardware advertising "hey, we have PASID support and we
actually tested it this time" on bit 40.

The VT-d hardware architect has promised that we are not going to have
any reason to support ECS *without* PASID any time soon, and he'll make
sure he checks with us before changing that.

In the future, if hypothetical new features also use new bits in the
context tables and can be seen on implementations *without* PASID support,
we might need to add their feature bits to the ecs_enabled() macro.
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent bd00c606
...@@ -1481,6 +1481,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -1481,6 +1481,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
By default, super page will be supported if Intel IOMMU By default, super page will be supported if Intel IOMMU
has the capability. With this option, super page will has the capability. With this option, super page will
not be supported. not be supported.
ecs_off [Default Off]
By default, extended context tables will be supported if
the hardware advertises that it has support both for the
extended tables themselves, and also PASID support. With
this option set, extended tables will not be used even
on hardware which claims to support them.
intel_idle.max_cstate= [KNL,HW,ACPI,X86] intel_idle.max_cstate= [KNL,HW,ACPI,X86]
0 disables intel_idle and fall back on acpi_idle. 0 disables intel_idle and fall back on acpi_idle.
......
...@@ -422,6 +422,14 @@ static int dmar_map_gfx = 1; ...@@ -422,6 +422,14 @@ static int dmar_map_gfx = 1;
static int dmar_forcedac; static int dmar_forcedac;
static int intel_iommu_strict; static int intel_iommu_strict;
static int intel_iommu_superpage = 1; static int intel_iommu_superpage = 1;
static int intel_iommu_ecs = 1;
/* We only actually use ECS when PASID support (on the new bit 40)
* is also advertised. Some early implementations — the ones with
* PASID support on bit 28 — have issues even when we *only* use
* extended root/context tables. */
#define ecs_enabled(iommu) (intel_iommu_ecs && ecap_ecs(iommu->ecap) && \
ecap_pasid(iommu->ecap))
int intel_iommu_gfx_mapped; int intel_iommu_gfx_mapped;
EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
...@@ -465,6 +473,10 @@ static int __init intel_iommu_setup(char *str) ...@@ -465,6 +473,10 @@ static int __init intel_iommu_setup(char *str)
printk(KERN_INFO printk(KERN_INFO
"Intel-IOMMU: disable supported super page\n"); "Intel-IOMMU: disable supported super page\n");
intel_iommu_superpage = 0; intel_iommu_superpage = 0;
} else if (!strncmp(str, "ecs_off", 7)) {
printk(KERN_INFO
"Intel-IOMMU: disable extended context table support\n");
intel_iommu_ecs = 0;
} }
str += strcspn(str, ","); str += strcspn(str, ",");
...@@ -669,7 +681,7 @@ static inline struct context_entry *iommu_context_addr(struct intel_iommu *iommu ...@@ -669,7 +681,7 @@ static inline struct context_entry *iommu_context_addr(struct intel_iommu *iommu
struct context_entry *context; struct context_entry *context;
u64 *entry; u64 *entry;
if (ecap_ecs(iommu->ecap)) { if (ecs_enabled(iommu)) {
if (devfn >= 0x80) { if (devfn >= 0x80) {
devfn -= 0x80; devfn -= 0x80;
entry = &root->hi; entry = &root->hi;
...@@ -806,7 +818,7 @@ static void free_context_table(struct intel_iommu *iommu) ...@@ -806,7 +818,7 @@ static void free_context_table(struct intel_iommu *iommu)
if (context) if (context)
free_pgtable_page(context); free_pgtable_page(context);
if (!ecap_ecs(iommu->ecap)) if (!ecs_enabled(iommu))
continue; continue;
context = iommu_context_addr(iommu, i, 0x80, 0); context = iommu_context_addr(iommu, i, 0x80, 0);
...@@ -1141,7 +1153,7 @@ static void iommu_set_root_entry(struct intel_iommu *iommu) ...@@ -1141,7 +1153,7 @@ static void iommu_set_root_entry(struct intel_iommu *iommu)
unsigned long flag; unsigned long flag;
addr = virt_to_phys(iommu->root_entry); addr = virt_to_phys(iommu->root_entry);
if (ecap_ecs(iommu->ecap)) if (ecs_enabled(iommu))
addr |= DMA_RTADDR_RTT; addr |= DMA_RTADDR_RTT;
raw_spin_lock_irqsave(&iommu->register_lock, flag); raw_spin_lock_irqsave(&iommu->register_lock, flag);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment