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.c222
1 files changed, 184 insertions, 38 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index a02a14f0f324..1076097dcab2 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -54,6 +54,26 @@ static unsigned long dma_reserve __initdata;
54 54
55DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 55DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
56 56
57int direct_gbpages __meminitdata
58#ifdef CONFIG_DIRECT_GBPAGES
59 = 1
60#endif
61;
62
63static int __init parse_direct_gbpages_off(char *arg)
64{
65 direct_gbpages = 0;
66 return 0;
67}
68early_param("nogbpages", parse_direct_gbpages_off);
69
70static int __init parse_direct_gbpages_on(char *arg)
71{
72 direct_gbpages = 1;
73 return 0;
74}
75early_param("gbpages", parse_direct_gbpages_on);
76
57/* 77/*
58 * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the 78 * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
59 * physical space so we can cache the place of the first one and move 79 * physical space so we can cache the place of the first one and move
@@ -69,9 +89,6 @@ void show_mem(void)
69 89
70 printk(KERN_INFO "Mem-info:\n"); 90 printk(KERN_INFO "Mem-info:\n");
71 show_free_areas(); 91 show_free_areas();
72 printk(KERN_INFO "Free swap: %6ldkB\n",
73 nr_swap_pages << (PAGE_SHIFT-10));
74
75 for_each_online_pgdat(pgdat) { 92 for_each_online_pgdat(pgdat) {
76 for (i = 0; i < pgdat->node_spanned_pages; ++i) { 93 for (i = 0; i < pgdat->node_spanned_pages; ++i) {
77 /* 94 /*
@@ -296,7 +313,7 @@ __meminit void early_iounmap(void *addr, unsigned long size)
296 __flush_tlb_all(); 313 __flush_tlb_all();
297} 314}
298 315
299static void __meminit 316static unsigned long __meminit
300phys_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)
301{ 318{
302 int i = pmd_index(address); 319 int i = pmd_index(address);
@@ -318,21 +335,26 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
318 set_pte((pte_t *)pmd, 335 set_pte((pte_t *)pmd,
319 pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE)); 336 pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
320 } 337 }
338 return address;
321} 339}
322 340
323static void __meminit 341static unsigned long __meminit
324phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) 342phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
325{ 343{
326 pmd_t *pmd = pmd_offset(pud, 0); 344 pmd_t *pmd = pmd_offset(pud, 0);
345 unsigned long last_map_addr;
346
327 spin_lock(&init_mm.page_table_lock); 347 spin_lock(&init_mm.page_table_lock);
328 phys_pmd_init(pmd, address, end); 348 last_map_addr = phys_pmd_init(pmd, address, end);
329 spin_unlock(&init_mm.page_table_lock); 349 spin_unlock(&init_mm.page_table_lock);
330 __flush_tlb_all(); 350 __flush_tlb_all();
351 return last_map_addr;
331} 352}
332 353
333static void __meminit 354static unsigned long __meminit
334phys_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)
335{ 356{
357 unsigned long last_map_addr = end;
336 int i = pud_index(addr); 358 int i = pud_index(addr);
337 359
338 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) {
@@ -350,7 +372,15 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
350 } 372 }
351 373
352 if (pud_val(*pud)) { 374 if (pud_val(*pud)) {
353 phys_pmd_update(pud, addr, end); 375 if (!pud_large(*pud))
376 last_map_addr = phys_pmd_update(pud, addr, end);
377 continue;
378 }
379
380 if (direct_gbpages) {
381 set_pte((pte_t *)pud,
382 pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
383 last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
354 continue; 384 continue;
355 } 385 }
356 386
@@ -358,12 +388,14 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
358 388
359 spin_lock(&init_mm.page_table_lock); 389 spin_lock(&init_mm.page_table_lock);
360 set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); 390 set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
361 phys_pmd_init(pmd, addr, end); 391 last_map_addr = phys_pmd_init(pmd, addr, end);
362 spin_unlock(&init_mm.page_table_lock); 392 spin_unlock(&init_mm.page_table_lock);
363 393
364 unmap_low_page(pmd); 394 unmap_low_page(pmd);
365 } 395 }
366 __flush_tlb_all(); 396 __flush_tlb_all();
397
398 return last_map_addr >> PAGE_SHIFT;
367} 399}
368 400
369static void __init find_early_table_space(unsigned long end) 401static void __init find_early_table_space(unsigned long end)
@@ -371,9 +403,11 @@ static void __init find_early_table_space(unsigned long end)
371 unsigned long puds, pmds, tables, start; 403 unsigned long puds, pmds, tables, start;
372 404
373 puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; 405 puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
374 pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; 406 tables = round_up(puds * sizeof(pud_t), PAGE_SIZE);
375 tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) + 407 if (!direct_gbpages) {
376 round_up(pmds * sizeof(pmd_t), PAGE_SIZE); 408 pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
409 tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
410 }
377 411
378 /* 412 /*
379 * RED-PEN putting page tables only on node 0 could 413 * RED-PEN putting page tables only on node 0 could
@@ -393,16 +427,135 @@ static void __init find_early_table_space(unsigned long end)
393 (table_start << PAGE_SHIFT) + tables); 427 (table_start << PAGE_SHIFT) + tables);
394} 428}
395 429
430static void __init init_gbpages(void)
431{
432 if (direct_gbpages && cpu_has_gbpages)
433 printk(KERN_INFO "Using GB pages for direct mapping\n");
434 else
435 direct_gbpages = 0;
436}
437
438#ifdef CONFIG_MEMTEST_BOOTPARAM
439
440static void __init memtest(unsigned long start_phys, unsigned long size,
441 unsigned pattern)
442{
443 unsigned long i;
444 unsigned long *start;
445 unsigned long start_bad;
446 unsigned long last_bad;
447 unsigned long val;
448 unsigned long start_phys_aligned;
449 unsigned long count;
450 unsigned long incr;
451
452 switch (pattern) {
453 case 0:
454 val = 0UL;
455 break;
456 case 1:
457 val = -1UL;
458 break;
459 case 2:
460 val = 0x5555555555555555UL;
461 break;
462 case 3:
463 val = 0xaaaaaaaaaaaaaaaaUL;
464 break;
465 default:
466 return;
467 }
468
469 incr = sizeof(unsigned long);
470 start_phys_aligned = ALIGN(start_phys, incr);
471 count = (size - (start_phys_aligned - start_phys))/incr;
472 start = __va(start_phys_aligned);
473 start_bad = 0;
474 last_bad = 0;
475
476 for (i = 0; i < count; i++)
477 start[i] = val;
478 for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
479 if (*start != val) {
480 if (start_phys_aligned == last_bad + incr) {
481 last_bad += incr;
482 } else {
483 if (start_bad) {
484 printk(KERN_CONT "\n %016lx bad mem addr %016lx - %016lx reserved",
485 val, start_bad, last_bad + incr);
486 reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
487 }
488 start_bad = last_bad = start_phys_aligned;
489 }
490 }
491 }
492 if (start_bad) {
493 printk(KERN_CONT "\n %016lx bad mem addr %016lx - %016lx reserved",
494 val, start_bad, last_bad + incr);
495 reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
496 }
497
498}
499
500static int memtest_pattern __initdata = CONFIG_MEMTEST_BOOTPARAM_VALUE;
501
502static int __init parse_memtest(char *arg)
503{
504 if (arg)
505 memtest_pattern = simple_strtoul(arg, NULL, 0);
506 return 0;
507}
508
509early_param("memtest", parse_memtest);
510
511static void __init early_memtest(unsigned long start, unsigned long end)
512{
513 unsigned long t_start, t_size;
514 unsigned pattern;
515
516 if (!memtest_pattern)
517 return;
518
519 printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
520 for (pattern = 0; pattern < memtest_pattern; pattern++) {
521 t_start = start;
522 t_size = 0;
523 while (t_start < end) {
524 t_start = find_e820_area_size(t_start, &t_size, 1);
525
526 /* done ? */
527 if (t_start >= end)
528 break;
529 if (t_start + t_size > end)
530 t_size = end - t_start;
531
532 printk(KERN_CONT "\n %016lx - %016lx pattern %d",
533 t_start, t_start + t_size, pattern);
534
535 memtest(t_start, t_size, pattern);
536
537 t_start += t_size;
538 }
539 }
540 printk(KERN_CONT "\n");
541}
542#else
543static void __init early_memtest(unsigned long start, unsigned long end)
544{
545}
546#endif
547
396/* 548/*
397 * Setup the direct mapping of the physical memory at PAGE_OFFSET. 549 * Setup the direct mapping of the physical memory at PAGE_OFFSET.
398 * This runs before bootmem is initialized and gets pages directly from 550 * This runs before bootmem is initialized and gets pages directly from
399 * the physical memory. To access them they are temporarily mapped. 551 * the physical memory. To access them they are temporarily mapped.
400 */ 552 */
401void __init_refok init_memory_mapping(unsigned long start, unsigned long end) 553unsigned long __init_refok init_memory_mapping(unsigned long start, unsigned long end)
402{ 554{
403 unsigned long next; 555 unsigned long next, last_map_addr = end;
556 unsigned long start_phys = start, end_phys = end;
404 557
405 pr_debug("init_memory_mapping\n"); 558 printk(KERN_INFO "init_memory_mapping\n");
406 559
407 /* 560 /*
408 * Find space for the kernel direct mapping tables. 561 * Find space for the kernel direct mapping tables.
@@ -411,8 +564,10 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
411 * memory mapped. Unfortunately this is done currently before the 564 * memory mapped. Unfortunately this is done currently before the
412 * nodes are discovered. 565 * nodes are discovered.
413 */ 566 */
414 if (!after_bootmem) 567 if (!after_bootmem) {
568 init_gbpages();
415 find_early_table_space(end); 569 find_early_table_space(end);
570 }
416 571
417 start = (unsigned long)__va(start); 572 start = (unsigned long)__va(start);
418 end = (unsigned long)__va(end); 573 end = (unsigned long)__va(end);
@@ -430,7 +585,7 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
430 next = start + PGDIR_SIZE; 585 next = start + PGDIR_SIZE;
431 if (next > end) 586 if (next > end)
432 next = end; 587 next = end;
433 phys_pud_init(pud, __pa(start), __pa(next)); 588 last_map_addr = phys_pud_init(pud, __pa(start), __pa(next));
434 if (!after_bootmem) 589 if (!after_bootmem)
435 set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); 590 set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
436 unmap_low_page(pud); 591 unmap_low_page(pud);
@@ -443,6 +598,11 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
443 if (!after_bootmem) 598 if (!after_bootmem)
444 reserve_early(table_start << PAGE_SHIFT, 599 reserve_early(table_start << PAGE_SHIFT,
445 table_end << PAGE_SHIFT, "PGTABLE"); 600 table_end << PAGE_SHIFT, "PGTABLE");
601
602 if (!after_bootmem)
603 early_memtest(start_phys, end_phys);
604
605 return last_map_addr;
446} 606}
447 607
448#ifndef CONFIG_NUMA 608#ifndef CONFIG_NUMA
@@ -482,11 +642,13 @@ int arch_add_memory(int nid, u64 start, u64 size)
482{ 642{
483 struct pglist_data *pgdat = NODE_DATA(nid); 643 struct pglist_data *pgdat = NODE_DATA(nid);
484 struct zone *zone = pgdat->node_zones + ZONE_NORMAL; 644 struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
485 unsigned long start_pfn = start >> PAGE_SHIFT; 645 unsigned long last_mapped_pfn, start_pfn = start >> PAGE_SHIFT;
486 unsigned long nr_pages = size >> PAGE_SHIFT; 646 unsigned long nr_pages = size >> PAGE_SHIFT;
487 int ret; 647 int ret;
488 648
489 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;
490 652
491 ret = __add_pages(zone, start_pfn, nr_pages); 653 ret = __add_pages(zone, start_pfn, nr_pages);
492 WARN_ON(1); 654 WARN_ON(1);
@@ -596,24 +758,7 @@ EXPORT_SYMBOL_GPL(rodata_test_data);
596 758
597void mark_rodata_ro(void) 759void mark_rodata_ro(void)
598{ 760{
599 unsigned long start = (unsigned long)_stext, end; 761 unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata);
600
601#ifdef CONFIG_HOTPLUG_CPU
602 /* It must still be possible to apply SMP alternatives. */
603 if (num_possible_cpus() > 1)
604 start = (unsigned long)_etext;
605#endif
606
607#ifdef CONFIG_KPROBES
608 start = (unsigned long)__start_rodata;
609#endif
610
611 end = (unsigned long)__end_rodata;
612 start = (start + PAGE_SIZE - 1) & PAGE_MASK;
613 end &= PAGE_MASK;
614 if (end <= start)
615 return;
616
617 762
618 printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", 763 printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
619 (end - start) >> 10); 764 (end - start) >> 10);
@@ -636,6 +781,7 @@ void mark_rodata_ro(void)
636 set_memory_ro(start, (end-start) >> PAGE_SHIFT); 781 set_memory_ro(start, (end-start) >> PAGE_SHIFT);
637#endif 782#endif
638} 783}
784
639#endif 785#endif
640 786
641#ifdef CONFIG_BLK_DEV_INITRD 787#ifdef CONFIG_BLK_DEV_INITRD
@@ -657,7 +803,7 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
657 * This can happen with kdump kernels when accessing 803 * This can happen with kdump kernels when accessing
658 * firmware tables: 804 * firmware tables:
659 */ 805 */
660 if (pfn < end_pfn_map) 806 if (pfn < max_pfn_mapped)
661 return; 807 return;
662 808
663 printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n", 809 printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",