diff options
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r-- | arch/x86/mm/init_64.c | 571 |
1 files changed, 414 insertions, 157 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 32ba13b0f818..306049edd553 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/swap.h> | 18 | #include <linux/swap.h> |
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/initrd.h> | ||
21 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
22 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
23 | #include <linux/proc_fs.h> | 24 | #include <linux/proc_fs.h> |
@@ -47,6 +48,14 @@ | |||
47 | #include <asm/numa.h> | 48 | #include <asm/numa.h> |
48 | #include <asm/cacheflush.h> | 49 | #include <asm/cacheflush.h> |
49 | 50 | ||
51 | /* | ||
52 | * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. | ||
53 | * The direct mapping extends to max_pfn_mapped, so that we can directly access | ||
54 | * apertures, ACPI and other tables without having to play with fixmaps. | ||
55 | */ | ||
56 | unsigned long max_low_pfn_mapped; | ||
57 | unsigned long max_pfn_mapped; | ||
58 | |||
50 | static unsigned long dma_reserve __initdata; | 59 | static unsigned long dma_reserve __initdata; |
51 | 60 | ||
52 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 61 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
@@ -135,26 +144,17 @@ static __init void *spp_getpage(void) | |||
135 | return ptr; | 144 | return ptr; |
136 | } | 145 | } |
137 | 146 | ||
138 | static void | 147 | void |
139 | set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) | 148 | set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) |
140 | { | 149 | { |
141 | pgd_t *pgd; | ||
142 | pud_t *pud; | 150 | pud_t *pud; |
143 | pmd_t *pmd; | 151 | pmd_t *pmd; |
144 | pte_t *pte, new_pte; | 152 | pte_t *pte; |
145 | |||
146 | pr_debug("set_pte_phys %lx to %lx\n", vaddr, phys); | ||
147 | 153 | ||
148 | pgd = pgd_offset_k(vaddr); | 154 | pud = pud_page + pud_index(vaddr); |
149 | if (pgd_none(*pgd)) { | ||
150 | printk(KERN_ERR | ||
151 | "PGD FIXMAP MISSING, it should be setup in head.S!\n"); | ||
152 | return; | ||
153 | } | ||
154 | pud = pud_offset(pgd, vaddr); | ||
155 | if (pud_none(*pud)) { | 155 | if (pud_none(*pud)) { |
156 | pmd = (pmd_t *) spp_getpage(); | 156 | pmd = (pmd_t *) spp_getpage(); |
157 | set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); | 157 | pud_populate(&init_mm, pud, pmd); |
158 | if (pmd != pmd_offset(pud, 0)) { | 158 | if (pmd != pmd_offset(pud, 0)) { |
159 | printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", | 159 | printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", |
160 | pmd, pmd_offset(pud, 0)); | 160 | pmd, pmd_offset(pud, 0)); |
@@ -164,13 +164,12 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) | |||
164 | pmd = pmd_offset(pud, vaddr); | 164 | pmd = pmd_offset(pud, vaddr); |
165 | if (pmd_none(*pmd)) { | 165 | if (pmd_none(*pmd)) { |
166 | pte = (pte_t *) spp_getpage(); | 166 | pte = (pte_t *) spp_getpage(); |
167 | set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); | 167 | pmd_populate_kernel(&init_mm, pmd, pte); |
168 | if (pte != pte_offset_kernel(pmd, 0)) { | 168 | if (pte != pte_offset_kernel(pmd, 0)) { |
169 | printk(KERN_ERR "PAGETABLE BUG #02!\n"); | 169 | printk(KERN_ERR "PAGETABLE BUG #02!\n"); |
170 | return; | 170 | return; |
171 | } | 171 | } |
172 | } | 172 | } |
173 | new_pte = pfn_pte(phys >> PAGE_SHIFT, prot); | ||
174 | 173 | ||
175 | pte = pte_offset_kernel(pmd, vaddr); | 174 | pte = pte_offset_kernel(pmd, vaddr); |
176 | if (!pte_none(*pte) && pte_val(new_pte) && | 175 | if (!pte_none(*pte) && pte_val(new_pte) && |
@@ -185,6 +184,64 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) | |||
185 | __flush_tlb_one(vaddr); | 184 | __flush_tlb_one(vaddr); |
186 | } | 185 | } |
187 | 186 | ||
187 | void | ||
188 | set_pte_vaddr(unsigned long vaddr, pte_t pteval) | ||
189 | { | ||
190 | pgd_t *pgd; | ||
191 | pud_t *pud_page; | ||
192 | |||
193 | pr_debug("set_pte_vaddr %lx to %lx\n", vaddr, native_pte_val(pteval)); | ||
194 | |||
195 | pgd = pgd_offset_k(vaddr); | ||
196 | if (pgd_none(*pgd)) { | ||
197 | printk(KERN_ERR | ||
198 | "PGD FIXMAP MISSING, it should be setup in head.S!\n"); | ||
199 | return; | ||
200 | } | ||
201 | pud_page = (pud_t*)pgd_page_vaddr(*pgd); | ||
202 | set_pte_vaddr_pud(pud_page, vaddr, pteval); | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * Create large page table mappings for a range of physical addresses. | ||
207 | */ | ||
208 | static void __init __init_extra_mapping(unsigned long phys, unsigned long size, | ||
209 | pgprot_t prot) | ||
210 | { | ||
211 | pgd_t *pgd; | ||
212 | pud_t *pud; | ||
213 | pmd_t *pmd; | ||
214 | |||
215 | BUG_ON((phys & ~PMD_MASK) || (size & ~PMD_MASK)); | ||
216 | for (; size; phys += PMD_SIZE, size -= PMD_SIZE) { | ||
217 | pgd = pgd_offset_k((unsigned long)__va(phys)); | ||
218 | if (pgd_none(*pgd)) { | ||
219 | pud = (pud_t *) spp_getpage(); | ||
220 | set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE | | ||
221 | _PAGE_USER)); | ||
222 | } | ||
223 | pud = pud_offset(pgd, (unsigned long)__va(phys)); | ||
224 | if (pud_none(*pud)) { | ||
225 | pmd = (pmd_t *) spp_getpage(); | ||
226 | set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | | ||
227 | _PAGE_USER)); | ||
228 | } | ||
229 | pmd = pmd_offset(pud, phys); | ||
230 | BUG_ON(!pmd_none(*pmd)); | ||
231 | set_pmd(pmd, __pmd(phys | pgprot_val(prot))); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | void __init init_extra_mapping_wb(unsigned long phys, unsigned long size) | ||
236 | { | ||
237 | __init_extra_mapping(phys, size, PAGE_KERNEL_LARGE); | ||
238 | } | ||
239 | |||
240 | void __init init_extra_mapping_uc(unsigned long phys, unsigned long size) | ||
241 | { | ||
242 | __init_extra_mapping(phys, size, PAGE_KERNEL_LARGE_NOCACHE); | ||
243 | } | ||
244 | |||
188 | /* | 245 | /* |
189 | * The head.S code sets up the kernel high mapping: | 246 | * The head.S code sets up the kernel high mapping: |
190 | * | 247 | * |
@@ -206,27 +263,16 @@ void __init cleanup_highmap(void) | |||
206 | pmd_t *last_pmd = pmd + PTRS_PER_PMD; | 263 | pmd_t *last_pmd = pmd + PTRS_PER_PMD; |
207 | 264 | ||
208 | for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) { | 265 | for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) { |
209 | if (!pmd_present(*pmd)) | 266 | if (pmd_none(*pmd)) |
210 | continue; | 267 | continue; |
211 | if (vaddr < (unsigned long) _text || vaddr > end) | 268 | if (vaddr < (unsigned long) _text || vaddr > end) |
212 | set_pmd(pmd, __pmd(0)); | 269 | set_pmd(pmd, __pmd(0)); |
213 | } | 270 | } |
214 | } | 271 | } |
215 | 272 | ||
216 | /* NOTE: this is meant to be run only at boot */ | ||
217 | void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) | ||
218 | { | ||
219 | unsigned long address = __fix_to_virt(idx); | ||
220 | |||
221 | if (idx >= __end_of_fixed_addresses) { | ||
222 | printk(KERN_ERR "Invalid __set_fixmap\n"); | ||
223 | return; | ||
224 | } | ||
225 | set_pte_phys(address, phys, prot); | ||
226 | } | ||
227 | |||
228 | static unsigned long __initdata table_start; | 273 | static unsigned long __initdata table_start; |
229 | static unsigned long __meminitdata table_end; | 274 | static unsigned long __meminitdata table_end; |
275 | static unsigned long __meminitdata table_top; | ||
230 | 276 | ||
231 | static __meminit void *alloc_low_page(unsigned long *phys) | 277 | static __meminit void *alloc_low_page(unsigned long *phys) |
232 | { | 278 | { |
@@ -240,7 +286,7 @@ static __meminit void *alloc_low_page(unsigned long *phys) | |||
240 | return adr; | 286 | return adr; |
241 | } | 287 | } |
242 | 288 | ||
243 | if (pfn >= end_pfn) | 289 | if (pfn >= table_top) |
244 | panic("alloc_low_page: ran out of memory"); | 290 | panic("alloc_low_page: ran out of memory"); |
245 | 291 | ||
246 | adr = early_ioremap(pfn * PAGE_SIZE, PAGE_SIZE); | 292 | adr = early_ioremap(pfn * PAGE_SIZE, PAGE_SIZE); |
@@ -257,65 +303,61 @@ static __meminit void unmap_low_page(void *adr) | |||
257 | early_iounmap(adr, PAGE_SIZE); | 303 | early_iounmap(adr, PAGE_SIZE); |
258 | } | 304 | } |
259 | 305 | ||
260 | /* Must run before zap_low_mappings */ | 306 | static unsigned long __meminit |
261 | __meminit void *early_ioremap(unsigned long addr, unsigned long size) | 307 | phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end) |
262 | { | 308 | { |
263 | pmd_t *pmd, *last_pmd; | 309 | unsigned pages = 0; |
264 | unsigned long vaddr; | 310 | unsigned long last_map_addr = end; |
265 | int i, pmds; | 311 | int i; |
312 | |||
313 | pte_t *pte = pte_page + pte_index(addr); | ||
266 | 314 | ||
267 | pmds = ((addr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE; | 315 | for(i = pte_index(addr); i < PTRS_PER_PTE; i++, addr += PAGE_SIZE, pte++) { |
268 | vaddr = __START_KERNEL_map; | ||
269 | pmd = level2_kernel_pgt; | ||
270 | last_pmd = level2_kernel_pgt + PTRS_PER_PMD - 1; | ||
271 | 316 | ||
272 | for (; pmd <= last_pmd; pmd++, vaddr += PMD_SIZE) { | 317 | if (addr >= end) { |
273 | for (i = 0; i < pmds; i++) { | 318 | if (!after_bootmem) { |
274 | if (pmd_present(pmd[i])) | 319 | for(; i < PTRS_PER_PTE; i++, pte++) |
275 | goto continue_outer_loop; | 320 | set_pte(pte, __pte(0)); |
321 | } | ||
322 | break; | ||
276 | } | 323 | } |
277 | vaddr += addr & ~PMD_MASK; | ||
278 | addr &= PMD_MASK; | ||
279 | 324 | ||
280 | for (i = 0; i < pmds; i++, addr += PMD_SIZE) | 325 | if (pte_val(*pte)) |
281 | set_pmd(pmd+i, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC)); | 326 | continue; |
282 | __flush_tlb_all(); | ||
283 | 327 | ||
284 | return (void *)vaddr; | 328 | if (0) |
285 | continue_outer_loop: | 329 | printk(" pte=%p addr=%lx pte=%016lx\n", |
286 | ; | 330 | pte, addr, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL).pte); |
331 | set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL)); | ||
332 | last_map_addr = (addr & PAGE_MASK) + PAGE_SIZE; | ||
333 | pages++; | ||
287 | } | 334 | } |
288 | printk(KERN_ERR "early_ioremap(0x%lx, %lu) failed\n", addr, size); | 335 | update_page_count(PG_LEVEL_4K, pages); |
289 | 336 | ||
290 | return NULL; | 337 | return last_map_addr; |
291 | } | 338 | } |
292 | 339 | ||
293 | /* | 340 | static unsigned long __meminit |
294 | * To avoid virtual aliases later: | 341 | phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end) |
295 | */ | ||
296 | __meminit void early_iounmap(void *addr, unsigned long size) | ||
297 | { | 342 | { |
298 | unsigned long vaddr; | 343 | pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd); |
299 | pmd_t *pmd; | ||
300 | int i, pmds; | ||
301 | |||
302 | vaddr = (unsigned long)addr; | ||
303 | pmds = ((vaddr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE; | ||
304 | pmd = level2_kernel_pgt + pmd_index(vaddr); | ||
305 | 344 | ||
306 | for (i = 0; i < pmds; i++) | 345 | return phys_pte_init(pte, address, end); |
307 | pmd_clear(pmd + i); | ||
308 | |||
309 | __flush_tlb_all(); | ||
310 | } | 346 | } |
311 | 347 | ||
312 | static unsigned long __meminit | 348 | static unsigned long __meminit |
313 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) | 349 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, |
350 | unsigned long page_size_mask) | ||
314 | { | 351 | { |
352 | unsigned long pages = 0; | ||
353 | unsigned long last_map_addr = end; | ||
354 | |||
315 | int i = pmd_index(address); | 355 | int i = pmd_index(address); |
316 | 356 | ||
317 | for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) { | 357 | for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) { |
358 | unsigned long pte_phys; | ||
318 | pmd_t *pmd = pmd_page + pmd_index(address); | 359 | pmd_t *pmd = pmd_page + pmd_index(address); |
360 | pte_t *pte; | ||
319 | 361 | ||
320 | if (address >= end) { | 362 | if (address >= end) { |
321 | if (!after_bootmem) { | 363 | if (!after_bootmem) { |
@@ -325,31 +367,50 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) | |||
325 | break; | 367 | break; |
326 | } | 368 | } |
327 | 369 | ||
328 | if (pmd_val(*pmd)) | 370 | if (pmd_val(*pmd)) { |
371 | if (!pmd_large(*pmd)) | ||
372 | last_map_addr = phys_pte_update(pmd, address, | ||
373 | end); | ||
374 | continue; | ||
375 | } | ||
376 | |||
377 | if (page_size_mask & (1<<PG_LEVEL_2M)) { | ||
378 | pages++; | ||
379 | set_pte((pte_t *)pmd, | ||
380 | pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); | ||
381 | last_map_addr = (address & PMD_MASK) + PMD_SIZE; | ||
329 | continue; | 382 | continue; |
383 | } | ||
330 | 384 | ||
331 | set_pte((pte_t *)pmd, | 385 | pte = alloc_low_page(&pte_phys); |
332 | pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); | 386 | last_map_addr = phys_pte_init(pte, address, end); |
387 | unmap_low_page(pte); | ||
388 | |||
389 | pmd_populate_kernel(&init_mm, pmd, __va(pte_phys)); | ||
333 | } | 390 | } |
334 | return address; | 391 | update_page_count(PG_LEVEL_2M, pages); |
392 | return last_map_addr; | ||
335 | } | 393 | } |
336 | 394 | ||
337 | static unsigned long __meminit | 395 | static unsigned long __meminit |
338 | phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) | 396 | phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end, |
397 | unsigned long page_size_mask) | ||
339 | { | 398 | { |
340 | pmd_t *pmd = pmd_offset(pud, 0); | 399 | pmd_t *pmd = pmd_offset(pud, 0); |
341 | unsigned long last_map_addr; | 400 | unsigned long last_map_addr; |
342 | 401 | ||
343 | spin_lock(&init_mm.page_table_lock); | 402 | spin_lock(&init_mm.page_table_lock); |
344 | last_map_addr = phys_pmd_init(pmd, address, end); | 403 | last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask); |
345 | spin_unlock(&init_mm.page_table_lock); | 404 | spin_unlock(&init_mm.page_table_lock); |
346 | __flush_tlb_all(); | 405 | __flush_tlb_all(); |
347 | return last_map_addr; | 406 | return last_map_addr; |
348 | } | 407 | } |
349 | 408 | ||
350 | static unsigned long __meminit | 409 | static unsigned long __meminit |
351 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | 410 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, |
411 | unsigned long page_size_mask) | ||
352 | { | 412 | { |
413 | unsigned long pages = 0; | ||
353 | unsigned long last_map_addr = end; | 414 | unsigned long last_map_addr = end; |
354 | int i = pud_index(addr); | 415 | int i = pud_index(addr); |
355 | 416 | ||
@@ -369,11 +430,13 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | |||
369 | 430 | ||
370 | if (pud_val(*pud)) { | 431 | if (pud_val(*pud)) { |
371 | if (!pud_large(*pud)) | 432 | if (!pud_large(*pud)) |
372 | last_map_addr = phys_pmd_update(pud, addr, end); | 433 | last_map_addr = phys_pmd_update(pud, addr, end, |
434 | page_size_mask); | ||
373 | continue; | 435 | continue; |
374 | } | 436 | } |
375 | 437 | ||
376 | if (direct_gbpages) { | 438 | if (page_size_mask & (1<<PG_LEVEL_1G)) { |
439 | pages++; | ||
377 | set_pte((pte_t *)pud, | 440 | set_pte((pte_t *)pud, |
378 | pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); | 441 | pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); |
379 | last_map_addr = (addr & PUD_MASK) + PUD_SIZE; | 442 | last_map_addr = (addr & PUD_MASK) + PUD_SIZE; |
@@ -383,27 +446,50 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | |||
383 | pmd = alloc_low_page(&pmd_phys); | 446 | pmd = alloc_low_page(&pmd_phys); |
384 | 447 | ||
385 | spin_lock(&init_mm.page_table_lock); | 448 | spin_lock(&init_mm.page_table_lock); |
386 | set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); | 449 | last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask); |
387 | last_map_addr = phys_pmd_init(pmd, addr, end); | 450 | unmap_low_page(pmd); |
451 | pud_populate(&init_mm, pud, __va(pmd_phys)); | ||
388 | spin_unlock(&init_mm.page_table_lock); | 452 | spin_unlock(&init_mm.page_table_lock); |
389 | 453 | ||
390 | unmap_low_page(pmd); | ||
391 | } | 454 | } |
392 | __flush_tlb_all(); | 455 | __flush_tlb_all(); |
456 | update_page_count(PG_LEVEL_1G, pages); | ||
393 | 457 | ||
394 | return last_map_addr >> PAGE_SHIFT; | 458 | return last_map_addr; |
459 | } | ||
460 | |||
461 | static unsigned long __meminit | ||
462 | phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
463 | unsigned long page_size_mask) | ||
464 | { | ||
465 | pud_t *pud; | ||
466 | |||
467 | pud = (pud_t *)pgd_page_vaddr(*pgd); | ||
468 | |||
469 | return phys_pud_init(pud, addr, end, page_size_mask); | ||
395 | } | 470 | } |
396 | 471 | ||
397 | static void __init find_early_table_space(unsigned long end) | 472 | static void __init find_early_table_space(unsigned long end) |
398 | { | 473 | { |
399 | unsigned long puds, pmds, tables, start; | 474 | unsigned long puds, pmds, ptes, tables, start; |
400 | 475 | ||
401 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; | 476 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; |
402 | tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); | 477 | tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); |
403 | if (!direct_gbpages) { | 478 | if (direct_gbpages) { |
479 | unsigned long extra; | ||
480 | extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); | ||
481 | pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; | ||
482 | } else | ||
404 | pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; | 483 | pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; |
405 | tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); | 484 | tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); |
406 | } | 485 | |
486 | if (cpu_has_pse) { | ||
487 | unsigned long extra; | ||
488 | extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); | ||
489 | ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
490 | } else | ||
491 | ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
492 | tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE); | ||
407 | 493 | ||
408 | /* | 494 | /* |
409 | * RED-PEN putting page tables only on node 0 could | 495 | * RED-PEN putting page tables only on node 0 could |
@@ -417,10 +503,10 @@ static void __init find_early_table_space(unsigned long end) | |||
417 | 503 | ||
418 | table_start >>= PAGE_SHIFT; | 504 | table_start >>= PAGE_SHIFT; |
419 | table_end = table_start; | 505 | table_end = table_start; |
506 | table_top = table_start + (tables >> PAGE_SHIFT); | ||
420 | 507 | ||
421 | early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n", | 508 | printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n", |
422 | end, table_start << PAGE_SHIFT, | 509 | end, table_start << PAGE_SHIFT, table_top << PAGE_SHIFT); |
423 | (table_start << PAGE_SHIFT) + tables); | ||
424 | } | 510 | } |
425 | 511 | ||
426 | static void __init init_gbpages(void) | 512 | static void __init init_gbpages(void) |
@@ -431,7 +517,7 @@ static void __init init_gbpages(void) | |||
431 | direct_gbpages = 0; | 517 | direct_gbpages = 0; |
432 | } | 518 | } |
433 | 519 | ||
434 | #ifdef CONFIG_MEMTEST_BOOTPARAM | 520 | #ifdef CONFIG_MEMTEST |
435 | 521 | ||
436 | static void __init memtest(unsigned long start_phys, unsigned long size, | 522 | static void __init memtest(unsigned long start_phys, unsigned long size, |
437 | unsigned pattern) | 523 | unsigned pattern) |
@@ -493,7 +579,8 @@ static void __init memtest(unsigned long start_phys, unsigned long size, | |||
493 | 579 | ||
494 | } | 580 | } |
495 | 581 | ||
496 | static int memtest_pattern __initdata = CONFIG_MEMTEST_BOOTPARAM_VALUE; | 582 | /* default is disabled */ |
583 | static int memtest_pattern __initdata; | ||
497 | 584 | ||
498 | static int __init parse_memtest(char *arg) | 585 | static int __init parse_memtest(char *arg) |
499 | { | 586 | { |
@@ -506,7 +593,7 @@ early_param("memtest", parse_memtest); | |||
506 | 593 | ||
507 | static void __init early_memtest(unsigned long start, unsigned long end) | 594 | static void __init early_memtest(unsigned long start, unsigned long end) |
508 | { | 595 | { |
509 | unsigned long t_start, t_size; | 596 | u64 t_start, t_size; |
510 | unsigned pattern; | 597 | unsigned pattern; |
511 | 598 | ||
512 | if (!memtest_pattern) | 599 | if (!memtest_pattern) |
@@ -525,8 +612,9 @@ static void __init early_memtest(unsigned long start, unsigned long end) | |||
525 | if (t_start + t_size > end) | 612 | if (t_start + t_size > end) |
526 | t_size = end - t_start; | 613 | t_size = end - t_start; |
527 | 614 | ||
528 | printk(KERN_CONT "\n %016lx - %016lx pattern %d", | 615 | printk(KERN_CONT "\n %016llx - %016llx pattern %d", |
529 | t_start, t_start + t_size, pattern); | 616 | (unsigned long long)t_start, |
617 | (unsigned long long)t_start + t_size, pattern); | ||
530 | 618 | ||
531 | memtest(t_start, t_size, pattern); | 619 | memtest(t_start, t_size, pattern); |
532 | 620 | ||
@@ -541,15 +629,85 @@ static void __init early_memtest(unsigned long start, unsigned long end) | |||
541 | } | 629 | } |
542 | #endif | 630 | #endif |
543 | 631 | ||
632 | static unsigned long __init kernel_physical_mapping_init(unsigned long start, | ||
633 | unsigned long end, | ||
634 | unsigned long page_size_mask) | ||
635 | { | ||
636 | |||
637 | unsigned long next, last_map_addr = end; | ||
638 | |||
639 | start = (unsigned long)__va(start); | ||
640 | end = (unsigned long)__va(end); | ||
641 | |||
642 | for (; start < end; start = next) { | ||
643 | pgd_t *pgd = pgd_offset_k(start); | ||
644 | unsigned long pud_phys; | ||
645 | pud_t *pud; | ||
646 | |||
647 | next = (start + PGDIR_SIZE) & PGDIR_MASK; | ||
648 | if (next > end) | ||
649 | next = end; | ||
650 | |||
651 | if (pgd_val(*pgd)) { | ||
652 | last_map_addr = phys_pud_update(pgd, __pa(start), | ||
653 | __pa(end), page_size_mask); | ||
654 | continue; | ||
655 | } | ||
656 | |||
657 | if (after_bootmem) | ||
658 | pud = pud_offset(pgd, start & PGDIR_MASK); | ||
659 | else | ||
660 | pud = alloc_low_page(&pud_phys); | ||
661 | |||
662 | last_map_addr = phys_pud_init(pud, __pa(start), __pa(next), | ||
663 | page_size_mask); | ||
664 | unmap_low_page(pud); | ||
665 | pgd_populate(&init_mm, pgd_offset_k(start), | ||
666 | __va(pud_phys)); | ||
667 | } | ||
668 | |||
669 | return last_map_addr; | ||
670 | } | ||
671 | |||
672 | struct map_range { | ||
673 | unsigned long start; | ||
674 | unsigned long end; | ||
675 | unsigned page_size_mask; | ||
676 | }; | ||
677 | |||
678 | #define NR_RANGE_MR 5 | ||
679 | |||
680 | static int save_mr(struct map_range *mr, int nr_range, | ||
681 | unsigned long start_pfn, unsigned long end_pfn, | ||
682 | unsigned long page_size_mask) | ||
683 | { | ||
684 | |||
685 | if (start_pfn < end_pfn) { | ||
686 | if (nr_range >= NR_RANGE_MR) | ||
687 | panic("run out of range for init_memory_mapping\n"); | ||
688 | mr[nr_range].start = start_pfn<<PAGE_SHIFT; | ||
689 | mr[nr_range].end = end_pfn<<PAGE_SHIFT; | ||
690 | mr[nr_range].page_size_mask = page_size_mask; | ||
691 | nr_range++; | ||
692 | } | ||
693 | |||
694 | return nr_range; | ||
695 | } | ||
696 | |||
544 | /* | 697 | /* |
545 | * Setup the direct mapping of the physical memory at PAGE_OFFSET. | 698 | * Setup the direct mapping of the physical memory at PAGE_OFFSET. |
546 | * This runs before bootmem is initialized and gets pages directly from | 699 | * This runs before bootmem is initialized and gets pages directly from |
547 | * the physical memory. To access them they are temporarily mapped. | 700 | * the physical memory. To access them they are temporarily mapped. |
548 | */ | 701 | */ |
549 | unsigned long __init_refok init_memory_mapping(unsigned long start, unsigned long end) | 702 | unsigned long __init_refok init_memory_mapping(unsigned long start, |
703 | unsigned long end) | ||
550 | { | 704 | { |
551 | unsigned long next, last_map_addr = end; | 705 | unsigned long last_map_addr = 0; |
552 | unsigned long start_phys = start, end_phys = end; | 706 | unsigned long page_size_mask = 0; |
707 | unsigned long start_pfn, end_pfn; | ||
708 | |||
709 | struct map_range mr[NR_RANGE_MR]; | ||
710 | int nr_range, i; | ||
553 | 711 | ||
554 | printk(KERN_INFO "init_memory_mapping\n"); | 712 | printk(KERN_INFO "init_memory_mapping\n"); |
555 | 713 | ||
@@ -560,48 +718,115 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, unsigned lon | |||
560 | * memory mapped. Unfortunately this is done currently before the | 718 | * memory mapped. Unfortunately this is done currently before the |
561 | * nodes are discovered. | 719 | * nodes are discovered. |
562 | */ | 720 | */ |
563 | if (!after_bootmem) { | 721 | if (!after_bootmem) |
564 | init_gbpages(); | 722 | init_gbpages(); |
565 | find_early_table_space(end); | 723 | |
724 | if (direct_gbpages) | ||
725 | page_size_mask |= 1 << PG_LEVEL_1G; | ||
726 | if (cpu_has_pse) | ||
727 | page_size_mask |= 1 << PG_LEVEL_2M; | ||
728 | |||
729 | memset(mr, 0, sizeof(mr)); | ||
730 | nr_range = 0; | ||
731 | |||
732 | /* head if not big page alignment ?*/ | ||
733 | start_pfn = start >> PAGE_SHIFT; | ||
734 | end_pfn = ((start + (PMD_SIZE - 1)) >> PMD_SHIFT) | ||
735 | << (PMD_SHIFT - PAGE_SHIFT); | ||
736 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0); | ||
737 | |||
738 | /* big page (2M) range*/ | ||
739 | start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT) | ||
740 | << (PMD_SHIFT - PAGE_SHIFT); | ||
741 | end_pfn = ((start + (PUD_SIZE - 1))>>PUD_SHIFT) | ||
742 | << (PUD_SHIFT - PAGE_SHIFT); | ||
743 | if (end_pfn > ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT))) | ||
744 | end_pfn = ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT)); | ||
745 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, | ||
746 | page_size_mask & (1<<PG_LEVEL_2M)); | ||
747 | |||
748 | /* big page (1G) range */ | ||
749 | start_pfn = end_pfn; | ||
750 | end_pfn = (end>>PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT); | ||
751 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, | ||
752 | page_size_mask & | ||
753 | ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G))); | ||
754 | |||
755 | /* tail is not big page (1G) alignment */ | ||
756 | start_pfn = end_pfn; | ||
757 | end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT); | ||
758 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, | ||
759 | page_size_mask & (1<<PG_LEVEL_2M)); | ||
760 | |||
761 | /* tail is not big page (2M) alignment */ | ||
762 | start_pfn = end_pfn; | ||
763 | end_pfn = end>>PAGE_SHIFT; | ||
764 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0); | ||
765 | |||
766 | /* try to merge same page size and continuous */ | ||
767 | for (i = 0; nr_range > 1 && i < nr_range - 1; i++) { | ||
768 | unsigned long old_start; | ||
769 | if (mr[i].end != mr[i+1].start || | ||
770 | mr[i].page_size_mask != mr[i+1].page_size_mask) | ||
771 | continue; | ||
772 | /* move it */ | ||
773 | old_start = mr[i].start; | ||
774 | memmove(&mr[i], &mr[i+1], | ||
775 | (nr_range - 1 - i) * sizeof (struct map_range)); | ||
776 | mr[i].start = old_start; | ||
777 | nr_range--; | ||
566 | } | 778 | } |
567 | 779 | ||
568 | start = (unsigned long)__va(start); | 780 | for (i = 0; i < nr_range; i++) |
569 | end = (unsigned long)__va(end); | 781 | printk(KERN_DEBUG " %010lx - %010lx page %s\n", |
782 | mr[i].start, mr[i].end, | ||
783 | (mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":( | ||
784 | (mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k")); | ||
570 | 785 | ||
571 | for (; start < end; start = next) { | 786 | if (!after_bootmem) |
572 | pgd_t *pgd = pgd_offset_k(start); | 787 | find_early_table_space(end); |
573 | unsigned long pud_phys; | ||
574 | pud_t *pud; | ||
575 | |||
576 | if (after_bootmem) | ||
577 | pud = pud_offset(pgd, start & PGDIR_MASK); | ||
578 | else | ||
579 | pud = alloc_low_page(&pud_phys); | ||
580 | 788 | ||
581 | next = start + PGDIR_SIZE; | 789 | for (i = 0; i < nr_range; i++) |
582 | if (next > end) | 790 | last_map_addr = kernel_physical_mapping_init( |
583 | next = end; | 791 | mr[i].start, mr[i].end, |
584 | last_map_addr = phys_pud_init(pud, __pa(start), __pa(next)); | 792 | mr[i].page_size_mask); |
585 | if (!after_bootmem) | ||
586 | set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); | ||
587 | unmap_low_page(pud); | ||
588 | } | ||
589 | 793 | ||
590 | if (!after_bootmem) | 794 | if (!after_bootmem) |
591 | mmu_cr4_features = read_cr4(); | 795 | mmu_cr4_features = read_cr4(); |
592 | __flush_tlb_all(); | 796 | __flush_tlb_all(); |
593 | 797 | ||
594 | if (!after_bootmem) | 798 | if (!after_bootmem && table_end > table_start) |
595 | reserve_early(table_start << PAGE_SHIFT, | 799 | reserve_early(table_start << PAGE_SHIFT, |
596 | table_end << PAGE_SHIFT, "PGTABLE"); | 800 | table_end << PAGE_SHIFT, "PGTABLE"); |
597 | 801 | ||
802 | printk(KERN_INFO "last_map_addr: %lx end: %lx\n", | ||
803 | last_map_addr, end); | ||
804 | |||
598 | if (!after_bootmem) | 805 | if (!after_bootmem) |
599 | early_memtest(start_phys, end_phys); | 806 | early_memtest(start, end); |
600 | 807 | ||
601 | return last_map_addr; | 808 | return last_map_addr >> PAGE_SHIFT; |
602 | } | 809 | } |
603 | 810 | ||
604 | #ifndef CONFIG_NUMA | 811 | #ifndef CONFIG_NUMA |
812 | void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn) | ||
813 | { | ||
814 | unsigned long bootmap_size, bootmap; | ||
815 | |||
816 | bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; | ||
817 | bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size, | ||
818 | PAGE_SIZE); | ||
819 | if (bootmap == -1L) | ||
820 | panic("Cannot find bootmem map of size %ld\n", bootmap_size); | ||
821 | /* don't touch min_low_pfn */ | ||
822 | bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT, | ||
823 | 0, end_pfn); | ||
824 | e820_register_active_regions(0, start_pfn, end_pfn); | ||
825 | free_bootmem_with_active_regions(0, end_pfn); | ||
826 | early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT); | ||
827 | reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT); | ||
828 | } | ||
829 | |||
605 | void __init paging_init(void) | 830 | void __init paging_init(void) |
606 | { | 831 | { |
607 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 832 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
@@ -609,9 +834,9 @@ void __init paging_init(void) | |||
609 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); | 834 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); |
610 | max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; | 835 | max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; |
611 | max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; | 836 | max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; |
612 | max_zone_pfns[ZONE_NORMAL] = end_pfn; | 837 | max_zone_pfns[ZONE_NORMAL] = max_pfn; |
613 | 838 | ||
614 | memory_present(0, 0, end_pfn); | 839 | memory_present(0, 0, max_pfn); |
615 | sparse_init(); | 840 | sparse_init(); |
616 | free_area_init_nodes(max_zone_pfns); | 841 | free_area_init_nodes(max_zone_pfns); |
617 | } | 842 | } |
@@ -693,8 +918,8 @@ void __init mem_init(void) | |||
693 | #else | 918 | #else |
694 | totalram_pages = free_all_bootmem(); | 919 | totalram_pages = free_all_bootmem(); |
695 | #endif | 920 | #endif |
696 | reservedpages = end_pfn - totalram_pages - | 921 | reservedpages = max_pfn - totalram_pages - |
697 | absent_pages_in_range(0, end_pfn); | 922 | absent_pages_in_range(0, max_pfn); |
698 | after_bootmem = 1; | 923 | after_bootmem = 1; |
699 | 924 | ||
700 | codesize = (unsigned long) &_etext - (unsigned long) &_text; | 925 | codesize = (unsigned long) &_etext - (unsigned long) &_text; |
@@ -713,7 +938,7 @@ void __init mem_init(void) | |||
713 | printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " | 938 | printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " |
714 | "%ldk reserved, %ldk data, %ldk init)\n", | 939 | "%ldk reserved, %ldk data, %ldk init)\n", |
715 | (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), | 940 | (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), |
716 | end_pfn << (PAGE_SHIFT-10), | 941 | max_pfn << (PAGE_SHIFT-10), |
717 | codesize >> 10, | 942 | codesize >> 10, |
718 | reservedpages << (PAGE_SHIFT-10), | 943 | reservedpages << (PAGE_SHIFT-10), |
719 | datasize >> 10, | 944 | datasize >> 10, |
@@ -766,6 +991,13 @@ EXPORT_SYMBOL_GPL(rodata_test_data); | |||
766 | void mark_rodata_ro(void) | 991 | void mark_rodata_ro(void) |
767 | { | 992 | { |
768 | unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); | 993 | unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); |
994 | unsigned long rodata_start = | ||
995 | ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; | ||
996 | |||
997 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
998 | /* Dynamic tracing modifies the kernel text section */ | ||
999 | start = rodata_start; | ||
1000 | #endif | ||
769 | 1001 | ||
770 | printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", | 1002 | printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", |
771 | (end - start) >> 10); | 1003 | (end - start) >> 10); |
@@ -775,8 +1007,7 @@ void mark_rodata_ro(void) | |||
775 | * The rodata section (but not the kernel text!) should also be | 1007 | * The rodata section (but not the kernel text!) should also be |
776 | * not-executable. | 1008 | * not-executable. |
777 | */ | 1009 | */ |
778 | start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; | 1010 | set_memory_nx(rodata_start, (end - rodata_start) >> PAGE_SHIFT); |
779 | set_memory_nx(start, (end - start) >> PAGE_SHIFT); | ||
780 | 1011 | ||
781 | rodata_test(); | 1012 | rodata_test(); |
782 | 1013 | ||
@@ -798,24 +1029,26 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
798 | } | 1029 | } |
799 | #endif | 1030 | #endif |
800 | 1031 | ||
801 | void __init reserve_bootmem_generic(unsigned long phys, unsigned len) | 1032 | int __init reserve_bootmem_generic(unsigned long phys, unsigned long len, |
1033 | int flags) | ||
802 | { | 1034 | { |
803 | #ifdef CONFIG_NUMA | 1035 | #ifdef CONFIG_NUMA |
804 | int nid, next_nid; | 1036 | int nid, next_nid; |
1037 | int ret; | ||
805 | #endif | 1038 | #endif |
806 | unsigned long pfn = phys >> PAGE_SHIFT; | 1039 | unsigned long pfn = phys >> PAGE_SHIFT; |
807 | 1040 | ||
808 | if (pfn >= end_pfn) { | 1041 | if (pfn >= max_pfn) { |
809 | /* | 1042 | /* |
810 | * This can happen with kdump kernels when accessing | 1043 | * This can happen with kdump kernels when accessing |
811 | * firmware tables: | 1044 | * firmware tables: |
812 | */ | 1045 | */ |
813 | if (pfn < max_pfn_mapped) | 1046 | if (pfn < max_pfn_mapped) |
814 | return; | 1047 | return -EFAULT; |
815 | 1048 | ||
816 | printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n", | 1049 | printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %lu\n", |
817 | phys, len); | 1050 | phys, len); |
818 | return; | 1051 | return -EFAULT; |
819 | } | 1052 | } |
820 | 1053 | ||
821 | /* Should check here against the e820 map to avoid double free */ | 1054 | /* Should check here against the e820 map to avoid double free */ |
@@ -823,9 +1056,13 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len) | |||
823 | nid = phys_to_nid(phys); | 1056 | nid = phys_to_nid(phys); |
824 | next_nid = phys_to_nid(phys + len - 1); | 1057 | next_nid = phys_to_nid(phys + len - 1); |
825 | if (nid == next_nid) | 1058 | if (nid == next_nid) |
826 | reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT); | 1059 | ret = reserve_bootmem_node(NODE_DATA(nid), phys, len, flags); |
827 | else | 1060 | else |
828 | reserve_bootmem(phys, len, BOOTMEM_DEFAULT); | 1061 | ret = reserve_bootmem(phys, len, flags); |
1062 | |||
1063 | if (ret != 0) | ||
1064 | return ret; | ||
1065 | |||
829 | #else | 1066 | #else |
830 | reserve_bootmem(phys, len, BOOTMEM_DEFAULT); | 1067 | reserve_bootmem(phys, len, BOOTMEM_DEFAULT); |
831 | #endif | 1068 | #endif |
@@ -834,6 +1071,8 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len) | |||
834 | dma_reserve += len / PAGE_SIZE; | 1071 | dma_reserve += len / PAGE_SIZE; |
835 | set_dma_reserve(dma_reserve); | 1072 | set_dma_reserve(dma_reserve); |
836 | } | 1073 | } |
1074 | |||
1075 | return 0; | ||
837 | } | 1076 | } |
838 | 1077 | ||
839 | int kern_addr_valid(unsigned long addr) | 1078 | int kern_addr_valid(unsigned long addr) |
@@ -938,7 +1177,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node) | |||
938 | pmd_t *pmd; | 1177 | pmd_t *pmd; |
939 | 1178 | ||
940 | for (; addr < end; addr = next) { | 1179 | for (; addr < end; addr = next) { |
941 | next = pmd_addr_end(addr, end); | 1180 | void *p = NULL; |
942 | 1181 | ||
943 | pgd = vmemmap_pgd_populate(addr, node); | 1182 | pgd = vmemmap_pgd_populate(addr, node); |
944 | if (!pgd) | 1183 | if (!pgd) |
@@ -948,33 +1187,51 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node) | |||
948 | if (!pud) | 1187 | if (!pud) |
949 | return -ENOMEM; | 1188 | return -ENOMEM; |
950 | 1189 | ||
951 | pmd = pmd_offset(pud, addr); | 1190 | if (!cpu_has_pse) { |
952 | if (pmd_none(*pmd)) { | 1191 | next = (addr + PAGE_SIZE) & PAGE_MASK; |
953 | pte_t entry; | 1192 | pmd = vmemmap_pmd_populate(pud, addr, node); |
954 | void *p; | 1193 | |
1194 | if (!pmd) | ||
1195 | return -ENOMEM; | ||
1196 | |||
1197 | p = vmemmap_pte_populate(pmd, addr, node); | ||
955 | 1198 | ||
956 | p = vmemmap_alloc_block(PMD_SIZE, node); | ||
957 | if (!p) | 1199 | if (!p) |
958 | return -ENOMEM; | 1200 | return -ENOMEM; |
959 | 1201 | ||
960 | entry = pfn_pte(__pa(p) >> PAGE_SHIFT, | 1202 | addr_end = addr + PAGE_SIZE; |
961 | PAGE_KERNEL_LARGE); | 1203 | p_end = p + PAGE_SIZE; |
962 | set_pmd(pmd, __pmd(pte_val(entry))); | ||
963 | |||
964 | /* check to see if we have contiguous blocks */ | ||
965 | if (p_end != p || node_start != node) { | ||
966 | if (p_start) | ||
967 | printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n", | ||
968 | addr_start, addr_end-1, p_start, p_end-1, node_start); | ||
969 | addr_start = addr; | ||
970 | node_start = node; | ||
971 | p_start = p; | ||
972 | } | ||
973 | addr_end = addr + PMD_SIZE; | ||
974 | p_end = p + PMD_SIZE; | ||
975 | } else { | 1204 | } else { |
976 | vmemmap_verify((pte_t *)pmd, node, addr, next); | 1205 | next = pmd_addr_end(addr, end); |
1206 | |||
1207 | pmd = pmd_offset(pud, addr); | ||
1208 | if (pmd_none(*pmd)) { | ||
1209 | pte_t entry; | ||
1210 | |||
1211 | p = vmemmap_alloc_block(PMD_SIZE, node); | ||
1212 | if (!p) | ||
1213 | return -ENOMEM; | ||
1214 | |||
1215 | entry = pfn_pte(__pa(p) >> PAGE_SHIFT, | ||
1216 | PAGE_KERNEL_LARGE); | ||
1217 | set_pmd(pmd, __pmd(pte_val(entry))); | ||
1218 | |||
1219 | /* check to see if we have contiguous blocks */ | ||
1220 | if (p_end != p || node_start != node) { | ||
1221 | if (p_start) | ||
1222 | printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n", | ||
1223 | addr_start, addr_end-1, p_start, p_end-1, node_start); | ||
1224 | addr_start = addr; | ||
1225 | node_start = node; | ||
1226 | p_start = p; | ||
1227 | } | ||
1228 | |||
1229 | addr_end = addr + PMD_SIZE; | ||
1230 | p_end = p + PMD_SIZE; | ||
1231 | } else | ||
1232 | vmemmap_verify((pte_t *)pmd, node, addr, next); | ||
977 | } | 1233 | } |
1234 | |||
978 | } | 1235 | } |
979 | return 0; | 1236 | return 0; |
980 | } | 1237 | } |