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
This commit is contained in:
commit
c39f3bc659
|
@ -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;
|
||||||
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)
|
||||||
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
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
|
|
|
@ -115,13 +115,14 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
|
||||||
* Extended Capability Register
|
* Extended Capability Register
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define ecap_pasid(e) ((e >> 40) & 0x1)
|
||||||
#define ecap_pss(e) ((e >> 35) & 0x1f)
|
#define ecap_pss(e) ((e >> 35) & 0x1f)
|
||||||
#define ecap_eafs(e) ((e >> 34) & 0x1)
|
#define ecap_eafs(e) ((e >> 34) & 0x1)
|
||||||
#define ecap_nwfs(e) ((e >> 33) & 0x1)
|
#define ecap_nwfs(e) ((e >> 33) & 0x1)
|
||||||
#define ecap_srs(e) ((e >> 31) & 0x1)
|
#define ecap_srs(e) ((e >> 31) & 0x1)
|
||||||
#define ecap_ers(e) ((e >> 30) & 0x1)
|
#define ecap_ers(e) ((e >> 30) & 0x1)
|
||||||
#define ecap_prs(e) ((e >> 29) & 0x1)
|
#define ecap_prs(e) ((e >> 29) & 0x1)
|
||||||
#define ecap_pasid(e) ((e >> 28) & 0x1)
|
/* PASID support used to be on bit 28 */
|
||||||
#define ecap_dis(e) ((e >> 27) & 0x1)
|
#define ecap_dis(e) ((e >> 27) & 0x1)
|
||||||
#define ecap_nest(e) ((e >> 26) & 0x1)
|
#define ecap_nest(e) ((e >> 26) & 0x1)
|
||||||
#define ecap_mts(e) ((e >> 25) & 0x1)
|
#define ecap_mts(e) ((e >> 25) & 0x1)
|
||||||
|
|
Loading…
Reference in New Issue