[PATCH] i386/x86-64: Check that MCFG points to an e820 reserved area
authorArjan van de Ven <arjan@linux.intel.com>
Fri, 7 Apr 2006 17:49:30 +0000 (19:49 +0200)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 9 Apr 2006 18:53:51 +0000 (11:53 -0700)
This patch introduces a user for the e820_all_mapped function:

There have been several machines that don't have a working MMCONFIG,
often because of a buggy MCFG table in the ACPI bios.  This patch adds a
simple sanity check that detects a whole bunch of these cases, and when
it detects it, linux now boots rather than crash-and-burns.

The accuracy of this detection can in principle be improved if there was
a "is this entire range in e820 with THIS attribute", but no such
function exist and the complexity needed for this is not really worth
it; this simple check already catches most cases anyway.

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/pci/mmconfig.c
arch/x86_64/pci/mmconfig.c

index 613789071f30dde13eec78efed2412ae3c399d90..ee815c7d3e4cc4d893314b68d225970c5f4179a8 100644 (file)
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <asm/e820.h>
 #include "pci.h"
 
+#define MMCONFIG_APER_SIZE (256*1024*1024)
+
 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
 
 /* The base address of the last MMCONFIG device accessed */
@@ -183,6 +186,14 @@ void __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                return;
 
+       if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+                       pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+                       E820_RESERVED)) {
+               printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+               printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+               return;
+       }
+
        printk(KERN_INFO "PCI: Using MMCONFIG\n");
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
index e616500207e4bd77402ada45286745b70833ba26..dfe84c322552bc015d54f04a18202131eac27971 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/bitmap.h>
+#include <asm/e820.h>
+
 #include "pci.h"
 
 #define MMCONFIG_APER_SIZE (256*1024*1024)
@@ -161,6 +163,14 @@ void __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                return;
 
+       if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+                       pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+                       E820_RESERVED)) {
+               printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+               printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+               return;
+       }
+
        /* RED-PEN i386 doesn't do _nocache right now */
        pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
        if (pci_mmcfg_virt == NULL) {