diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86_64/mm/srat.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index d96c701dbed6..8b7f85608fa8 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/topology.h> | 17 | #include <linux/topology.h> |
18 | #include <asm/proto.h> | 18 | #include <asm/proto.h> |
19 | #include <asm/numa.h> | 19 | #include <asm/numa.h> |
20 | #include <asm/e820.h> | ||
20 | 21 | ||
21 | static struct acpi_table_slit *acpi_slit; | 22 | static struct acpi_table_slit *acpi_slit; |
22 | 23 | ||
@@ -196,12 +197,39 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | |||
196 | nd->start, nd->end); | 197 | nd->start, nd->end); |
197 | } | 198 | } |
198 | 199 | ||
200 | /* Sanity check to catch more bad SRATs (they are amazingly common). | ||
201 | Make sure the PXMs cover all memory. */ | ||
202 | static int nodes_cover_memory(void) | ||
203 | { | ||
204 | int i; | ||
205 | unsigned long pxmram, e820ram; | ||
206 | |||
207 | pxmram = 0; | ||
208 | for_each_node_mask(i, nodes_parsed) { | ||
209 | unsigned long s = nodes[i].start >> PAGE_SHIFT; | ||
210 | unsigned long e = nodes[i].end >> PAGE_SHIFT; | ||
211 | pxmram += e - s; | ||
212 | pxmram -= e820_hole_size(s, e); | ||
213 | } | ||
214 | |||
215 | e820ram = end_pfn - e820_hole_size(0, end_pfn); | ||
216 | if (pxmram < e820ram) { | ||
217 | printk(KERN_ERR | ||
218 | "SRAT: PXMs only cover %luMB of your %luMB e820 RAM. Not used.\n", | ||
219 | (pxmram << PAGE_SHIFT) >> 20, | ||
220 | (e820ram << PAGE_SHIFT) >> 20); | ||
221 | return 0; | ||
222 | } | ||
223 | return 1; | ||
224 | } | ||
225 | |||
199 | void __init acpi_numa_arch_fixup(void) {} | 226 | void __init acpi_numa_arch_fixup(void) {} |
200 | 227 | ||
201 | /* Use the information discovered above to actually set up the nodes. */ | 228 | /* Use the information discovered above to actually set up the nodes. */ |
202 | int __init acpi_scan_nodes(unsigned long start, unsigned long end) | 229 | int __init acpi_scan_nodes(unsigned long start, unsigned long end) |
203 | { | 230 | { |
204 | int i; | 231 | int i; |
232 | |||
205 | if (acpi_numa <= 0) | 233 | if (acpi_numa <= 0) |
206 | return -1; | 234 | return -1; |
207 | 235 | ||
@@ -212,6 +240,11 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
212 | node_clear(i, nodes_parsed); | 240 | node_clear(i, nodes_parsed); |
213 | } | 241 | } |
214 | 242 | ||
243 | if (!nodes_cover_memory()) { | ||
244 | bad_srat(); | ||
245 | return -1; | ||
246 | } | ||
247 | |||
215 | memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed)); | 248 | memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed)); |
216 | if (memnode_shift < 0) { | 249 | if (memnode_shift < 0) { |
217 | printk(KERN_ERR | 250 | printk(KERN_ERR |