aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/init_64.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2008-04-17 11:40:45 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:40:45 -0400
commitef9257668e3199f9566dc4a31f5292838bd99b49 (patch)
treeff80abf80bdbae23fe8bd6e51967f11af3723b65 /arch/x86/mm/init_64.c
parent00d1c5e05736f947687be27706bda01cec104e57 (diff)
x86: do kernel direct mapping at boot using GB pages
The AMD Fam10h CPUs support new Gigabyte page table entry for mapping 1GB at a time. Use this for the kernel direct mapping. Only done for 64bit because i386 does not support GB page tables. This only applies to the data portion of the direct mapping; the kernel text mapping stays with 2MB pages because the AMD Fam10h microarchitecture does not support GB ITLBs and AMD recommends against using GB mappings for code. Can be disabled with disable_gbpages on the kernel command line [ tglx@linutronix.de: simplify enable code ] [ Yinghai Lu <yinghai.lu@sun.com>: boot fix on 256 GB RAM ] Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r--arch/x86/mm/init_64.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 6e7d5a42a09a..ae66d8d4c58d 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -370,7 +370,14 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
370 } 370 }
371 371
372 if (pud_val(*pud)) { 372 if (pud_val(*pud)) {
373 phys_pmd_update(pud, addr, end); 373 if (!pud_large(*pud))
374 phys_pmd_update(pud, addr, end);
375 continue;
376 }
377
378 if (direct_gbpages) {
379 set_pte((pte_t *)pud,
380 pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
374 continue; 381 continue;
375 } 382 }
376 383
@@ -391,9 +398,11 @@ static void __init find_early_table_space(unsigned long end)
391 unsigned long puds, pmds, tables, start; 398 unsigned long puds, pmds, tables, start;
392 399
393 puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; 400 puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
394 pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; 401 tables = round_up(puds * sizeof(pud_t), PAGE_SIZE);
395 tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) + 402 if (!direct_gbpages) {
396 round_up(pmds * sizeof(pmd_t), PAGE_SIZE); 403 pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
404 tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
405 }
397 406
398 /* 407 /*
399 * RED-PEN putting page tables only on node 0 could 408 * RED-PEN putting page tables only on node 0 could
@@ -413,6 +422,14 @@ static void __init find_early_table_space(unsigned long end)
413 (table_start << PAGE_SHIFT) + tables); 422 (table_start << PAGE_SHIFT) + tables);
414} 423}
415 424
425static void __init init_gbpages(void)
426{
427 if (direct_gbpages && cpu_has_gbpages)
428 printk(KERN_INFO "Using GB pages for direct mapping\n");
429 else
430 direct_gbpages = 0;
431}
432
416/* 433/*
417 * Setup the direct mapping of the physical memory at PAGE_OFFSET. 434 * Setup the direct mapping of the physical memory at PAGE_OFFSET.
418 * This runs before bootmem is initialized and gets pages directly from 435 * This runs before bootmem is initialized and gets pages directly from
@@ -431,8 +448,10 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
431 * memory mapped. Unfortunately this is done currently before the 448 * memory mapped. Unfortunately this is done currently before the
432 * nodes are discovered. 449 * nodes are discovered.
433 */ 450 */
434 if (!after_bootmem) 451 if (!after_bootmem) {
452 init_gbpages();
435 find_early_table_space(end); 453 find_early_table_space(end);
454 }
436 455
437 start = (unsigned long)__va(start); 456 start = (unsigned long)__va(start);
438 end = (unsigned long)__va(end); 457 end = (unsigned long)__va(end);