diff options
Diffstat (limited to 'arch/x86/mm/discontig_32.c')
-rw-r--r-- | arch/x86/mm/discontig_32.c | 110 |
1 files changed, 91 insertions, 19 deletions
diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c index 13a474d3c6e9..04b1d20e2613 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/discontig_32.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/kexec.h> | 32 | #include <linux/kexec.h> |
33 | #include <linux/pfn.h> | 33 | #include <linux/pfn.h> |
34 | #include <linux/swap.h> | 34 | #include <linux/swap.h> |
35 | #include <linux/acpi.h> | ||
35 | 36 | ||
36 | #include <asm/e820.h> | 37 | #include <asm/e820.h> |
37 | #include <asm/setup.h> | 38 | #include <asm/setup.h> |
@@ -103,14 +104,10 @@ extern unsigned long highend_pfn, highstart_pfn; | |||
103 | 104 | ||
104 | #define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE) | 105 | #define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE) |
105 | 106 | ||
106 | static unsigned long node_remap_start_pfn[MAX_NUMNODES]; | ||
107 | unsigned long node_remap_size[MAX_NUMNODES]; | 107 | unsigned long node_remap_size[MAX_NUMNODES]; |
108 | static unsigned long node_remap_offset[MAX_NUMNODES]; | ||
109 | static void *node_remap_start_vaddr[MAX_NUMNODES]; | 108 | static void *node_remap_start_vaddr[MAX_NUMNODES]; |
110 | void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); | 109 | void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); |
111 | 110 | ||
112 | static void *node_remap_end_vaddr[MAX_NUMNODES]; | ||
113 | static void *node_remap_alloc_vaddr[MAX_NUMNODES]; | ||
114 | static unsigned long kva_start_pfn; | 111 | static unsigned long kva_start_pfn; |
115 | static unsigned long kva_pages; | 112 | static unsigned long kva_pages; |
116 | /* | 113 | /* |
@@ -167,6 +164,22 @@ static void __init allocate_pgdat(int nid) | |||
167 | } | 164 | } |
168 | } | 165 | } |
169 | 166 | ||
167 | #ifdef CONFIG_DISCONTIGMEM | ||
168 | /* | ||
169 | * In the discontig memory model, a portion of the kernel virtual area (KVA) | ||
170 | * is reserved and portions of nodes are mapped using it. This is to allow | ||
171 | * node-local memory to be allocated for structures that would normally require | ||
172 | * ZONE_NORMAL. The memory is allocated with alloc_remap() and callers | ||
173 | * should be prepared to allocate from the bootmem allocator instead. This KVA | ||
174 | * mechanism is incompatible with SPARSEMEM as it makes assumptions about the | ||
175 | * layout of memory that are broken if alloc_remap() succeeds for some of the | ||
176 | * map and fails for others | ||
177 | */ | ||
178 | static unsigned long node_remap_start_pfn[MAX_NUMNODES]; | ||
179 | static void *node_remap_end_vaddr[MAX_NUMNODES]; | ||
180 | static void *node_remap_alloc_vaddr[MAX_NUMNODES]; | ||
181 | static unsigned long node_remap_offset[MAX_NUMNODES]; | ||
182 | |||
170 | void *alloc_remap(int nid, unsigned long size) | 183 | void *alloc_remap(int nid, unsigned long size) |
171 | { | 184 | { |
172 | void *allocation = node_remap_alloc_vaddr[nid]; | 185 | void *allocation = node_remap_alloc_vaddr[nid]; |
@@ -263,11 +276,46 @@ static unsigned long calculate_numa_remap_pages(void) | |||
263 | return reserve_pages; | 276 | return reserve_pages; |
264 | } | 277 | } |
265 | 278 | ||
279 | static void init_remap_allocator(int nid) | ||
280 | { | ||
281 | node_remap_start_vaddr[nid] = pfn_to_kaddr( | ||
282 | kva_start_pfn + node_remap_offset[nid]); | ||
283 | node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] + | ||
284 | (node_remap_size[nid] * PAGE_SIZE); | ||
285 | node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] + | ||
286 | ALIGN(sizeof(pg_data_t), PAGE_SIZE); | ||
287 | |||
288 | printk ("node %d will remap to vaddr %08lx - %08lx\n", nid, | ||
289 | (ulong) node_remap_start_vaddr[nid], | ||
290 | (ulong) pfn_to_kaddr(highstart_pfn | ||
291 | + node_remap_offset[nid] + node_remap_size[nid])); | ||
292 | } | ||
293 | #else | ||
294 | void *alloc_remap(int nid, unsigned long size) | ||
295 | { | ||
296 | return NULL; | ||
297 | } | ||
298 | |||
299 | static unsigned long calculate_numa_remap_pages(void) | ||
300 | { | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static void init_remap_allocator(int nid) | ||
305 | { | ||
306 | } | ||
307 | |||
308 | void __init remap_numa_kva(void) | ||
309 | { | ||
310 | } | ||
311 | #endif /* CONFIG_DISCONTIGMEM */ | ||
312 | |||
266 | extern void setup_bootmem_allocator(void); | 313 | extern void setup_bootmem_allocator(void); |
267 | unsigned long __init setup_memory(void) | 314 | unsigned long __init setup_memory(void) |
268 | { | 315 | { |
269 | int nid; | 316 | int nid; |
270 | unsigned long system_start_pfn, system_max_low_pfn; | 317 | unsigned long system_start_pfn, system_max_low_pfn; |
318 | unsigned long wasted_pages; | ||
271 | 319 | ||
272 | /* | 320 | /* |
273 | * When mapping a NUMA machine we allocate the node_mem_map arrays | 321 | * When mapping a NUMA machine we allocate the node_mem_map arrays |
@@ -288,11 +336,18 @@ unsigned long __init setup_memory(void) | |||
288 | 336 | ||
289 | #ifdef CONFIG_BLK_DEV_INITRD | 337 | #ifdef CONFIG_BLK_DEV_INITRD |
290 | /* Numa kva area is below the initrd */ | 338 | /* Numa kva area is below the initrd */ |
291 | if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) | 339 | if (initrd_start) |
292 | kva_start_pfn = PFN_DOWN(boot_params.hdr.ramdisk_image) | 340 | kva_start_pfn = PFN_DOWN(initrd_start - PAGE_OFFSET) |
293 | - kva_pages; | 341 | - kva_pages; |
294 | #endif | 342 | #endif |
295 | kva_start_pfn -= kva_start_pfn & (PTRS_PER_PTE-1); | 343 | |
344 | /* | ||
345 | * We waste pages past at the end of the KVA for no good reason other | ||
346 | * than how it is located. This is bad. | ||
347 | */ | ||
348 | wasted_pages = kva_start_pfn & (PTRS_PER_PTE-1); | ||
349 | kva_start_pfn -= wasted_pages; | ||
350 | kva_pages += wasted_pages; | ||
296 | 351 | ||
297 | system_max_low_pfn = max_low_pfn = find_max_low_pfn(); | 352 | system_max_low_pfn = max_low_pfn = find_max_low_pfn(); |
298 | printk("kva_start_pfn ~ %ld find_max_low_pfn() ~ %ld\n", | 353 | printk("kva_start_pfn ~ %ld find_max_low_pfn() ~ %ld\n", |
@@ -318,19 +373,9 @@ unsigned long __init setup_memory(void) | |||
318 | printk("Low memory ends at vaddr %08lx\n", | 373 | printk("Low memory ends at vaddr %08lx\n", |
319 | (ulong) pfn_to_kaddr(max_low_pfn)); | 374 | (ulong) pfn_to_kaddr(max_low_pfn)); |
320 | for_each_online_node(nid) { | 375 | for_each_online_node(nid) { |
321 | node_remap_start_vaddr[nid] = pfn_to_kaddr( | 376 | init_remap_allocator(nid); |
322 | kva_start_pfn + node_remap_offset[nid]); | ||
323 | /* Init the node remap allocator */ | ||
324 | node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] + | ||
325 | (node_remap_size[nid] * PAGE_SIZE); | ||
326 | node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] + | ||
327 | ALIGN(sizeof(pg_data_t), PAGE_SIZE); | ||
328 | 377 | ||
329 | allocate_pgdat(nid); | 378 | allocate_pgdat(nid); |
330 | printk ("node %d will remap to vaddr %08lx - %08lx\n", nid, | ||
331 | (ulong) node_remap_start_vaddr[nid], | ||
332 | (ulong) pfn_to_kaddr(highstart_pfn | ||
333 | + node_remap_offset[nid] + node_remap_size[nid])); | ||
334 | } | 379 | } |
335 | printk("High memory starts at vaddr %08lx\n", | 380 | printk("High memory starts at vaddr %08lx\n", |
336 | (ulong) pfn_to_kaddr(highstart_pfn)); | 381 | (ulong) pfn_to_kaddr(highstart_pfn)); |
@@ -345,7 +390,8 @@ unsigned long __init setup_memory(void) | |||
345 | 390 | ||
346 | void __init numa_kva_reserve(void) | 391 | void __init numa_kva_reserve(void) |
347 | { | 392 | { |
348 | reserve_bootmem(PFN_PHYS(kva_start_pfn),PFN_PHYS(kva_pages)); | 393 | if (kva_pages) |
394 | reserve_bootmem(PFN_PHYS(kva_start_pfn), PFN_PHYS(kva_pages)); | ||
349 | } | 395 | } |
350 | 396 | ||
351 | void __init zone_sizes_init(void) | 397 | void __init zone_sizes_init(void) |
@@ -430,3 +476,29 @@ int memory_add_physaddr_to_nid(u64 addr) | |||
430 | 476 | ||
431 | EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); | 477 | EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); |
432 | #endif | 478 | #endif |
479 | |||
480 | #ifndef CONFIG_HAVE_ARCH_PARSE_SRAT | ||
481 | /* | ||
482 | * XXX FIXME: Make SLIT table parsing available to 32-bit NUMA | ||
483 | * | ||
484 | * These stub functions are needed to compile 32-bit NUMA when SRAT is | ||
485 | * not set. There are functions in srat_64.c for parsing this table | ||
486 | * and it may be possible to make them common functions. | ||
487 | */ | ||
488 | void acpi_numa_slit_init (struct acpi_table_slit *slit) | ||
489 | { | ||
490 | printk(KERN_INFO "ACPI: No support for parsing SLIT table\n"); | ||
491 | } | ||
492 | |||
493 | void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa) | ||
494 | { | ||
495 | } | ||
496 | |||
497 | void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma) | ||
498 | { | ||
499 | } | ||
500 | |||
501 | void acpi_numa_arch_fixup(void) | ||
502 | { | ||
503 | } | ||
504 | #endif /* CONFIG_HAVE_ARCH_PARSE_SRAT */ | ||