aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2008-03-11 22:53:28 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:41:30 -0400
commitcc6150321903ca4c3bc9d53b0cdafb05d77d64d0 (patch)
treecfdb0ee512da7da82c15d4b1aae66d1f25640f31
parent67794292c8615b05f46419ba8d4fd99e7c9a5db9 (diff)
x86: account overlapped mappings in max_pfn_mapped
When end_pfn is not aligned to 2MB (or 1GB) then the kernel might map more memory than end_pfn. Account this in max_pfn_mapped. Signed-off-by: Andi Kleen <ak@suse.de> Cc: andreas.herrmann3@amd.com Cc: mingo@elte.hu Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/setup_64.c2
-rw-r--r--arch/x86/mm/init_64.c34
-rw-r--r--include/asm-x86/page_64.h3
-rw-r--r--include/asm-x86/proto.h2
4 files changed, 27 insertions, 14 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
316static void __meminit 316static unsigned long __meminit
317phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end) 317phys_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
340static void __meminit 341static unsigned long __meminit
341phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) 342phys_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
350static void __meminit 354static unsigned long __meminit
351phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end) 355phys_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
393static void __init find_early_table_space(unsigned long end) 401static 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 */
545void __init_refok init_memory_mapping(unsigned long start, unsigned long end) 553unsigned 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);
diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h
index 54d5db634858..6ea72859c491 100644
--- a/include/asm-x86/page_64.h
+++ b/include/asm-x86/page_64.h
@@ -80,6 +80,9 @@ typedef struct { pteval_t pte; } pte_t;
80 80
81#define vmemmap ((struct page *)VMEMMAP_START) 81#define vmemmap ((struct page *)VMEMMAP_START)
82 82
83extern unsigned long init_memory_mapping(unsigned long start,
84 unsigned long end);
85
83#endif /* !__ASSEMBLY__ */ 86#endif /* !__ASSEMBLY__ */
84 87
85#ifdef CONFIG_FLATMEM 88#ifdef CONFIG_FLATMEM
diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h
index 9da46af3b0e9..1e17bcce450e 100644
--- a/include/asm-x86/proto.h
+++ b/include/asm-x86/proto.h
@@ -7,8 +7,6 @@
7 7
8extern void early_idt_handler(void); 8extern void early_idt_handler(void);
9 9
10extern void init_memory_mapping(unsigned long start, unsigned long end);
11
12extern void system_call(void); 10extern void system_call(void);
13extern void syscall_init(void); 11extern void syscall_init(void);
14 12