x86: remove double-checking empty zero pages debug
[sfrench/cifs-2.6.git] / arch / x86 / mm / init_64.c
index eabcaed76c28a15768b057119ebd8cecb8eb90d5..6dbb0035c57aa7c4059f0b157ed7ec1bfbe6f659 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/sections.h>
 #include <asm/kdebug.h>
 #include <asm/numa.h>
+#include <asm/cacheflush.h>
 
 const struct dma_mapping_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
@@ -170,6 +171,33 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
        __flush_tlb_one(vaddr);
 }
 
+/*
+ * The head.S code sets up the kernel high mapping from:
+ * __START_KERNEL_map to __START_KERNEL_map + KERNEL_TEXT_SIZE
+ *
+ * phys_addr holds the negative offset to the kernel, which is added
+ * to the compile time generated pmds. This results in invalid pmds up
+ * to the point where we hit the physaddr 0 mapping.
+ *
+ * We limit the mappings to the region from _text to _end.  _end is
+ * rounded up to the 2MB boundary. This catches the invalid pmds as
+ * well, as they are located before _text:
+ */
+void __init cleanup_highmap(void)
+{
+       unsigned long vaddr = __START_KERNEL_map;
+       unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1;
+       pmd_t *pmd = level2_kernel_pgt;
+       pmd_t *last_pmd = pmd + PTRS_PER_PMD;
+
+       for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) {
+               if (!pmd_present(*pmd))
+                       continue;
+               if (vaddr < (unsigned long) _text || vaddr > end)
+                       set_pmd(pmd, __pmd(0));
+       }
+}
+
 /* NOTE: this is meant to be run only at boot */
 void __init
 __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
@@ -273,7 +301,6 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
        int i = pmd_index(address);
 
        for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
-               unsigned long entry;
                pmd_t *pmd = pmd_page + pmd_index(address);
 
                if (address >= end) {
@@ -287,9 +314,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
                if (pmd_val(*pmd))
                        continue;
 
-               entry = __PAGE_KERNEL_LARGE|_PAGE_GLOBAL|address;
-               entry &= __supported_pte_mask;
-               set_pmd(pmd, __pmd(entry));
+               set_pte((pte_t *)pmd,
+                       pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
        }
 }
 
@@ -434,49 +460,6 @@ void __init paging_init(void)
 }
 #endif
 
-/*
- * Unmap a kernel mapping if it exists. This is useful to avoid
- * prefetches from the CPU leading to inconsistent cache lines.
- * address and size must be aligned to 2MB boundaries.
- * Does nothing when the mapping doesn't exist.
- */
-void __init clear_kernel_mapping(unsigned long address, unsigned long size)
-{
-       unsigned long end = address + size;
-
-       BUG_ON(address & ~LARGE_PAGE_MASK);
-       BUG_ON(size & ~LARGE_PAGE_MASK);
-
-       for (; address < end; address += LARGE_PAGE_SIZE) {
-               pgd_t *pgd = pgd_offset_k(address);
-               pud_t *pud;
-               pmd_t *pmd;
-
-               if (pgd_none(*pgd))
-                       continue;
-
-               pud = pud_offset(pgd, address);
-               if (pud_none(*pud))
-                       continue;
-
-               pmd = pmd_offset(pud, address);
-               if (!pmd || pmd_none(*pmd))
-                       continue;
-
-               if (!(pmd_val(*pmd) & _PAGE_PSE)) {
-                       /*
-                        * Could handle this, but it should not happen
-                        * currently:
-                        */
-                       printk(KERN_ERR "clear_kernel_mapping: "
-                               "mapping has been split. will leak memory\n");
-                       pmd_ERROR(*pmd);
-               }
-               set_pmd(pmd, __pmd(0));
-       }
-       __flush_tlb_all();
-}
-
 /*
  * Memory hotplug specific functions
  */
@@ -532,14 +515,6 @@ void __init mem_init(void)
 
        /* clear_bss() already clear the empty_zero_page */
 
-       /* temporary debugging - double check it's true: */
-       {
-               int i;
-
-               for (i = 0; i < 1024; i++)
-                       WARN_ON_ONCE(empty_zero_page[i]);
-       }
-
        reservedpages = 0;
 
        /* this will put all low memory onto the freelists */
@@ -573,13 +548,15 @@ void __init mem_init(void)
                reservedpages << (PAGE_SHIFT-10),
                datasize >> 10,
                initsize >> 10);
+
+       cpa_init();
 }
 
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
 {
-       unsigned long addr;
+       unsigned long addr = begin;
 
-       if (begin >= end)
+       if (addr >= end)
                return;
 
        /*
@@ -594,7 +571,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
 #else
        printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
 
-       for (addr = begin; addr < end; addr += PAGE_SIZE) {
+       for (; addr < end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
                memset((void *)(addr & ~(PAGE_SIZE-1)),
@@ -636,10 +613,17 @@ void mark_rodata_ro(void)
        if (end <= start)
                return;
 
-       set_memory_ro(start, (end - start) >> PAGE_SHIFT);
 
        printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
               (end - start) >> 10);
+       set_memory_ro(start, (end - start) >> PAGE_SHIFT);
+
+       /*
+        * The rodata section (but not the kernel text!) should also be
+        * not-executable.
+        */
+       start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
+       set_memory_nx(start, (end - start) >> PAGE_SHIFT);
 
        rodata_test();
 
@@ -682,9 +666,9 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
 
        /* Should check here against the e820 map to avoid double free */
 #ifdef CONFIG_NUMA
-       reserve_bootmem_node(NODE_DATA(nid), phys, len);
+       reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
 #else
-       reserve_bootmem(phys, len);
+       reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
 #endif
        if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
                dma_reserve += len / PAGE_SIZE;