diff options
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r-- | arch/x86/mm/init_64.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 5a4398a6006b..ee41bba315d1 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/memory_hotplug.h> | 30 | #include <linux/memory_hotplug.h> |
31 | #include <linux/nmi.h> | 31 | #include <linux/nmi.h> |
32 | #include <linux/gfp.h> | ||
32 | 33 | ||
33 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
34 | #include <asm/bios_ebda.h> | 35 | #include <asm/bios_ebda.h> |
@@ -49,6 +50,7 @@ | |||
49 | #include <asm/numa.h> | 50 | #include <asm/numa.h> |
50 | #include <asm/cacheflush.h> | 51 | #include <asm/cacheflush.h> |
51 | #include <asm/init.h> | 52 | #include <asm/init.h> |
53 | #include <linux/bootmem.h> | ||
52 | 54 | ||
53 | static unsigned long dma_reserve __initdata; | 55 | static unsigned long dma_reserve __initdata; |
54 | 56 | ||
@@ -568,8 +570,10 @@ kernel_physical_mapping_init(unsigned long start, | |||
568 | } | 570 | } |
569 | 571 | ||
570 | #ifndef CONFIG_NUMA | 572 | #ifndef CONFIG_NUMA |
571 | void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn) | 573 | void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn, |
574 | int acpi, int k8) | ||
572 | { | 575 | { |
576 | #ifndef CONFIG_NO_BOOTMEM | ||
573 | unsigned long bootmap_size, bootmap; | 577 | unsigned long bootmap_size, bootmap; |
574 | 578 | ||
575 | bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; | 579 | bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; |
@@ -577,13 +581,15 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn) | |||
577 | PAGE_SIZE); | 581 | PAGE_SIZE); |
578 | if (bootmap == -1L) | 582 | if (bootmap == -1L) |
579 | panic("Cannot find bootmem map of size %ld\n", bootmap_size); | 583 | panic("Cannot find bootmem map of size %ld\n", bootmap_size); |
584 | reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP"); | ||
580 | /* don't touch min_low_pfn */ | 585 | /* don't touch min_low_pfn */ |
581 | bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT, | 586 | bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT, |
582 | 0, end_pfn); | 587 | 0, end_pfn); |
583 | e820_register_active_regions(0, start_pfn, end_pfn); | 588 | e820_register_active_regions(0, start_pfn, end_pfn); |
584 | free_bootmem_with_active_regions(0, end_pfn); | 589 | free_bootmem_with_active_regions(0, end_pfn); |
585 | early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT); | 590 | #else |
586 | reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT); | 591 | e820_register_active_regions(0, start_pfn, end_pfn); |
592 | #endif | ||
587 | } | 593 | } |
588 | #endif | 594 | #endif |
589 | 595 | ||
@@ -615,6 +621,21 @@ void __init paging_init(void) | |||
615 | */ | 621 | */ |
616 | #ifdef CONFIG_MEMORY_HOTPLUG | 622 | #ifdef CONFIG_MEMORY_HOTPLUG |
617 | /* | 623 | /* |
624 | * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need | ||
625 | * updating. | ||
626 | */ | ||
627 | static void update_end_of_memory_vars(u64 start, u64 size) | ||
628 | { | ||
629 | unsigned long end_pfn = PFN_UP(start + size); | ||
630 | |||
631 | if (end_pfn > max_pfn) { | ||
632 | max_pfn = end_pfn; | ||
633 | max_low_pfn = end_pfn; | ||
634 | high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; | ||
635 | } | ||
636 | } | ||
637 | |||
638 | /* | ||
618 | * Memory is added always to NORMAL zone. This means you will never get | 639 | * Memory is added always to NORMAL zone. This means you will never get |
619 | * additional DMA/DMA32 memory. | 640 | * additional DMA/DMA32 memory. |
620 | */ | 641 | */ |
@@ -633,6 +654,9 @@ int arch_add_memory(int nid, u64 start, u64 size) | |||
633 | ret = __add_pages(nid, zone, start_pfn, nr_pages); | 654 | ret = __add_pages(nid, zone, start_pfn, nr_pages); |
634 | WARN_ON_ONCE(ret); | 655 | WARN_ON_ONCE(ret); |
635 | 656 | ||
657 | /* update max_pfn, max_low_pfn and high_memory */ | ||
658 | update_end_of_memory_vars(start, size); | ||
659 | |||
636 | return ret; | 660 | return ret; |
637 | } | 661 | } |
638 | EXPORT_SYMBOL_GPL(arch_add_memory); | 662 | EXPORT_SYMBOL_GPL(arch_add_memory); |
@@ -694,12 +718,12 @@ void __init mem_init(void) | |||
694 | const int rodata_test_data = 0xC3; | 718 | const int rodata_test_data = 0xC3; |
695 | EXPORT_SYMBOL_GPL(rodata_test_data); | 719 | EXPORT_SYMBOL_GPL(rodata_test_data); |
696 | 720 | ||
697 | static int kernel_set_to_readonly; | 721 | int kernel_set_to_readonly; |
698 | 722 | ||
699 | void set_kernel_text_rw(void) | 723 | void set_kernel_text_rw(void) |
700 | { | 724 | { |
701 | unsigned long start = PFN_ALIGN(_stext); | 725 | unsigned long start = PFN_ALIGN(_text); |
702 | unsigned long end = PFN_ALIGN(__start_rodata); | 726 | unsigned long end = PFN_ALIGN(__stop___ex_table); |
703 | 727 | ||
704 | if (!kernel_set_to_readonly) | 728 | if (!kernel_set_to_readonly) |
705 | return; | 729 | return; |
@@ -707,13 +731,18 @@ void set_kernel_text_rw(void) | |||
707 | pr_debug("Set kernel text: %lx - %lx for read write\n", | 731 | pr_debug("Set kernel text: %lx - %lx for read write\n", |
708 | start, end); | 732 | start, end); |
709 | 733 | ||
734 | /* | ||
735 | * Make the kernel identity mapping for text RW. Kernel text | ||
736 | * mapping will always be RO. Refer to the comment in | ||
737 | * static_protections() in pageattr.c | ||
738 | */ | ||
710 | set_memory_rw(start, (end - start) >> PAGE_SHIFT); | 739 | set_memory_rw(start, (end - start) >> PAGE_SHIFT); |
711 | } | 740 | } |
712 | 741 | ||
713 | void set_kernel_text_ro(void) | 742 | void set_kernel_text_ro(void) |
714 | { | 743 | { |
715 | unsigned long start = PFN_ALIGN(_stext); | 744 | unsigned long start = PFN_ALIGN(_text); |
716 | unsigned long end = PFN_ALIGN(__start_rodata); | 745 | unsigned long end = PFN_ALIGN(__stop___ex_table); |
717 | 746 | ||
718 | if (!kernel_set_to_readonly) | 747 | if (!kernel_set_to_readonly) |
719 | return; | 748 | return; |
@@ -721,14 +750,21 @@ void set_kernel_text_ro(void) | |||
721 | pr_debug("Set kernel text: %lx - %lx for read only\n", | 750 | pr_debug("Set kernel text: %lx - %lx for read only\n", |
722 | start, end); | 751 | start, end); |
723 | 752 | ||
753 | /* | ||
754 | * Set the kernel identity mapping for text RO. | ||
755 | */ | ||
724 | set_memory_ro(start, (end - start) >> PAGE_SHIFT); | 756 | set_memory_ro(start, (end - start) >> PAGE_SHIFT); |
725 | } | 757 | } |
726 | 758 | ||
727 | void mark_rodata_ro(void) | 759 | void mark_rodata_ro(void) |
728 | { | 760 | { |
729 | unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); | 761 | unsigned long start = PFN_ALIGN(_text); |
730 | unsigned long rodata_start = | 762 | unsigned long rodata_start = |
731 | ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; | 763 | ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; |
764 | unsigned long end = (unsigned long) &__end_rodata_hpage_align; | ||
765 | unsigned long text_end = PAGE_ALIGN((unsigned long) &__stop___ex_table); | ||
766 | unsigned long rodata_end = PAGE_ALIGN((unsigned long) &__end_rodata); | ||
767 | unsigned long data_start = (unsigned long) &_sdata; | ||
732 | 768 | ||
733 | printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", | 769 | printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", |
734 | (end - start) >> 10); | 770 | (end - start) >> 10); |
@@ -751,6 +787,14 @@ void mark_rodata_ro(void) | |||
751 | printk(KERN_INFO "Testing CPA: again\n"); | 787 | printk(KERN_INFO "Testing CPA: again\n"); |
752 | set_memory_ro(start, (end-start) >> PAGE_SHIFT); | 788 | set_memory_ro(start, (end-start) >> PAGE_SHIFT); |
753 | #endif | 789 | #endif |
790 | |||
791 | free_init_pages("unused kernel memory", | ||
792 | (unsigned long) page_address(virt_to_page(text_end)), | ||
793 | (unsigned long) | ||
794 | page_address(virt_to_page(rodata_start))); | ||
795 | free_init_pages("unused kernel memory", | ||
796 | (unsigned long) page_address(virt_to_page(rodata_end)), | ||
797 | (unsigned long) page_address(virt_to_page(data_start))); | ||
754 | } | 798 | } |
755 | 799 | ||
756 | #endif | 800 | #endif |
@@ -934,7 +978,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node) | |||
934 | if (pmd_none(*pmd)) { | 978 | if (pmd_none(*pmd)) { |
935 | pte_t entry; | 979 | pte_t entry; |
936 | 980 | ||
937 | p = vmemmap_alloc_block(PMD_SIZE, node); | 981 | p = vmemmap_alloc_block_buf(PMD_SIZE, node); |
938 | if (!p) | 982 | if (!p) |
939 | return -ENOMEM; | 983 | return -ENOMEM; |
940 | 984 | ||