diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/setup_64.c | 2 | ||||
-rw-r--r-- | arch/x86/mm/init_64.c | 34 |
2 files changed, 24 insertions, 12 deletions
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 413b8fc31545..3d76dbd9f2c0 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c | |||
@@ -347,7 +347,7 @@ void __init setup_arch(char **cmdline_p) | |||
347 | 347 | ||
348 | check_efer(); | 348 | check_efer(); |
349 | 349 | ||
350 | init_memory_mapping(0, (max_pfn_mapped << PAGE_SHIFT)); | 350 | max_pfn_mapped = init_memory_mapping(0, (max_pfn_mapped << PAGE_SHIFT)); |
351 | if (efi_enabled) | 351 | if (efi_enabled) |
352 | efi_init(); | 352 | efi_init(); |
353 | 353 | ||
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index ef9e9cfb1fc2..1076097dcab2 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -313,7 +313,7 @@ __meminit void early_iounmap(void *addr, unsigned long size) | |||
313 | __flush_tlb_all(); | 313 | __flush_tlb_all(); |
314 | } | 314 | } |
315 | 315 | ||
316 | static void __meminit | 316 | static unsigned long __meminit |
317 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) | 317 | phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) |
318 | { | 318 | { |
319 | int i = pmd_index(address); | 319 | int i = pmd_index(address); |
@@ -335,21 +335,26 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) | |||
335 | set_pte((pte_t *)pmd, | 335 | set_pte((pte_t *)pmd, |
336 | pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); | 336 | pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); |
337 | } | 337 | } |
338 | return address; | ||
338 | } | 339 | } |
339 | 340 | ||
340 | static void __meminit | 341 | static unsigned long __meminit |
341 | phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) | 342 | phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) |
342 | { | 343 | { |
343 | pmd_t *pmd = pmd_offset(pud, 0); | 344 | pmd_t *pmd = pmd_offset(pud, 0); |
345 | unsigned long last_map_addr; | ||
346 | |||
344 | spin_lock(&init_mm.page_table_lock); | 347 | spin_lock(&init_mm.page_table_lock); |
345 | phys_pmd_init(pmd, address, end); | 348 | last_map_addr = phys_pmd_init(pmd, address, end); |
346 | spin_unlock(&init_mm.page_table_lock); | 349 | spin_unlock(&init_mm.page_table_lock); |
347 | __flush_tlb_all(); | 350 | __flush_tlb_all(); |
351 | return last_map_addr; | ||
348 | } | 352 | } |
349 | 353 | ||
350 | static void __meminit | 354 | static unsigned long __meminit |
351 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | 355 | phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) |
352 | { | 356 | { |
357 | unsigned long last_map_addr = end; | ||
353 | int i = pud_index(addr); | 358 | int i = pud_index(addr); |
354 | 359 | ||
355 | for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) { | 360 | for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) { |
@@ -368,13 +373,14 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | |||
368 | 373 | ||
369 | if (pud_val(*pud)) { | 374 | if (pud_val(*pud)) { |
370 | if (!pud_large(*pud)) | 375 | if (!pud_large(*pud)) |
371 | phys_pmd_update(pud, addr, end); | 376 | last_map_addr = phys_pmd_update(pud, addr, end); |
372 | continue; | 377 | continue; |
373 | } | 378 | } |
374 | 379 | ||
375 | if (direct_gbpages) { | 380 | if (direct_gbpages) { |
376 | set_pte((pte_t *)pud, | 381 | set_pte((pte_t *)pud, |
377 | pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); | 382 | pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); |
383 | last_map_addr = (addr & PUD_MASK) + PUD_SIZE; | ||
378 | continue; | 384 | continue; |
379 | } | 385 | } |
380 | 386 | ||
@@ -382,12 +388,14 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) | |||
382 | 388 | ||
383 | spin_lock(&init_mm.page_table_lock); | 389 | spin_lock(&init_mm.page_table_lock); |
384 | set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); | 390 | set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); |
385 | phys_pmd_init(pmd, addr, end); | 391 | last_map_addr = phys_pmd_init(pmd, addr, end); |
386 | spin_unlock(&init_mm.page_table_lock); | 392 | spin_unlock(&init_mm.page_table_lock); |
387 | 393 | ||
388 | unmap_low_page(pmd); | 394 | unmap_low_page(pmd); |
389 | } | 395 | } |
390 | __flush_tlb_all(); | 396 | __flush_tlb_all(); |
397 | |||
398 | return last_map_addr >> PAGE_SHIFT; | ||
391 | } | 399 | } |
392 | 400 | ||
393 | static void __init find_early_table_space(unsigned long end) | 401 | static void __init find_early_table_space(unsigned long end) |
@@ -542,9 +550,9 @@ static void __init early_memtest(unsigned long start, unsigned long end) | |||
542 | * This runs before bootmem is initialized and gets pages directly from | 550 | * This runs before bootmem is initialized and gets pages directly from |
543 | * the physical memory. To access them they are temporarily mapped. | 551 | * the physical memory. To access them they are temporarily mapped. |
544 | */ | 552 | */ |
545 | void __init_refok init_memory_mapping(unsigned long start, unsigned long end) | 553 | unsigned long __init_refok init_memory_mapping(unsigned long start, unsigned long end) |
546 | { | 554 | { |
547 | unsigned long next; | 555 | unsigned long next, last_map_addr = end; |
548 | unsigned long start_phys = start, end_phys = end; | 556 | unsigned long start_phys = start, end_phys = end; |
549 | 557 | ||
550 | printk(KERN_INFO "init_memory_mapping\n"); | 558 | printk(KERN_INFO "init_memory_mapping\n"); |
@@ -577,7 +585,7 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end) | |||
577 | next = start + PGDIR_SIZE; | 585 | next = start + PGDIR_SIZE; |
578 | if (next > end) | 586 | if (next > end) |
579 | next = end; | 587 | next = end; |
580 | phys_pud_init(pud, __pa(start), __pa(next)); | 588 | last_map_addr = phys_pud_init(pud, __pa(start), __pa(next)); |
581 | if (!after_bootmem) | 589 | if (!after_bootmem) |
582 | set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); | 590 | set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); |
583 | unmap_low_page(pud); | 591 | unmap_low_page(pud); |
@@ -593,6 +601,8 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end) | |||
593 | 601 | ||
594 | if (!after_bootmem) | 602 | if (!after_bootmem) |
595 | early_memtest(start_phys, end_phys); | 603 | early_memtest(start_phys, end_phys); |
604 | |||
605 | return last_map_addr; | ||
596 | } | 606 | } |
597 | 607 | ||
598 | #ifndef CONFIG_NUMA | 608 | #ifndef CONFIG_NUMA |
@@ -632,11 +642,13 @@ int arch_add_memory(int nid, u64 start, u64 size) | |||
632 | { | 642 | { |
633 | struct pglist_data *pgdat = NODE_DATA(nid); | 643 | struct pglist_data *pgdat = NODE_DATA(nid); |
634 | struct zone *zone = pgdat->node_zones + ZONE_NORMAL; | 644 | struct zone *zone = pgdat->node_zones + ZONE_NORMAL; |
635 | unsigned long start_pfn = start >> PAGE_SHIFT; | 645 | unsigned long last_mapped_pfn, start_pfn = start >> PAGE_SHIFT; |
636 | unsigned long nr_pages = size >> PAGE_SHIFT; | 646 | unsigned long nr_pages = size >> PAGE_SHIFT; |
637 | int ret; | 647 | int ret; |
638 | 648 | ||
639 | init_memory_mapping(start, start + size-1); | 649 | last_mapped_pfn = init_memory_mapping(start, start + size-1); |
650 | if (last_mapped_pfn > max_pfn_mapped) | ||
651 | max_pfn_mapped = last_mapped_pfn; | ||
640 | 652 | ||
641 | ret = __add_pages(zone, start_pfn, nr_pages); | 653 | ret = __add_pages(zone, start_pfn, nr_pages); |
642 | WARN_ON(1); | 654 | WARN_ON(1); |