diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-01-27 06:01:51 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-01-27 06:01:51 -0500 |
commit | 3ddeb51d9c83931c1ca6abf76a38934c5a1ed918 (patch) | |
tree | fc2efb59d627135ea2199a8a68415b162646b121 /arch/x86/mm/init_32.c | |
parent | 5a611268b69f05262936dd177205acbce4471358 (diff) | |
parent | 5ee810072175042775e39bdd3eaaa68884c27805 (diff) |
Merge branch 'linus' into core/percpu
Conflicts:
arch/x86/kernel/setup_percpu.c
Diffstat (limited to 'arch/x86/mm/init_32.c')
-rw-r--r-- | arch/x86/mm/init_32.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 4a6989e47a53..00263bf07a88 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -137,6 +137,47 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) | |||
137 | return pte_offset_kernel(pmd, 0); | 137 | return pte_offset_kernel(pmd, 0); |
138 | } | 138 | } |
139 | 139 | ||
140 | static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd, | ||
141 | unsigned long vaddr, pte_t *lastpte) | ||
142 | { | ||
143 | #ifdef CONFIG_HIGHMEM | ||
144 | /* | ||
145 | * Something (early fixmap) may already have put a pte | ||
146 | * page here, which causes the page table allocation | ||
147 | * to become nonlinear. Attempt to fix it, and if it | ||
148 | * is still nonlinear then we have to bug. | ||
149 | */ | ||
150 | int pmd_idx_kmap_begin = fix_to_virt(FIX_KMAP_END) >> PMD_SHIFT; | ||
151 | int pmd_idx_kmap_end = fix_to_virt(FIX_KMAP_BEGIN) >> PMD_SHIFT; | ||
152 | |||
153 | if (pmd_idx_kmap_begin != pmd_idx_kmap_end | ||
154 | && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin | ||
155 | && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end | ||
156 | && ((__pa(pte) >> PAGE_SHIFT) < table_start | ||
157 | || (__pa(pte) >> PAGE_SHIFT) >= table_end)) { | ||
158 | pte_t *newpte; | ||
159 | int i; | ||
160 | |||
161 | BUG_ON(after_init_bootmem); | ||
162 | newpte = alloc_low_page(); | ||
163 | for (i = 0; i < PTRS_PER_PTE; i++) | ||
164 | set_pte(newpte + i, pte[i]); | ||
165 | |||
166 | paravirt_alloc_pte(&init_mm, __pa(newpte) >> PAGE_SHIFT); | ||
167 | set_pmd(pmd, __pmd(__pa(newpte)|_PAGE_TABLE)); | ||
168 | BUG_ON(newpte != pte_offset_kernel(pmd, 0)); | ||
169 | __flush_tlb_all(); | ||
170 | |||
171 | paravirt_release_pte(__pa(pte) >> PAGE_SHIFT); | ||
172 | pte = newpte; | ||
173 | } | ||
174 | BUG_ON(vaddr < fix_to_virt(FIX_KMAP_BEGIN - 1) | ||
175 | && vaddr > fix_to_virt(FIX_KMAP_END) | ||
176 | && lastpte && lastpte + PTRS_PER_PTE != pte); | ||
177 | #endif | ||
178 | return pte; | ||
179 | } | ||
180 | |||
140 | /* | 181 | /* |
141 | * This function initializes a certain range of kernel virtual memory | 182 | * This function initializes a certain range of kernel virtual memory |
142 | * with new bootmem page tables, everywhere page tables are missing in | 183 | * with new bootmem page tables, everywhere page tables are missing in |
@@ -153,6 +194,7 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base) | |||
153 | unsigned long vaddr; | 194 | unsigned long vaddr; |
154 | pgd_t *pgd; | 195 | pgd_t *pgd; |
155 | pmd_t *pmd; | 196 | pmd_t *pmd; |
197 | pte_t *pte = NULL; | ||
156 | 198 | ||
157 | vaddr = start; | 199 | vaddr = start; |
158 | pgd_idx = pgd_index(vaddr); | 200 | pgd_idx = pgd_index(vaddr); |
@@ -164,7 +206,8 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base) | |||
164 | pmd = pmd + pmd_index(vaddr); | 206 | pmd = pmd + pmd_index(vaddr); |
165 | for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); | 207 | for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); |
166 | pmd++, pmd_idx++) { | 208 | pmd++, pmd_idx++) { |
167 | one_page_table_init(pmd); | 209 | pte = page_table_kmap_check(one_page_table_init(pmd), |
210 | pmd, vaddr, pte); | ||
168 | 211 | ||
169 | vaddr += PMD_SIZE; | 212 | vaddr += PMD_SIZE; |
170 | } | 213 | } |
@@ -507,7 +550,6 @@ static void __init early_ioremap_page_table_range_init(pgd_t *pgd_base) | |||
507 | * Fixed mappings, only the page table structure has to be | 550 | * Fixed mappings, only the page table structure has to be |
508 | * created - mappings will be set by set_fixmap(): | 551 | * created - mappings will be set by set_fixmap(): |
509 | */ | 552 | */ |
510 | early_ioremap_clear(); | ||
511 | vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; | 553 | vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; |
512 | end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; | 554 | end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; |
513 | page_table_range_init(vaddr, end, pgd_base); | 555 | page_table_range_init(vaddr, end, pgd_base); |
@@ -800,7 +842,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse) | |||
800 | tables += PAGE_ALIGN(ptes * sizeof(pte_t)); | 842 | tables += PAGE_ALIGN(ptes * sizeof(pte_t)); |
801 | 843 | ||
802 | /* for fixmap */ | 844 | /* for fixmap */ |
803 | tables += PAGE_SIZE * 2; | 845 | tables += PAGE_ALIGN(__end_of_fixed_addresses * sizeof(pte_t)); |
804 | 846 | ||
805 | /* | 847 | /* |
806 | * RED-PEN putting page tables only on node 0 could | 848 | * RED-PEN putting page tables only on node 0 could |