aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/init_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r--arch/x86/mm/init_64.c77
1 files changed, 65 insertions, 12 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index f7d80313ede..51f69b39b75 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -462,18 +462,25 @@ phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end,
462 462
463static void __init find_early_table_space(unsigned long end) 463static void __init find_early_table_space(unsigned long end)
464{ 464{
465 unsigned long puds, tables, start; 465 unsigned long puds, pmds, ptes, tables, start;
466 466
467 puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; 467 puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
468 tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); 468 tables = round_up(puds * sizeof(pud_t), PAGE_SIZE);
469 if (!direct_gbpages) { 469 if (direct_gbpages) {
470 unsigned long pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; 470 unsigned long extra;
471 tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); 471 extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
472 } 472 pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
473 if (!cpu_has_pse) { 473 } else
474 unsigned long ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; 474 pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
475 tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE); 475 tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
476 } 476
477 if (cpu_has_pse) {
478 unsigned long extra;
479 extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
480 ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
481 } else
482 ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
483 tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE);
477 484
478 /* 485 /*
479 * RED-PEN putting page tables only on node 0 could 486 * RED-PEN putting page tables only on node 0 could
@@ -660,8 +667,9 @@ static unsigned long __init kernel_physical_mapping_init(unsigned long start,
660unsigned long __init_refok init_memory_mapping(unsigned long start, 667unsigned long __init_refok init_memory_mapping(unsigned long start,
661 unsigned long end) 668 unsigned long end)
662{ 669{
663 unsigned long last_map_addr; 670 unsigned long last_map_addr = end;
664 unsigned long page_size_mask = 0; 671 unsigned long page_size_mask = 0;
672 unsigned long start_pfn, end_pfn;
665 673
666 printk(KERN_INFO "init_memory_mapping\n"); 674 printk(KERN_INFO "init_memory_mapping\n");
667 675
@@ -682,8 +690,53 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
682 if (cpu_has_pse) 690 if (cpu_has_pse)
683 page_size_mask |= 1 << PG_LEVEL_2M; 691 page_size_mask |= 1 << PG_LEVEL_2M;
684 692
685 last_map_addr = kernel_physical_mapping_init(start, end, 693 /* head if not big page aligment ?*/
686 page_size_mask); 694 start_pfn = start >> PAGE_SHIFT;
695 end_pfn = ((start + (PMD_SIZE - 1)) >> PMD_SHIFT)
696 << (PMD_SHIFT - PAGE_SHIFT);
697 if (start_pfn < end_pfn)
698 last_map_addr = kernel_physical_mapping_init(
699 start_pfn<<PAGE_SHIFT,
700 end_pfn<<PAGE_SHIFT, 0);
701
702 /* big page (2M) range*/
703 start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
704 << (PMD_SHIFT - PAGE_SHIFT);
705 end_pfn = ((start + (PUD_SIZE - 1))>>PUD_SHIFT)
706 << (PUD_SHIFT - PAGE_SHIFT);
707 if (end_pfn > ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT)))
708 end_pfn = ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT));
709 if (start_pfn < end_pfn)
710 last_map_addr = kernel_physical_mapping_init(
711 start_pfn<<PAGE_SHIFT,
712 end_pfn<<PAGE_SHIFT,
713 page_size_mask & (1<<PG_LEVEL_2M));
714
715 /* big page (1G) range */
716 start_pfn = end_pfn;
717 end_pfn = (end>>PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
718 if (start_pfn < end_pfn)
719 last_map_addr = kernel_physical_mapping_init(
720 start_pfn<<PAGE_SHIFT,
721 end_pfn<<PAGE_SHIFT,
722 page_size_mask & ((1<<PG_LEVEL_2M)
723 | (1<<PG_LEVEL_1G)));
724
725 /* tail is not big page (1G) alignment */
726 start_pfn = end_pfn;
727 end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
728 if (start_pfn < end_pfn)
729 last_map_addr = kernel_physical_mapping_init(
730 start_pfn<<PAGE_SHIFT,
731 end_pfn<<PAGE_SHIFT,
732 page_size_mask & (1<<PG_LEVEL_2M));
733 /* tail is not big page (2M) alignment */
734 start_pfn = end_pfn;
735 end_pfn = end>>PAGE_SHIFT;
736 if (start_pfn < end_pfn)
737 last_map_addr = kernel_physical_mapping_init(
738 start_pfn<<PAGE_SHIFT,
739 end_pfn<<PAGE_SHIFT, 0);
687 740
688 if (!after_bootmem) 741 if (!after_bootmem)
689 mmu_cr4_features = read_cr4(); 742 mmu_cr4_features = read_cr4();