diff options
author | Andi Kleen <ak@suse.de> | 2008-04-17 11:40:45 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-17 11:40:45 -0400 |
commit | ef9257668e3199f9566dc4a31f5292838bd99b49 (patch) | |
tree | ff80abf80bdbae23fe8bd6e51967f11af3723b65 /arch/x86/mm/init_64.c | |
parent | 00d1c5e05736f947687be27706bda01cec104e57 (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.c | 29 |
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 | ||
425 | static 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); |