aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2011-02-16 03:42:50 -0500
committerIngo Molnar <mingo@elte.hu>2011-02-16 03:43:54 -0500
commit02ac81a812fe0575a8475a93bdc22fb291ebad91 (patch)
tree690f1b48b070f5e268d51c54b63943dc3b807e50 /arch/x86/mm
parent9a6d44b9adb777ca9549e88cd55bd8f2673c52a2 (diff)
parentd2137d5af4259f50c19addb8246a186c9ffac325 (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.c8
-rw-r--r--arch/x86/mm/init.c36
-rw-r--r--arch/x86/mm/init_64.c117
-rw-r--r--arch/x86/mm/numa_64.c8
-rw-r--r--arch/x86/mm/srat_64.c2
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
33static void __init find_early_table_space(unsigned long end, int use_pse, 33static 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
336static __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
336static __ref void unmap_low_page(void *adr) 352static __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
344static unsigned long __meminit 360static unsigned long __meminit
@@ -386,15 +402,6 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
386} 402}
387 403
388static unsigned long __meminit 404static unsigned long __meminit
389phys_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
397static unsigned long __meminit
398phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, 405phys_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
470static unsigned long __meminit 479static unsigned long __meminit
471phys_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
482static unsigned long __meminit
483phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, 480phys_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
556static unsigned long __meminit
557phys_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
567unsigned long __meminit 556unsigned long __meminit
568kernel_physical_mapping_init(unsigned long start, 557kernel_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
614struct mapping_work_data {
615 unsigned long start;
616 unsigned long end;
617 unsigned long pfn_mapped;
618};
619
620static int __init_refok
621mapping_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
641static unsigned long __init_refok
642init_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
655void __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
622void __init paging_init(void) 667void __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