summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/intr_remapping.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-26 16:11:53 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-26 16:11:53 +0200
commit982653009b883ef1529089e3e6f1ae2fee41cbe2 (patch)
treeeec3b1fe947d442ee204a2d648133bc5223e5c59 /drivers/iommu/intr_remapping.c
parent37d96c28ecf0af1215bb6bbf580dbb1fabb5a6ec (diff)
parentc020570138f5d9cb1fc0a853f9cf9e641178b5c5 (diff)
downloadlinux-982653009b883ef1529089e3e6f1ae2fee41cbe2.tar.bz2
Merge branch 'core-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'core-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, ioapic: Consolidate the explicit EOI code x86, ioapic: Restore the mask bit correctly in eoi_ioapic_irq() x86, kdump, ioapic: Reset remote-IRR in clear_IO_APIC iommu: Rename the DMAR and INTR_REMAP config options x86, ioapic: Define irq_remap_modify_chip_defaults() x86, msi, intr-remap: Use the ioapic set affinity routine iommu: Cleanup ifdefs in detect_intel_iommu() iommu: No need to set dmar_disabled in check_zero_address() iommu: Move IOMMU specific code to intel-iommu.c intr_remap: Call dmar_dev_scope_init() explicitly x86, x2apic: Enable the bios request for x2apic optout
Diffstat (limited to 'drivers/iommu/intr_remapping.c')
-rw-r--r--drivers/iommu/intr_remapping.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c
index 1a89d4a2cadf..cfb0dd4bf0b6 100644
--- a/drivers/iommu/intr_remapping.c
+++ b/drivers/iommu/intr_remapping.c
@@ -21,6 +21,7 @@ int intr_remapping_enabled;
static int disable_intremap;
static int disable_sourceid_checking;
+static int no_x2apic_optout;
static __init int setup_nointremap(char *str)
{
@@ -34,12 +35,20 @@ static __init int setup_intremap(char *str)
if (!str)
return -EINVAL;
- if (!strncmp(str, "on", 2))
- disable_intremap = 0;
- else if (!strncmp(str, "off", 3))
- disable_intremap = 1;
- else if (!strncmp(str, "nosid", 5))
- disable_sourceid_checking = 1;
+ while (*str) {
+ if (!strncmp(str, "on", 2))
+ disable_intremap = 0;
+ else if (!strncmp(str, "off", 3))
+ disable_intremap = 1;
+ else if (!strncmp(str, "nosid", 5))
+ disable_sourceid_checking = 1;
+ else if (!strncmp(str, "no_x2apic_optout", 16))
+ no_x2apic_optout = 1;
+
+ str += strcspn(str, ",");
+ while (*str == ',')
+ str++;
+ }
return 0;
}
@@ -501,6 +510,15 @@ end:
spin_unlock_irqrestore(&iommu->register_lock, flags);
}
+static int __init dmar_x2apic_optout(void)
+{
+ struct acpi_table_dmar *dmar;
+ dmar = (struct acpi_table_dmar *)dmar_tbl;
+ if (!dmar || no_x2apic_optout)
+ return 0;
+ return dmar->flags & DMAR_X2APIC_OPT_OUT;
+}
+
int __init intr_remapping_supported(void)
{
struct dmar_drhd_unit *drhd;
@@ -521,16 +539,25 @@ int __init intr_remapping_supported(void)
return 1;
}
-int __init enable_intr_remapping(int eim)
+int __init enable_intr_remapping(void)
{
struct dmar_drhd_unit *drhd;
int setup = 0;
+ int eim = 0;
if (parse_ioapics_under_ir() != 1) {
printk(KERN_INFO "Not enable interrupt remapping\n");
return -1;
}
+ if (x2apic_supported()) {
+ eim = !dmar_x2apic_optout();
+ WARN(!eim, KERN_WARNING
+ "Your BIOS is broken and requested that x2apic be disabled\n"
+ "This will leave your machine vulnerable to irq-injection attacks\n"
+ "Use 'intremap=no_x2apic_optout' to override BIOS request\n");
+ }
+
for_each_drhd_unit(drhd) {
struct intel_iommu *iommu = drhd->iommu;
@@ -606,8 +633,9 @@ int __init enable_intr_remapping(int eim)
goto error;
intr_remapping_enabled = 1;
+ pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
- return 0;
+ return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
error:
/*
@@ -745,6 +773,15 @@ int __init parse_ioapics_under_ir(void)
return ir_supported;
}
+int ir_dev_scope_init(void)
+{
+ if (!intr_remapping_enabled)
+ return 0;
+
+ return dmar_dev_scope_init();
+}
+rootfs_initcall(ir_dev_scope_init);
+
void disable_intr_remapping(void)
{
struct dmar_drhd_unit *drhd;