diff options
Diffstat (limited to 'arch/x86/mm/init_64.c')
| -rw-r--r-- | arch/x86/mm/init_64.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index b8e461d4941..9db01db6e3c 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
| @@ -350,8 +350,10 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, | |||
| 350 | * pagetable pages as RO. So assume someone who pre-setup | 350 | * pagetable pages as RO. So assume someone who pre-setup |
| 351 | * these mappings are more intelligent. | 351 | * these mappings are more intelligent. |
| 352 | */ | 352 | */ |
| 353 | if (pte_val(*pte)) | 353 | if (pte_val(*pte)) { |
| 354 | pages++; | ||
| 354 | continue; | 355 | continue; |
| 356 | } | ||
| 355 | 357 | ||
| 356 | if (0) | 358 | if (0) |
| 357 | printk(" pte=%p addr=%lx pte=%016lx\n", | 359 | printk(" pte=%p addr=%lx pte=%016lx\n", |
| @@ -418,8 +420,10 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, | |||
| 418 | * not differ with respect to page frame and | 420 | * not differ with respect to page frame and |
| 419 | * attributes. | 421 | * attributes. |
| 420 | */ | 422 | */ |
| 421 | if (page_size_mask & (1 << PG_LEVEL_2M)) | 423 | if (page_size_mask & (1 << PG_LEVEL_2M)) { |
| 424 | pages++; | ||
| 422 | continue; | 425 | continue; |
| 426 | } | ||
| 423 | new_prot = pte_pgprot(pte_clrhuge(*(pte_t *)pmd)); | 427 | new_prot = pte_pgprot(pte_clrhuge(*(pte_t *)pmd)); |
| 424 | } | 428 | } |
| 425 | 429 | ||
| @@ -499,8 +503,10 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, | |||
| 499 | * not differ with respect to page frame and | 503 | * not differ with respect to page frame and |
| 500 | * attributes. | 504 | * attributes. |
| 501 | */ | 505 | */ |
| 502 | if (page_size_mask & (1 << PG_LEVEL_1G)) | 506 | if (page_size_mask & (1 << PG_LEVEL_1G)) { |
| 507 | pages++; | ||
| 503 | continue; | 508 | continue; |
| 509 | } | ||
| 504 | prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud)); | 510 | prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud)); |
| 505 | } | 511 | } |
| 506 | 512 | ||
| @@ -665,12 +671,13 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
| 665 | unsigned long last_map_addr = 0; | 671 | unsigned long last_map_addr = 0; |
| 666 | unsigned long page_size_mask = 0; | 672 | unsigned long page_size_mask = 0; |
| 667 | unsigned long start_pfn, end_pfn; | 673 | unsigned long start_pfn, end_pfn; |
| 674 | unsigned long pos; | ||
| 668 | 675 | ||
| 669 | struct map_range mr[NR_RANGE_MR]; | 676 | struct map_range mr[NR_RANGE_MR]; |
| 670 | int nr_range, i; | 677 | int nr_range, i; |
| 671 | int use_pse, use_gbpages; | 678 | int use_pse, use_gbpages; |
| 672 | 679 | ||
| 673 | printk(KERN_INFO "init_memory_mapping\n"); | 680 | printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end); |
| 674 | 681 | ||
| 675 | /* | 682 | /* |
| 676 | * Find space for the kernel direct mapping tables. | 683 | * Find space for the kernel direct mapping tables. |
| @@ -704,35 +711,50 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
| 704 | 711 | ||
| 705 | /* head if not big page alignment ?*/ | 712 | /* head if not big page alignment ?*/ |
| 706 | start_pfn = start >> PAGE_SHIFT; | 713 | start_pfn = start >> PAGE_SHIFT; |
| 707 | end_pfn = ((start + (PMD_SIZE - 1)) >> PMD_SHIFT) | 714 | pos = start_pfn << PAGE_SHIFT; |
| 715 | end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT) | ||
| 708 | << (PMD_SHIFT - PAGE_SHIFT); | 716 | << (PMD_SHIFT - PAGE_SHIFT); |
| 709 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0); | 717 | if (start_pfn < end_pfn) { |
| 718 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0); | ||
| 719 | pos = end_pfn << PAGE_SHIFT; | ||
| 720 | } | ||
| 710 | 721 | ||
| 711 | /* big page (2M) range*/ | 722 | /* big page (2M) range*/ |
| 712 | start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT) | 723 | start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT) |
| 713 | << (PMD_SHIFT - PAGE_SHIFT); | 724 | << (PMD_SHIFT - PAGE_SHIFT); |
| 714 | end_pfn = ((start + (PUD_SIZE - 1))>>PUD_SHIFT) | 725 | end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT) |
| 715 | << (PUD_SHIFT - PAGE_SHIFT); | 726 | << (PUD_SHIFT - PAGE_SHIFT); |
| 716 | if (end_pfn > ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT))) | 727 | if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT))) |
| 717 | end_pfn = ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT)); | 728 | end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)); |
| 718 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, | 729 | if (start_pfn < end_pfn) { |
| 719 | page_size_mask & (1<<PG_LEVEL_2M)); | 730 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, |
| 731 | page_size_mask & (1<<PG_LEVEL_2M)); | ||
| 732 | pos = end_pfn << PAGE_SHIFT; | ||
| 733 | } | ||
| 720 | 734 | ||
| 721 | /* big page (1G) range */ | 735 | /* big page (1G) range */ |
| 722 | start_pfn = end_pfn; | 736 | start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT) |
| 723 | end_pfn = (end>>PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT); | 737 | << (PUD_SHIFT - PAGE_SHIFT); |
| 724 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, | 738 | end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT); |
| 739 | if (start_pfn < end_pfn) { | ||
| 740 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, | ||
| 725 | page_size_mask & | 741 | page_size_mask & |
| 726 | ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G))); | 742 | ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G))); |
| 743 | pos = end_pfn << PAGE_SHIFT; | ||
| 744 | } | ||
| 727 | 745 | ||
| 728 | /* tail is not big page (1G) alignment */ | 746 | /* tail is not big page (1G) alignment */ |
| 729 | start_pfn = end_pfn; | 747 | start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT) |
| 730 | end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT); | 748 | << (PMD_SHIFT - PAGE_SHIFT); |
| 731 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, | 749 | end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT); |
| 732 | page_size_mask & (1<<PG_LEVEL_2M)); | 750 | if (start_pfn < end_pfn) { |
| 751 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, | ||
| 752 | page_size_mask & (1<<PG_LEVEL_2M)); | ||
| 753 | pos = end_pfn << PAGE_SHIFT; | ||
| 754 | } | ||
| 733 | 755 | ||
| 734 | /* tail is not big page (2M) alignment */ | 756 | /* tail is not big page (2M) alignment */ |
| 735 | start_pfn = end_pfn; | 757 | start_pfn = pos>>PAGE_SHIFT; |
| 736 | end_pfn = end>>PAGE_SHIFT; | 758 | end_pfn = end>>PAGE_SHIFT; |
| 737 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0); | 759 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0); |
| 738 | 760 | ||
| @@ -831,12 +853,12 @@ int arch_add_memory(int nid, u64 start, u64 size) | |||
| 831 | unsigned long nr_pages = size >> PAGE_SHIFT; | 853 | unsigned long nr_pages = size >> PAGE_SHIFT; |
| 832 | int ret; | 854 | int ret; |
| 833 | 855 | ||
| 834 | last_mapped_pfn = init_memory_mapping(start, start + size-1); | 856 | last_mapped_pfn = init_memory_mapping(start, start + size); |
| 835 | if (last_mapped_pfn > max_pfn_mapped) | 857 | if (last_mapped_pfn > max_pfn_mapped) |
| 836 | max_pfn_mapped = last_mapped_pfn; | 858 | max_pfn_mapped = last_mapped_pfn; |
| 837 | 859 | ||
| 838 | ret = __add_pages(zone, start_pfn, nr_pages); | 860 | ret = __add_pages(zone, start_pfn, nr_pages); |
| 839 | WARN_ON(1); | 861 | WARN_ON_ONCE(ret); |
| 840 | 862 | ||
| 841 | return ret; | 863 | return ret; |
| 842 | } | 864 | } |
| @@ -878,6 +900,7 @@ static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, | |||
| 878 | void __init mem_init(void) | 900 | void __init mem_init(void) |
| 879 | { | 901 | { |
| 880 | long codesize, reservedpages, datasize, initsize; | 902 | long codesize, reservedpages, datasize, initsize; |
| 903 | unsigned long absent_pages; | ||
| 881 | 904 | ||
| 882 | start_periodic_check_for_corruption(); | 905 | start_periodic_check_for_corruption(); |
| 883 | 906 | ||
| @@ -893,8 +916,9 @@ void __init mem_init(void) | |||
| 893 | #else | 916 | #else |
| 894 | totalram_pages = free_all_bootmem(); | 917 | totalram_pages = free_all_bootmem(); |
| 895 | #endif | 918 | #endif |
| 896 | reservedpages = max_pfn - totalram_pages - | 919 | |
| 897 | absent_pages_in_range(0, max_pfn); | 920 | absent_pages = absent_pages_in_range(0, max_pfn); |
| 921 | reservedpages = max_pfn - totalram_pages - absent_pages; | ||
| 898 | after_bootmem = 1; | 922 | after_bootmem = 1; |
| 899 | 923 | ||
| 900 | codesize = (unsigned long) &_etext - (unsigned long) &_text; | 924 | codesize = (unsigned long) &_etext - (unsigned long) &_text; |
| @@ -911,10 +935,11 @@ void __init mem_init(void) | |||
| 911 | VSYSCALL_END - VSYSCALL_START); | 935 | VSYSCALL_END - VSYSCALL_START); |
| 912 | 936 | ||
| 913 | printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " | 937 | printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " |
| 914 | "%ldk reserved, %ldk data, %ldk init)\n", | 938 | "%ldk absent, %ldk reserved, %ldk data, %ldk init)\n", |
| 915 | (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), | 939 | (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), |
| 916 | max_pfn << (PAGE_SHIFT-10), | 940 | max_pfn << (PAGE_SHIFT-10), |
| 917 | codesize >> 10, | 941 | codesize >> 10, |
| 942 | absent_pages << (PAGE_SHIFT-10), | ||
| 918 | reservedpages << (PAGE_SHIFT-10), | 943 | reservedpages << (PAGE_SHIFT-10), |
| 919 | datasize >> 10, | 944 | datasize >> 10, |
| 920 | initsize >> 10); | 945 | initsize >> 10); |
