diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-02-16 03:42:50 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-02-16 03:43:54 -0500 |
commit | 02ac81a812fe0575a8475a93bdc22fb291ebad91 (patch) | |
tree | 690f1b48b070f5e268d51c54b63943dc3b807e50 /arch/x86/mm | |
parent | 9a6d44b9adb777ca9549e88cd55bd8f2673c52a2 (diff) | |
parent | d2137d5af4259f50c19addb8246a186c9ffac325 (diff) |
Merge branch 'x86/bootmem' into x86/mm
Merge reason: the topic is ready - consolidate it into the more generic x86/mm tree
and prevent conflicts.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/amdtopology_64.c | 8 | ||||
-rw-r--r-- | arch/x86/mm/init.c | 36 | ||||
-rw-r--r-- | arch/x86/mm/init_64.c | 117 | ||||
-rw-r--r-- | arch/x86/mm/numa_64.c | 8 | ||||
-rw-r--r-- | arch/x86/mm/srat_64.c | 2 |
5 files changed, 97 insertions, 74 deletions
diff --git a/arch/x86/mm/amdtopology_64.c b/arch/x86/mm/amdtopology_64.c index f21962c435ed..49b334cdd64c 100644 --- a/arch/x86/mm/amdtopology_64.c +++ b/arch/x86/mm/amdtopology_64.c | |||
@@ -278,12 +278,14 @@ int __init amd_scan_nodes(void) | |||
278 | apicid_base = boot_cpu_physical_apicid; | 278 | apicid_base = boot_cpu_physical_apicid; |
279 | } | 279 | } |
280 | 280 | ||
281 | for_each_node_mask(i, node_possible_map) { | 281 | for_each_node_mask(i, node_possible_map) |
282 | int j; | ||
283 | |||
284 | memblock_x86_register_active_regions(i, | 282 | memblock_x86_register_active_regions(i, |
285 | nodes[i].start >> PAGE_SHIFT, | 283 | nodes[i].start >> PAGE_SHIFT, |
286 | nodes[i].end >> PAGE_SHIFT); | 284 | nodes[i].end >> PAGE_SHIFT); |
285 | init_memory_mapping_high(); | ||
286 | for_each_node_mask(i, node_possible_map) { | ||
287 | int j; | ||
288 | |||
287 | for (j = apicid_base; j < cores + apicid_base; j++) | 289 | for (j = apicid_base; j < cores + apicid_base; j++) |
288 | apicid_to_node[(i << bits) + j] = i; | 290 | apicid_to_node[(i << bits) + j] = i; |
289 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 291 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 947f42abe820..b8054e087ead 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -33,7 +33,7 @@ int direct_gbpages | |||
33 | static void __init find_early_table_space(unsigned long end, int use_pse, | 33 | static void __init find_early_table_space(unsigned long end, int use_pse, |
34 | int use_gbpages) | 34 | int use_gbpages) |
35 | { | 35 | { |
36 | unsigned long puds, pmds, ptes, tables, start; | 36 | unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; |
37 | phys_addr_t base; | 37 | phys_addr_t base; |
38 | 38 | ||
39 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; | 39 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; |
@@ -65,20 +65,11 @@ static void __init find_early_table_space(unsigned long end, int use_pse, | |||
65 | #ifdef CONFIG_X86_32 | 65 | #ifdef CONFIG_X86_32 |
66 | /* for fixmap */ | 66 | /* for fixmap */ |
67 | tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE); | 67 | tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE); |
68 | #endif | ||
69 | 68 | ||
70 | /* | 69 | good_end = max_pfn_mapped << PAGE_SHIFT; |
71 | * RED-PEN putting page tables only on node 0 could | ||
72 | * cause a hotspot and fill up ZONE_DMA. The page tables | ||
73 | * need roughly 0.5KB per GB. | ||
74 | */ | ||
75 | #ifdef CONFIG_X86_32 | ||
76 | start = 0x7000; | ||
77 | #else | ||
78 | start = 0x8000; | ||
79 | #endif | 70 | #endif |
80 | base = memblock_find_in_range(start, max_pfn_mapped<<PAGE_SHIFT, | 71 | |
81 | tables, PAGE_SIZE); | 72 | base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE); |
82 | if (base == MEMBLOCK_ERROR) | 73 | if (base == MEMBLOCK_ERROR) |
83 | panic("Cannot find space for the kernel page tables"); | 74 | panic("Cannot find space for the kernel page tables"); |
84 | 75 | ||
@@ -279,25 +270,6 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
279 | load_cr3(swapper_pg_dir); | 270 | load_cr3(swapper_pg_dir); |
280 | #endif | 271 | #endif |
281 | 272 | ||
282 | #ifdef CONFIG_X86_64 | ||
283 | if (!after_bootmem && !start) { | ||
284 | pud_t *pud; | ||
285 | pmd_t *pmd; | ||
286 | |||
287 | mmu_cr4_features = read_cr4(); | ||
288 | |||
289 | /* | ||
290 | * _brk_end cannot change anymore, but it and _end may be | ||
291 | * located on different 2M pages. cleanup_highmap(), however, | ||
292 | * can only consider _end when it runs, so destroy any | ||
293 | * mappings beyond _brk_end here. | ||
294 | */ | ||
295 | pud = pud_offset(pgd_offset_k(_brk_end), _brk_end); | ||
296 | pmd = pmd_offset(pud, _brk_end - 1); | ||
297 | while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1)) | ||
298 | pmd_clear(pmd); | ||
299 | } | ||
300 | #endif | ||
301 | __flush_tlb_all(); | 273 | __flush_tlb_all(); |
302 | 274 | ||
303 | if (!after_bootmem && e820_table_end > e820_table_start) | 275 | if (!after_bootmem && e820_table_end > e820_table_start) |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 71a59296af80..194f2732ab77 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -333,12 +333,28 @@ static __ref void *alloc_low_page(unsigned long *phys) | |||
333 | return adr; | 333 | return adr; |
334 | } | 334 | } |
335 | 335 | ||
336 | static __ref void *map_low_page(void *virt) | ||
337 | { | ||
338 | void *adr; | ||
339 | unsigned long phys, left; | ||
340 | |||
341 | if (after_bootmem) | ||
342 | return virt; | ||
343 | |||
344 | phys = __pa(virt); | ||
345 | left = phys & (PAGE_SIZE - 1); | ||
346 | adr = early_memremap(phys & PAGE_MASK, PAGE_SIZE); | ||
347 | adr = (void *)(((unsigned long)adr) | left); | ||
348 | |||
349 | return adr; | ||
350 | } | ||
351 | |||
336 | static __ref void unmap_low_page(void *adr) | 352 | static __ref void unmap_low_page(void *adr) |
337 | { | 353 | { |
338 | if (after_bootmem) | 354 | if (after_bootmem) |
339 | return; | 355 | return; |
340 | 356 | ||
341 | early_iounmap(adr, PAGE_SIZE); | 357 | early_iounmap((void *)((unsigned long)adr & PAGE_MASK), PAGE_SIZE); |
342 | } | 358 | } |
343 | 359 | ||
344 | static unsigned long __meminit | 360 | static unsigned long __meminit |
@@ -386,15 +402,6 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, | |||
386 | } | 402 | } |
387 | 403 | ||
388 | static unsigned long __meminit | 404 | static unsigned long __meminit |
389 | phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end, | ||
390 | pgprot_t prot) | ||
391 | { | ||
392 | pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd); | ||
393 | |||
394 | return phys_pte_init(pte, address, end, prot); | ||
395 | } | ||
396 | |||
397 | static unsigned long __meminit | ||
398 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, | 405 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, |
399 | unsigned long page_size_mask, pgprot_t prot) | 406 | unsigned long page_size_mask, pgprot_t prot) |
400 | { | 407 | { |
@@ -420,8 +427,10 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, | |||
420 | if (pmd_val(*pmd)) { | 427 | if (pmd_val(*pmd)) { |
421 | if (!pmd_large(*pmd)) { | 428 | if (!pmd_large(*pmd)) { |
422 | spin_lock(&init_mm.page_table_lock); | 429 | spin_lock(&init_mm.page_table_lock); |
423 | last_map_addr = phys_pte_update(pmd, address, | 430 | pte = map_low_page((pte_t *)pmd_page_vaddr(*pmd)); |
431 | last_map_addr = phys_pte_init(pte, address, | ||
424 | end, prot); | 432 | end, prot); |
433 | unmap_low_page(pte); | ||
425 | spin_unlock(&init_mm.page_table_lock); | 434 | spin_unlock(&init_mm.page_table_lock); |
426 | continue; | 435 | continue; |
427 | } | 436 | } |
@@ -468,18 +477,6 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, | |||
468 | } | 477 | } |
469 | 478 | ||
470 | static unsigned long __meminit | 479 | static unsigned long __meminit |
471 | phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end, | ||
472 | unsigned long page_size_mask, pgprot_t prot) | ||
473 | { | ||
474 | pmd_t *pmd = pmd_offset(pud, 0); | ||
475 | unsigned long last_map_addr; | ||
476 | |||
477 | last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask, prot); | ||
478 | __flush_tlb_all(); | ||
479 | return last_map_addr; | ||
480 | } | ||
481 | |||
482 | static unsigned long __meminit | ||
483 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, | 480 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, |
484 | unsigned long page_size_mask) | 481 | unsigned long page_size_mask) |
485 | { | 482 | { |
@@ -504,8 +501,11 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, | |||
504 | 501 | ||
505 | if (pud_val(*pud)) { | 502 | if (pud_val(*pud)) { |
506 | if (!pud_large(*pud)) { | 503 | if (!pud_large(*pud)) { |
507 | last_map_addr = phys_pmd_update(pud, addr, end, | 504 | pmd = map_low_page(pmd_offset(pud, 0)); |
505 | last_map_addr = phys_pmd_init(pmd, addr, end, | ||
508 | page_size_mask, prot); | 506 | page_size_mask, prot); |
507 | unmap_low_page(pmd); | ||
508 | __flush_tlb_all(); | ||
509 | continue; | 509 | continue; |
510 | } | 510 | } |
511 | /* | 511 | /* |
@@ -553,17 +553,6 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, | |||
553 | return last_map_addr; | 553 | return last_map_addr; |
554 | } | 554 | } |
555 | 555 | ||
556 | static unsigned long __meminit | ||
557 | phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
558 | unsigned long page_size_mask) | ||
559 | { | ||
560 | pud_t *pud; | ||
561 | |||
562 | pud = (pud_t *)pgd_page_vaddr(*pgd); | ||
563 | |||
564 | return phys_pud_init(pud, addr, end, page_size_mask); | ||
565 | } | ||
566 | |||
567 | unsigned long __meminit | 556 | unsigned long __meminit |
568 | kernel_physical_mapping_init(unsigned long start, | 557 | kernel_physical_mapping_init(unsigned long start, |
569 | unsigned long end, | 558 | unsigned long end, |
@@ -587,8 +576,10 @@ kernel_physical_mapping_init(unsigned long start, | |||
587 | next = end; | 576 | next = end; |
588 | 577 | ||
589 | if (pgd_val(*pgd)) { | 578 | if (pgd_val(*pgd)) { |
590 | last_map_addr = phys_pud_update(pgd, __pa(start), | 579 | pud = map_low_page((pud_t *)pgd_page_vaddr(*pgd)); |
580 | last_map_addr = phys_pud_init(pud, __pa(start), | ||
591 | __pa(end), page_size_mask); | 581 | __pa(end), page_size_mask); |
582 | unmap_low_page(pud); | ||
592 | continue; | 583 | continue; |
593 | } | 584 | } |
594 | 585 | ||
@@ -616,9 +607,63 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn, | |||
616 | int acpi, int k8) | 607 | int acpi, int k8) |
617 | { | 608 | { |
618 | memblock_x86_register_active_regions(0, start_pfn, end_pfn); | 609 | memblock_x86_register_active_regions(0, start_pfn, end_pfn); |
610 | init_memory_mapping_high(); | ||
619 | } | 611 | } |
620 | #endif | 612 | #endif |
621 | 613 | ||
614 | struct mapping_work_data { | ||
615 | unsigned long start; | ||
616 | unsigned long end; | ||
617 | unsigned long pfn_mapped; | ||
618 | }; | ||
619 | |||
620 | static int __init_refok | ||
621 | mapping_work_fn(unsigned long start_pfn, unsigned long end_pfn, void *datax) | ||
622 | { | ||
623 | struct mapping_work_data *data = datax; | ||
624 | unsigned long pfn_mapped; | ||
625 | unsigned long final_start, final_end; | ||
626 | |||
627 | final_start = max_t(unsigned long, start_pfn<<PAGE_SHIFT, data->start); | ||
628 | final_end = min_t(unsigned long, end_pfn<<PAGE_SHIFT, data->end); | ||
629 | |||
630 | if (final_end <= final_start) | ||
631 | return 0; | ||
632 | |||
633 | pfn_mapped = init_memory_mapping(final_start, final_end); | ||
634 | |||
635 | if (pfn_mapped > data->pfn_mapped) | ||
636 | data->pfn_mapped = pfn_mapped; | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static unsigned long __init_refok | ||
642 | init_memory_mapping_active_regions(unsigned long start, unsigned long end) | ||
643 | { | ||
644 | struct mapping_work_data data; | ||
645 | |||
646 | data.start = start; | ||
647 | data.end = end; | ||
648 | data.pfn_mapped = 0; | ||
649 | |||
650 | work_with_active_regions(MAX_NUMNODES, mapping_work_fn, &data); | ||
651 | |||
652 | return data.pfn_mapped; | ||
653 | } | ||
654 | |||
655 | void __init_refok init_memory_mapping_high(void) | ||
656 | { | ||
657 | if (max_pfn > max_low_pfn) { | ||
658 | max_pfn_mapped = init_memory_mapping_active_regions(1UL<<32, | ||
659 | max_pfn<<PAGE_SHIFT); | ||
660 | /* can we preserve max_low_pfn ? */ | ||
661 | max_low_pfn = max_pfn; | ||
662 | |||
663 | memblock.current_limit = get_max_mapped(); | ||
664 | } | ||
665 | } | ||
666 | |||
622 | void __init paging_init(void) | 667 | void __init paging_init(void) |
623 | { | 668 | { |
624 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 669 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 95ea1551eebc..62cb634b5cf8 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -86,7 +86,7 @@ static int __init allocate_cachealigned_memnodemap(void) | |||
86 | 86 | ||
87 | addr = 0x8000; | 87 | addr = 0x8000; |
88 | nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); | 88 | nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); |
89 | nodemap_addr = memblock_find_in_range(addr, max_pfn<<PAGE_SHIFT, | 89 | nodemap_addr = memblock_find_in_range(addr, get_max_mapped(), |
90 | nodemap_size, L1_CACHE_BYTES); | 90 | nodemap_size, L1_CACHE_BYTES); |
91 | if (nodemap_addr == MEMBLOCK_ERROR) { | 91 | if (nodemap_addr == MEMBLOCK_ERROR) { |
92 | printk(KERN_ERR | 92 | printk(KERN_ERR |
@@ -598,11 +598,12 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
598 | * the e820 memory map. | 598 | * the e820 memory map. |
599 | */ | 599 | */ |
600 | remove_all_active_ranges(); | 600 | remove_all_active_ranges(); |
601 | for_each_node_mask(i, node_possible_map) { | 601 | for_each_node_mask(i, node_possible_map) |
602 | memblock_x86_register_active_regions(i, nodes[i].start >> PAGE_SHIFT, | 602 | memblock_x86_register_active_regions(i, nodes[i].start >> PAGE_SHIFT, |
603 | nodes[i].end >> PAGE_SHIFT); | 603 | nodes[i].end >> PAGE_SHIFT); |
604 | init_memory_mapping_high(); | ||
605 | for_each_node_mask(i, node_possible_map) | ||
604 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 606 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
605 | } | ||
606 | setup_physnodes(addr, max_addr, acpi, amd); | 607 | setup_physnodes(addr, max_addr, acpi, amd); |
607 | fake_physnodes(acpi, amd, num_nodes); | 608 | fake_physnodes(acpi, amd, num_nodes); |
608 | numa_init_array(); | 609 | numa_init_array(); |
@@ -658,6 +659,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, | |||
658 | for (i = 0; i < nr_cpu_ids; i++) | 659 | for (i = 0; i < nr_cpu_ids; i++) |
659 | numa_set_node(i, 0); | 660 | numa_set_node(i, 0); |
660 | memblock_x86_register_active_regions(0, start_pfn, last_pfn); | 661 | memblock_x86_register_active_regions(0, start_pfn, last_pfn); |
662 | init_memory_mapping_high(); | ||
661 | setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT); | 663 | setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT); |
662 | } | 664 | } |
663 | 665 | ||
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 603d285d1daa..4c03e13da138 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
@@ -444,6 +444,8 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
444 | return -1; | 444 | return -1; |
445 | } | 445 | } |
446 | 446 | ||
447 | init_memory_mapping_high(); | ||
448 | |||
447 | /* Account for nodes with cpus and no memory */ | 449 | /* Account for nodes with cpus and no memory */ |
448 | nodes_or(node_possible_map, nodes_parsed, cpu_nodes_parsed); | 450 | nodes_or(node_possible_map, nodes_parsed, cpu_nodes_parsed); |
449 | 451 | ||