From 0b8973a81876d90f916507ac40d1381068dc986a Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Wed, 16 Dec 2009 22:59:29 +0000 Subject: intel-iommu: Fix section mismatch dmar_ir_support() uses dmar_tbl. dmar_tbl is declared as __initdata, but dmar_ir_support() is not declared as an __init function. Fix is simple since the only caller of dmar_ir_support (intr_remapping_supported) is an __init function. Signed-off-by: Tony Luck Signed-off-by: David Woodhouse --- drivers/pci/dmar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/dmar.c') diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 83aae47..ffe22bc 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -1456,7 +1456,7 @@ int dmar_reenable_qi(struct intel_iommu *iommu) /* * Check interrupt remapping support in DMAR table description. */ -int dmar_ir_support(void) +int __init dmar_ir_support(void) { struct acpi_table_dmar *dmar; dmar = (struct acpi_table_dmar *)dmar_tbl; -- cgit v1.1 From 5715f0f9d3814e83e5f2f754d3f7abdfa096a0b9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 8 Apr 2010 19:58:22 +0100 Subject: intel-iommu: Don't complain that ACPI_DMAR_SCOPE_TYPE_IOAPIC is not supported Signed-off-by: Yinghai Lu Signed-off-by: David Woodhouse --- drivers/pci/dmar.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/pci/dmar.c') diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index ffe22bc..a04bde9 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -130,9 +130,10 @@ static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) (*cnt)++; - else + else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) { printk(KERN_WARNING PREFIX - "Unsupported device scope\n"); + "Unsupported device scope\n"); + } start += scope->length; } if (*cnt == 0) -- cgit v1.1 From 680a7524622356f5476e8fad2fe32b2b68b432c0 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 8 Apr 2010 19:58:23 +0100 Subject: intel-iommu: Print out iommu seq_id more info on system with more than one IOMMU Signed-off-by: Yinghai Lu Signed-off-by: David Woodhouse --- drivers/pci/dmar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/pci/dmar.c') diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index a04bde9..d439917 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -806,7 +806,8 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) } ver = readl(iommu->reg + DMAR_VER_REG); - pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", + pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n", + iommu->seq_id, (unsigned long long)drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), (unsigned long long)iommu->cap, -- cgit v1.1 From dda565492776b7dff5f8507298d868745e734aab Mon Sep 17 00:00:00 2001 From: Yinghai Date: Fri, 9 Apr 2010 01:07:55 +0100 Subject: intel-iommu: use physfn to search drhd for VF When virtfn is used, we should use physfn to find correct drhd -v2: add pci_physfn() Suggested by Roland Dreier do can remove ifdef in dmar.c -v3: Chris pointed out we need that for dma_find_matched_atsr_unit too also change dmar_pci_device_match() static Signed-off-by: Yinghai Lu Acked-by: Roland Dreier Acked-by: Chris Wright Acked-by: Jesse Barnes Signed-off-by: David Woodhouse --- drivers/pci/dmar.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/pci/dmar.c') diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index d439917..edc5f00 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -309,6 +309,8 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) struct acpi_dmar_atsr *atsr; struct dmar_atsr_unit *atsru; + dev = pci_physfn(dev); + list_for_each_entry(atsru, &dmar_atsr_units, list) { atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); if (atsr->segment == pci_domain_nr(dev->bus)) @@ -507,7 +509,7 @@ parse_dmar_table(void) return ret; } -int dmar_pci_device_match(struct pci_dev *devices[], int cnt, +static int dmar_pci_device_match(struct pci_dev *devices[], int cnt, struct pci_dev *dev) { int index; @@ -530,6 +532,8 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) struct dmar_drhd_unit *dmaru = NULL; struct acpi_dmar_hardware_unit *drhd; + dev = pci_physfn(dev); + list_for_each_entry(dmaru, &dmar_drhd_units, list) { drhd = container_of(dmaru->hdr, struct acpi_dmar_hardware_unit, -- cgit v1.1 From 4f506e07e0a3dff34427cece255a8f390a78d5a0 Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 25 Mar 2010 18:02:58 +0000 Subject: intel-iommu: Fix boot inside 64bit virtualbox with io-apic disabled Commit 074835f0143b83845af5044af2739c52c9f53808 ("intel-iommu: Fix kernel hand if interrupt remapping disabled in BIOS") is adding a check for interrupt remapping disabled and is dereferencing the dmar_tbl pointer without checking its value. Unfortunately, this value is null when booting inside a 64bit virtual box guest with io-apic disabled, leading to a crash. With a check on it, the guest is now booting. It's triggering a WARN() in clockevent_delta2ns but it's better than not booting at all and allows the user to see there's something wrong on their io-apic setup. Signed-off-by: Arnaud Patard Signed-off-by: David Woodhouse --- drivers/pci/dmar.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/pci/dmar.c') diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index edc5f00..7771b2d 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -1466,5 +1466,7 @@ int __init dmar_ir_support(void) { struct acpi_table_dmar *dmar; dmar = (struct acpi_table_dmar *)dmar_tbl; + if (!dmar) + return 0; return dmar->flags & 0x1; } -- cgit v1.1 From 3a8663ee6171e1e61f5c139ed65aa0a769380f00 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 3 Apr 2010 19:37:23 +0100 Subject: intel-iommu: Combine the BIOS DMAR table warning messages We have nearly the same code for warnings repeated four times. Move it into a separate function. Signed-off-by: Ben Hutchings Signed-off-by: David Woodhouse --- drivers/pci/dmar.c | 48 ++++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) (limited to 'drivers/pci/dmar.c') diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 7771b2d..1959cda 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -618,7 +618,15 @@ int __init dmar_table_init(void) return 0; } -static int bios_warned; +static void warn_invalid_dmar(u64 addr, const char *message) +{ + WARN_ONCE(1, "Your BIOS is broken; DMAR reported at address %llx%s!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + addr, message, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); +} int __init check_zero_address(void) { @@ -644,13 +652,7 @@ int __init check_zero_address(void) drhd = (void *)entry_header; if (!drhd->address) { - /* Promote an attitude of violence to a BIOS engineer today */ - WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); - bios_warned = 1; + warn_invalid_dmar(0, ""); goto failed; } @@ -663,14 +665,8 @@ int __init check_zero_address(void) ecap = dmar_readq(addr + DMAR_ECAP_REG); early_iounmap(addr, VTD_PAGE_SIZE); if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) { - /* Promote an attitude of violence to a BIOS engineer today */ - WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - drhd->address, - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); - bios_warned = 1; + warn_invalid_dmar(drhd->address, + " returns all ones"); goto failed; } } @@ -735,14 +731,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) int msagaw = 0; if (!drhd->reg_base_addr) { - if (!bios_warned) { - WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); - bios_warned = 1; - } + warn_invalid_dmar(0, ""); return -EINVAL; } @@ -762,16 +751,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { - if (!bios_warned) { - /* Promote an attitude of violence to a BIOS engineer today */ - WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - drhd->reg_base_addr, - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); - bios_warned = 1; - } + warn_invalid_dmar(drhd->reg_base_addr, " returns all ones"); goto err_unmap; } -- cgit v1.1 From fd0c8894893cba722bdea12de25b49f980795d06 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 3 Apr 2010 19:38:43 +0100 Subject: intel-iommu: Set a more specific taint flag for invalid BIOS DMAR tables We now know how to deal with these tables so that they are harmless. Set TAINT_FIRMWARE_WORKAROUND instead of the default TAINT_WARN. Signed-off-by: Ben Hutchings Signed-off-by: David Woodhouse --- drivers/pci/dmar.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers/pci/dmar.c') diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 1959cda..f4c5170 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -360,12 +360,14 @@ dmar_parse_one_rhsa(struct acpi_dmar_header *header) return 0; } } - WARN(1, "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - drhd->reg_base_addr, - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); + WARN_TAINT( + 1, TAINT_FIRMWARE_WORKAROUND, + "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + drhd->reg_base_addr, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); return 0; } @@ -620,12 +622,14 @@ int __init dmar_table_init(void) static void warn_invalid_dmar(u64 addr, const char *message) { - WARN_ONCE(1, "Your BIOS is broken; DMAR reported at address %llx%s!\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - addr, message, - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); + WARN_TAINT_ONCE( + 1, TAINT_FIRMWARE_WORKAROUND, + "Your BIOS is broken; DMAR reported at address %llx%s!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + addr, message, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); } int __init check_zero_address(void) -- cgit v1.1