aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/init_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r--arch/x86/mm/init_64.c97
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
55static int __init parse_direct_gbpages_off(char *arg) 57static 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 */
300void __init cleanup_highmap(void) 302void __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
315static __ref void *alloc_low_page(unsigned long *phys) 317static __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
338static __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
336static __ref void unmap_low_page(void *adr) 354static __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
344static unsigned long __meminit 362static unsigned long __meminit
@@ -386,15 +404,6 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
386} 404}
387 405
388static unsigned long __meminit 406static unsigned long __meminit
389phys_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
397static unsigned long __meminit
398phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, 407phys_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
470static unsigned long __meminit 481static unsigned long __meminit
471phys_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
482static unsigned long __meminit
483phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, 482phys_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
556static unsigned long __meminit
557phys_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
567unsigned long __meminit 558unsigned long __meminit
568kernel_physical_mapping_init(unsigned long start, 559kernel_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
615void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn, 608void __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
906unsigned 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.