aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/init_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/init_32.c')
-rw-r--r--arch/x86/mm/init_32.c213
1 files changed, 99 insertions, 114 deletions
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 2cef05074413..47df0e1bbeb9 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -49,9 +49,6 @@
49#include <asm/paravirt.h> 49#include <asm/paravirt.h>
50#include <asm/setup.h> 50#include <asm/setup.h>
51#include <asm/cacheflush.h> 51#include <asm/cacheflush.h>
52#include <asm/smp.h>
53
54unsigned int __VMALLOC_RESERVE = 128 << 20;
55 52
56unsigned long max_low_pfn_mapped; 53unsigned long max_low_pfn_mapped;
57unsigned long max_pfn_mapped; 54unsigned long max_pfn_mapped;
@@ -138,6 +135,23 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
138 return pte_offset_kernel(pmd, 0); 135 return pte_offset_kernel(pmd, 0);
139} 136}
140 137
138pmd_t * __init populate_extra_pmd(unsigned long vaddr)
139{
140 int pgd_idx = pgd_index(vaddr);
141 int pmd_idx = pmd_index(vaddr);
142
143 return one_md_table_init(swapper_pg_dir + pgd_idx) + pmd_idx;
144}
145
146pte_t * __init populate_extra_pte(unsigned long vaddr)
147{
148 int pte_idx = pte_index(vaddr);
149 pmd_t *pmd;
150
151 pmd = populate_extra_pmd(vaddr);
152 return one_page_table_init(pmd) + pte_idx;
153}
154
141static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd, 155static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
142 unsigned long vaddr, pte_t *lastpte) 156 unsigned long vaddr, pte_t *lastpte)
143{ 157{
@@ -470,22 +484,10 @@ void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn,
470 work_with_active_regions(nid, add_highpages_work_fn, &data); 484 work_with_active_regions(nid, add_highpages_work_fn, &data);
471} 485}
472 486
473#ifndef CONFIG_NUMA
474static void __init set_highmem_pages_init(void)
475{
476 add_highpages_with_active_regions(0, highstart_pfn, highend_pfn);
477
478 totalram_pages += totalhigh_pages;
479}
480#endif /* !CONFIG_NUMA */
481
482#else 487#else
483static inline void permanent_kmaps_init(pgd_t *pgd_base) 488static inline void permanent_kmaps_init(pgd_t *pgd_base)
484{ 489{
485} 490}
486static inline void set_highmem_pages_init(void)
487{
488}
489#endif /* CONFIG_HIGHMEM */ 491#endif /* CONFIG_HIGHMEM */
490 492
491void __init native_pagetable_setup_start(pgd_t *base) 493void __init native_pagetable_setup_start(pgd_t *base)
@@ -675,75 +677,97 @@ static int __init parse_highmem(char *arg)
675} 677}
676early_param("highmem", parse_highmem); 678early_param("highmem", parse_highmem);
677 679
680#define MSG_HIGHMEM_TOO_BIG \
681 "highmem size (%luMB) is bigger than pages available (%luMB)!\n"
682
683#define MSG_LOWMEM_TOO_SMALL \
684 "highmem size (%luMB) results in <64MB lowmem, ignoring it!\n"
678/* 685/*
679 * Determine low and high memory ranges: 686 * All of RAM fits into lowmem - but if user wants highmem
687 * artificially via the highmem=x boot parameter then create
688 * it:
680 */ 689 */
681void __init find_low_pfn_range(void) 690void __init lowmem_pfn_init(void)
682{ 691{
683 /* it could update max_pfn */
684
685 /* max_low_pfn is 0, we already have early_res support */ 692 /* max_low_pfn is 0, we already have early_res support */
686
687 max_low_pfn = max_pfn; 693 max_low_pfn = max_pfn;
688 if (max_low_pfn > MAXMEM_PFN) { 694
689 if (highmem_pages == -1) 695 if (highmem_pages == -1)
690 highmem_pages = max_pfn - MAXMEM_PFN; 696 highmem_pages = 0;
691 if (highmem_pages + MAXMEM_PFN < max_pfn) 697#ifdef CONFIG_HIGHMEM
692 max_pfn = MAXMEM_PFN + highmem_pages; 698 if (highmem_pages >= max_pfn) {
693 if (highmem_pages + MAXMEM_PFN > max_pfn) { 699 printk(KERN_ERR MSG_HIGHMEM_TOO_BIG,
694 printk(KERN_WARNING "only %luMB highmem pages " 700 pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
695 "available, ignoring highmem size of %uMB.\n", 701 highmem_pages = 0;
696 pages_to_mb(max_pfn - MAXMEM_PFN), 702 }
703 if (highmem_pages) {
704 if (max_low_pfn - highmem_pages < 64*1024*1024/PAGE_SIZE) {
705 printk(KERN_ERR MSG_LOWMEM_TOO_SMALL,
697 pages_to_mb(highmem_pages)); 706 pages_to_mb(highmem_pages));
698 highmem_pages = 0; 707 highmem_pages = 0;
699 } 708 }
700 max_low_pfn = MAXMEM_PFN; 709 max_low_pfn -= highmem_pages;
710 }
711#else
712 if (highmem_pages)
713 printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
714#endif
715}
716
717#define MSG_HIGHMEM_TOO_SMALL \
718 "only %luMB highmem pages available, ignoring highmem size of %luMB!\n"
719
720#define MSG_HIGHMEM_TRIMMED \
721 "Warning: only 4GB will be used. Use a HIGHMEM64G enabled kernel!\n"
722/*
723 * We have more RAM than fits into lowmem - we try to put it into
724 * highmem, also taking the highmem=x boot parameter into account:
725 */
726void __init highmem_pfn_init(void)
727{
728 max_low_pfn = MAXMEM_PFN;
729
730 if (highmem_pages == -1)
731 highmem_pages = max_pfn - MAXMEM_PFN;
732
733 if (highmem_pages + MAXMEM_PFN < max_pfn)
734 max_pfn = MAXMEM_PFN + highmem_pages;
735
736 if (highmem_pages + MAXMEM_PFN > max_pfn) {
737 printk(KERN_WARNING MSG_HIGHMEM_TOO_SMALL,
738 pages_to_mb(max_pfn - MAXMEM_PFN),
739 pages_to_mb(highmem_pages));
740 highmem_pages = 0;
741 }
701#ifndef CONFIG_HIGHMEM 742#ifndef CONFIG_HIGHMEM
702 /* Maximum memory usable is what is directly addressable */ 743 /* Maximum memory usable is what is directly addressable */
703 printk(KERN_WARNING "Warning only %ldMB will be used.\n", 744 printk(KERN_WARNING "Warning only %ldMB will be used.\n", MAXMEM>>20);
704 MAXMEM>>20); 745 if (max_pfn > MAX_NONPAE_PFN)
705 if (max_pfn > MAX_NONPAE_PFN) 746 printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
706 printk(KERN_WARNING 747 else
707 "Use a HIGHMEM64G enabled kernel.\n"); 748 printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
708 else 749 max_pfn = MAXMEM_PFN;
709 printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
710 max_pfn = MAXMEM_PFN;
711#else /* !CONFIG_HIGHMEM */ 750#else /* !CONFIG_HIGHMEM */
712#ifndef CONFIG_HIGHMEM64G 751#ifndef CONFIG_HIGHMEM64G
713 if (max_pfn > MAX_NONPAE_PFN) { 752 if (max_pfn > MAX_NONPAE_PFN) {
714 max_pfn = MAX_NONPAE_PFN; 753 max_pfn = MAX_NONPAE_PFN;
715 printk(KERN_WARNING "Warning only 4GB will be used." 754 printk(KERN_WARNING MSG_HIGHMEM_TRIMMED);
716 "Use a HIGHMEM64G enabled kernel.\n"); 755 }
717 }
718#endif /* !CONFIG_HIGHMEM64G */ 756#endif /* !CONFIG_HIGHMEM64G */
719#endif /* !CONFIG_HIGHMEM */ 757#endif /* !CONFIG_HIGHMEM */
720 } else { 758}
721 if (highmem_pages == -1) 759
722 highmem_pages = 0; 760/*
723#ifdef CONFIG_HIGHMEM 761 * Determine low and high memory ranges:
724 if (highmem_pages >= max_pfn) { 762 */
725 printk(KERN_ERR "highmem size specified (%uMB) is " 763void __init find_low_pfn_range(void)
726 "bigger than pages available (%luMB)!.\n", 764{
727 pages_to_mb(highmem_pages), 765 /* it could update max_pfn */
728 pages_to_mb(max_pfn)); 766
729 highmem_pages = 0; 767 if (max_pfn <= MAXMEM_PFN)
730 } 768 lowmem_pfn_init();
731 if (highmem_pages) { 769 else
732 if (max_low_pfn - highmem_pages < 770 highmem_pfn_init();
733 64*1024*1024/PAGE_SIZE){
734 printk(KERN_ERR "highmem size %uMB results in "
735 "smaller than 64MB lowmem, ignoring it.\n"
736 , pages_to_mb(highmem_pages));
737 highmem_pages = 0;
738 }
739 max_low_pfn -= highmem_pages;
740 }
741#else
742 if (highmem_pages)
743 printk(KERN_ERR "ignoring highmem size on non-highmem"
744 " kernel!\n");
745#endif
746 }
747} 771}
748 772
749#ifndef CONFIG_NEED_MULTIPLE_NODES 773#ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -826,10 +850,10 @@ static void __init find_early_table_space(unsigned long end, int use_pse)
826 unsigned long puds, pmds, ptes, tables, start; 850 unsigned long puds, pmds, ptes, tables, start;
827 851
828 puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; 852 puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
829 tables = PAGE_ALIGN(puds * sizeof(pud_t)); 853 tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
830 854
831 pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; 855 pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
832 tables += PAGE_ALIGN(pmds * sizeof(pmd_t)); 856 tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
833 857
834 if (use_pse) { 858 if (use_pse) {
835 unsigned long extra; 859 unsigned long extra;
@@ -840,10 +864,10 @@ static void __init find_early_table_space(unsigned long end, int use_pse)
840 } else 864 } else
841 ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; 865 ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
842 866
843 tables += PAGE_ALIGN(ptes * sizeof(pte_t)); 867 tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
844 868
845 /* for fixmap */ 869 /* for fixmap */
846 tables += PAGE_ALIGN(__end_of_fixed_addresses * sizeof(pte_t)); 870 tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
847 871
848 /* 872 /*
849 * RED-PEN putting page tables only on node 0 could 873 * RED-PEN putting page tables only on node 0 could
@@ -1193,45 +1217,6 @@ void mark_rodata_ro(void)
1193} 1217}
1194#endif 1218#endif
1195 1219
1196void free_init_pages(char *what, unsigned long begin, unsigned long end)
1197{
1198#ifdef CONFIG_DEBUG_PAGEALLOC
1199 /*
1200 * If debugging page accesses then do not free this memory but
1201 * mark them not present - any buggy init-section access will
1202 * create a kernel page fault:
1203 */
1204 printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
1205 begin, PAGE_ALIGN(end));
1206 set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
1207#else
1208 unsigned long addr;
1209
1210 /*
1211 * We just marked the kernel text read only above, now that
1212 * we are going to free part of that, we need to make that
1213 * writeable first.
1214 */
1215 set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
1216
1217 for (addr = begin; addr < end; addr += PAGE_SIZE) {
1218 ClearPageReserved(virt_to_page(addr));
1219 init_page_count(virt_to_page(addr));
1220 memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
1221 free_page(addr);
1222 totalram_pages++;
1223 }
1224 printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
1225#endif
1226}
1227
1228void free_initmem(void)
1229{
1230 free_init_pages("unused kernel memory",
1231 (unsigned long)(&__init_begin),
1232 (unsigned long)(&__init_end));
1233}
1234
1235#ifdef CONFIG_BLK_DEV_INITRD 1220#ifdef CONFIG_BLK_DEV_INITRD
1236void free_initrd_mem(unsigned long start, unsigned long end) 1221void free_initrd_mem(unsigned long start, unsigned long end)
1237{ 1222{