diff options
author | Arjan van de Ven <arjan@linux.intel.com> | 2006-04-07 13:49:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-09 14:53:51 -0400 |
commit | 946f2ee5c7312e8acac4f3ab6629e7e2d36a3646 (patch) | |
tree | 0821a2f3f59a089b73d33f64f59331460e20355a | |
parent | 952223683ec989e86328c24808fdb962c4dbeb0a (diff) |
[PATCH] i386/x86-64: Check that MCFG points to an e820 reserved area
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>
-rw-r--r-- | arch/i386/pci/mmconfig.c | 11 | ||||
-rw-r--r-- | arch/x86_64/pci/mmconfig.c | 10 |
2 files changed, 21 insertions, 0 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 613789071f30..ee815c7d3e4c 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
@@ -12,8 +12,11 @@ | |||
12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
15 | #include <asm/e820.h> | ||
15 | #include "pci.h" | 16 | #include "pci.h" |
16 | 17 | ||
18 | #define MMCONFIG_APER_SIZE (256*1024*1024) | ||
19 | |||
17 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) | 20 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) |
18 | 21 | ||
19 | /* The base address of the last MMCONFIG device accessed */ | 22 | /* The base address of the last MMCONFIG device accessed */ |
@@ -183,6 +186,14 @@ void __init pci_mmcfg_init(void) | |||
183 | (pci_mmcfg_config[0].base_address == 0)) | 186 | (pci_mmcfg_config[0].base_address == 0)) |
184 | return; | 187 | return; |
185 | 188 | ||
189 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, | ||
190 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, | ||
191 | E820_RESERVED)) { | ||
192 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); | ||
193 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
194 | return; | ||
195 | } | ||
196 | |||
186 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); | 197 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); |
187 | raw_pci_ops = &pci_mmcfg; | 198 | raw_pci_ops = &pci_mmcfg; |
188 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 199 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; |
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index e616500207e4..dfe84c322552 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
@@ -9,6 +9,8 @@ | |||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/acpi.h> | 10 | #include <linux/acpi.h> |
11 | #include <linux/bitmap.h> | 11 | #include <linux/bitmap.h> |
12 | #include <asm/e820.h> | ||
13 | |||
12 | #include "pci.h" | 14 | #include "pci.h" |
13 | 15 | ||
14 | #define MMCONFIG_APER_SIZE (256*1024*1024) | 16 | #define MMCONFIG_APER_SIZE (256*1024*1024) |
@@ -161,6 +163,14 @@ void __init pci_mmcfg_init(void) | |||
161 | (pci_mmcfg_config[0].base_address == 0)) | 163 | (pci_mmcfg_config[0].base_address == 0)) |
162 | return; | 164 | return; |
163 | 165 | ||
166 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, | ||
167 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, | ||
168 | E820_RESERVED)) { | ||
169 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); | ||
170 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
171 | return; | ||
172 | } | ||
173 | |||
164 | /* RED-PEN i386 doesn't do _nocache right now */ | 174 | /* RED-PEN i386 doesn't do _nocache right now */ |
165 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); | 175 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); |
166 | if (pci_mmcfg_virt == NULL) { | 176 | if (pci_mmcfg_virt == NULL) { |