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.c64
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
53static unsigned long dma_reserve __initdata; 55static 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
571void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn) 573void __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 */
627static 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}
638EXPORT_SYMBOL_GPL(arch_add_memory); 662EXPORT_SYMBOL_GPL(arch_add_memory);
@@ -694,12 +718,12 @@ void __init mem_init(void)
694const int rodata_test_data = 0xC3; 718const int rodata_test_data = 0xC3;
695EXPORT_SYMBOL_GPL(rodata_test_data); 719EXPORT_SYMBOL_GPL(rodata_test_data);
696 720
697static int kernel_set_to_readonly; 721int kernel_set_to_readonly;
698 722
699void set_kernel_text_rw(void) 723void 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
713void set_kernel_text_ro(void) 742void 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
727void mark_rodata_ro(void) 759void 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