diff options
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r-- | arch/x86/mm/init_64.c | 97 |
1 files changed, 51 insertions, 46 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index c14a5422e152..2362b646178e 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -51,6 +51,8 @@ | |||
51 | #include <asm/numa.h> | 51 | #include <asm/numa.h> |
52 | #include <asm/cacheflush.h> | 52 | #include <asm/cacheflush.h> |
53 | #include <asm/init.h> | 53 | #include <asm/init.h> |
54 | #include <asm/uv/uv.h> | ||
55 | #include <asm/setup.h> | ||
54 | 56 | ||
55 | static int __init parse_direct_gbpages_off(char *arg) | 57 | static int __init parse_direct_gbpages_off(char *arg) |
56 | { | 58 | { |
@@ -293,18 +295,18 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size) | |||
293 | * to the compile time generated pmds. This results in invalid pmds up | 295 | * to the compile time generated pmds. This results in invalid pmds up |
294 | * to the point where we hit the physaddr 0 mapping. | 296 | * to the point where we hit the physaddr 0 mapping. |
295 | * | 297 | * |
296 | * We limit the mappings to the region from _text to _end. _end is | 298 | * We limit the mappings to the region from _text to _brk_end. _brk_end |
297 | * rounded up to the 2MB boundary. This catches the invalid pmds as | 299 | * is rounded up to the 2MB boundary. This catches the invalid pmds as |
298 | * well, as they are located before _text: | 300 | * well, as they are located before _text: |
299 | */ | 301 | */ |
300 | void __init cleanup_highmap(void) | 302 | void __init cleanup_highmap(void) |
301 | { | 303 | { |
302 | unsigned long vaddr = __START_KERNEL_map; | 304 | unsigned long vaddr = __START_KERNEL_map; |
303 | unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1; | 305 | unsigned long vaddr_end = __START_KERNEL_map + (max_pfn_mapped << PAGE_SHIFT); |
306 | unsigned long end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1; | ||
304 | pmd_t *pmd = level2_kernel_pgt; | 307 | pmd_t *pmd = level2_kernel_pgt; |
305 | pmd_t *last_pmd = pmd + PTRS_PER_PMD; | ||
306 | 308 | ||
307 | for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) { | 309 | for (; vaddr + PMD_SIZE - 1 < vaddr_end; pmd++, vaddr += PMD_SIZE) { |
308 | if (pmd_none(*pmd)) | 310 | if (pmd_none(*pmd)) |
309 | continue; | 311 | continue; |
310 | if (vaddr < (unsigned long) _text || vaddr > end) | 312 | if (vaddr < (unsigned long) _text || vaddr > end) |
@@ -314,7 +316,7 @@ void __init cleanup_highmap(void) | |||
314 | 316 | ||
315 | static __ref void *alloc_low_page(unsigned long *phys) | 317 | static __ref void *alloc_low_page(unsigned long *phys) |
316 | { | 318 | { |
317 | unsigned long pfn = e820_table_end++; | 319 | unsigned long pfn = pgt_buf_end++; |
318 | void *adr; | 320 | void *adr; |
319 | 321 | ||
320 | if (after_bootmem) { | 322 | if (after_bootmem) { |
@@ -324,7 +326,7 @@ static __ref void *alloc_low_page(unsigned long *phys) | |||
324 | return adr; | 326 | return adr; |
325 | } | 327 | } |
326 | 328 | ||
327 | if (pfn >= e820_table_top) | 329 | if (pfn >= pgt_buf_top) |
328 | panic("alloc_low_page: ran out of memory"); | 330 | panic("alloc_low_page: ran out of memory"); |
329 | 331 | ||
330 | adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE); | 332 | adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE); |
@@ -333,12 +335,28 @@ static __ref void *alloc_low_page(unsigned long *phys) | |||
333 | return adr; | 335 | return adr; |
334 | } | 336 | } |
335 | 337 | ||
338 | static __ref void *map_low_page(void *virt) | ||
339 | { | ||
340 | void *adr; | ||
341 | unsigned long phys, left; | ||
342 | |||
343 | if (after_bootmem) | ||
344 | return virt; | ||
345 | |||
346 | phys = __pa(virt); | ||
347 | left = phys & (PAGE_SIZE - 1); | ||
348 | adr = early_memremap(phys & PAGE_MASK, PAGE_SIZE); | ||
349 | adr = (void *)(((unsigned long)adr) | left); | ||
350 | |||
351 | return adr; | ||
352 | } | ||
353 | |||
336 | static __ref void unmap_low_page(void *adr) | 354 | static __ref void unmap_low_page(void *adr) |
337 | { | 355 | { |
338 | if (after_bootmem) | 356 | if (after_bootmem) |
339 | return; | 357 | return; |
340 | 358 | ||
341 | early_iounmap(adr, PAGE_SIZE); | 359 | early_iounmap((void *)((unsigned long)adr & PAGE_MASK), PAGE_SIZE); |
342 | } | 360 | } |
343 | 361 | ||
344 | static unsigned long __meminit | 362 | static unsigned long __meminit |
@@ -386,15 +404,6 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, | |||
386 | } | 404 | } |
387 | 405 | ||
388 | static unsigned long __meminit | 406 | static unsigned long __meminit |
389 | phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end, | ||
390 | pgprot_t prot) | ||
391 | { | ||
392 | pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd); | ||
393 | |||
394 | return phys_pte_init(pte, address, end, prot); | ||
395 | } | ||
396 | |||
397 | static unsigned long __meminit | ||
398 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, | 407 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, |
399 | unsigned long page_size_mask, pgprot_t prot) | 408 | unsigned long page_size_mask, pgprot_t prot) |
400 | { | 409 | { |
@@ -420,8 +429,10 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, | |||
420 | if (pmd_val(*pmd)) { | 429 | if (pmd_val(*pmd)) { |
421 | if (!pmd_large(*pmd)) { | 430 | if (!pmd_large(*pmd)) { |
422 | spin_lock(&init_mm.page_table_lock); | 431 | spin_lock(&init_mm.page_table_lock); |
423 | last_map_addr = phys_pte_update(pmd, address, | 432 | pte = map_low_page((pte_t *)pmd_page_vaddr(*pmd)); |
433 | last_map_addr = phys_pte_init(pte, address, | ||
424 | end, prot); | 434 | end, prot); |
435 | unmap_low_page(pte); | ||
425 | spin_unlock(&init_mm.page_table_lock); | 436 | spin_unlock(&init_mm.page_table_lock); |
426 | continue; | 437 | continue; |
427 | } | 438 | } |
@@ -468,18 +479,6 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, | |||
468 | } | 479 | } |
469 | 480 | ||
470 | static unsigned long __meminit | 481 | static unsigned long __meminit |
471 | phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end, | ||
472 | unsigned long page_size_mask, pgprot_t prot) | ||
473 | { | ||
474 | pmd_t *pmd = pmd_offset(pud, 0); | ||
475 | unsigned long last_map_addr; | ||
476 | |||
477 | last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask, prot); | ||
478 | __flush_tlb_all(); | ||
479 | return last_map_addr; | ||
480 | } | ||
481 | |||
482 | static unsigned long __meminit | ||
483 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, | 482 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, |
484 | unsigned long page_size_mask) | 483 | unsigned long page_size_mask) |
485 | { | 484 | { |
@@ -504,8 +503,11 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, | |||
504 | 503 | ||
505 | if (pud_val(*pud)) { | 504 | if (pud_val(*pud)) { |
506 | if (!pud_large(*pud)) { | 505 | if (!pud_large(*pud)) { |
507 | last_map_addr = phys_pmd_update(pud, addr, end, | 506 | pmd = map_low_page(pmd_offset(pud, 0)); |
507 | last_map_addr = phys_pmd_init(pmd, addr, end, | ||
508 | page_size_mask, prot); | 508 | page_size_mask, prot); |
509 | unmap_low_page(pmd); | ||
510 | __flush_tlb_all(); | ||
509 | continue; | 511 | continue; |
510 | } | 512 | } |
511 | /* | 513 | /* |
@@ -553,17 +555,6 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, | |||
553 | return last_map_addr; | 555 | return last_map_addr; |
554 | } | 556 | } |
555 | 557 | ||
556 | static unsigned long __meminit | ||
557 | phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
558 | unsigned long page_size_mask) | ||
559 | { | ||
560 | pud_t *pud; | ||
561 | |||
562 | pud = (pud_t *)pgd_page_vaddr(*pgd); | ||
563 | |||
564 | return phys_pud_init(pud, addr, end, page_size_mask); | ||
565 | } | ||
566 | |||
567 | unsigned long __meminit | 558 | unsigned long __meminit |
568 | kernel_physical_mapping_init(unsigned long start, | 559 | kernel_physical_mapping_init(unsigned long start, |
569 | unsigned long end, | 560 | unsigned long end, |
@@ -587,8 +578,10 @@ kernel_physical_mapping_init(unsigned long start, | |||
587 | next = end; | 578 | next = end; |
588 | 579 | ||
589 | if (pgd_val(*pgd)) { | 580 | if (pgd_val(*pgd)) { |
590 | last_map_addr = phys_pud_update(pgd, __pa(start), | 581 | pud = map_low_page((pud_t *)pgd_page_vaddr(*pgd)); |
582 | last_map_addr = phys_pud_init(pud, __pa(start), | ||
591 | __pa(end), page_size_mask); | 583 | __pa(end), page_size_mask); |
584 | unmap_low_page(pud); | ||
592 | continue; | 585 | continue; |
593 | } | 586 | } |
594 | 587 | ||
@@ -612,10 +605,9 @@ kernel_physical_mapping_init(unsigned long start, | |||
612 | } | 605 | } |
613 | 606 | ||
614 | #ifndef CONFIG_NUMA | 607 | #ifndef CONFIG_NUMA |
615 | void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn, | 608 | void __init initmem_init(void) |
616 | int acpi, int k8) | ||
617 | { | 609 | { |
618 | memblock_x86_register_active_regions(0, start_pfn, end_pfn); | 610 | memblock_x86_register_active_regions(0, 0, max_pfn); |
619 | } | 611 | } |
620 | #endif | 612 | #endif |
621 | 613 | ||
@@ -908,6 +900,19 @@ const char *arch_vma_name(struct vm_area_struct *vma) | |||
908 | return NULL; | 900 | return NULL; |
909 | } | 901 | } |
910 | 902 | ||
903 | #ifdef CONFIG_X86_UV | ||
904 | #define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS) | ||
905 | |||
906 | unsigned long memory_block_size_bytes(void) | ||
907 | { | ||
908 | if (is_uv_system()) { | ||
909 | printk(KERN_INFO "UV: memory block size 2GB\n"); | ||
910 | return 2UL * 1024 * 1024 * 1024; | ||
911 | } | ||
912 | return MIN_MEMORY_BLOCK_SIZE; | ||
913 | } | ||
914 | #endif | ||
915 | |||
911 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | 916 | #ifdef CONFIG_SPARSEMEM_VMEMMAP |
912 | /* | 917 | /* |
913 | * Initialise the sparsemem vmemmap using huge-pages at the PMD level. | 918 | * Initialise the sparsemem vmemmap using huge-pages at the PMD level. |