OSDN Git Service

Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 12 Jan 2012 03:12:10 +0000 (19:12 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 12 Jan 2012 03:12:10 +0000 (19:12 -0800)
* 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/numa: Add constraints check for nid parameters
  mm, x86: Remove debug_pagealloc_enabled
  x86/mm: Initialize high mem before free_all_bootmem()
  arch/x86/kernel/e820.c: quiet sparse noise about plain integer as NULL pointer
  arch/x86/kernel/e820.c: Eliminate bubble sort from sanitize_e820_map()
  x86: Fix mmap random address range
  x86, mm: Unify zone_sizes_init()
  x86, mm: Prepare zone_sizes_init() for unification
  x86, mm: Use max_low_pfn for ZONE_NORMAL on 64-bit
  x86, mm: Wrap ZONE_DMA32 with CONFIG_ZONE_DMA32
  x86, mm: Use max_pfn instead of highend_pfn
  x86, mm: Move zone init from paging_init() on 64-bit
  x86, mm: Use MAX_DMA_PFN for ZONE_DMA on 32-bit

1  2 
arch/x86/kernel/e820.c
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/numa.c
arch/x86/mm/pageattr.c
include/linux/mm.h
init/main.c

diff --combined arch/x86/kernel/e820.c
@@@ -19,6 -19,7 +19,7 @@@
  #include <linux/acpi.h>
  #include <linux/firmware-map.h>
  #include <linux/memblock.h>
+ #include <linux/sort.h>
  
  #include <asm/e820.h>
  #include <asm/proto.h>
@@@ -227,22 -228,38 +228,38 @@@ void __init e820_print_map(char *who
   *       ____________________33__
   *       ______________________4_
   */
+ struct change_member {
+       struct e820entry *pbios; /* pointer to original bios entry */
+       unsigned long long addr; /* address for this change point */
+ };
+ static int __init cpcompare(const void *a, const void *b)
+ {
+       struct change_member * const *app = a, * const *bpp = b;
+       const struct change_member *ap = *app, *bp = *bpp;
+       /*
+        * Inputs are pointers to two elements of change_point[].  If their
+        * addresses are unequal, their difference dominates.  If the addresses
+        * are equal, then consider one that represents the end of its region
+        * to be greater than one that does not.
+        */
+       if (ap->addr != bp->addr)
+               return ap->addr > bp->addr ? 1 : -1;
+       return (ap->addr != ap->pbios->addr) - (bp->addr != bp->pbios->addr);
+ }
  
  int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map,
                             u32 *pnr_map)
  {
-       struct change_member {
-               struct e820entry *pbios; /* pointer to original bios entry */
-               unsigned long long addr; /* address for this change point */
-       };
        static struct change_member change_point_list[2*E820_X_MAX] __initdata;
        static struct change_member *change_point[2*E820_X_MAX] __initdata;
        static struct e820entry *overlap_list[E820_X_MAX] __initdata;
        static struct e820entry new_bios[E820_X_MAX] __initdata;
-       struct change_member *change_tmp;
        unsigned long current_type, last_type;
        unsigned long long last_addr;
-       int chgidx, still_changing;
+       int chgidx;
        int overlap_entries;
        int new_bios_entry;
        int old_nr, new_nr, chg_nr;
        chg_nr = chgidx;
  
        /* sort change-point list by memory addresses (low -> high) */
-       still_changing = 1;
-       while (still_changing)  {
-               still_changing = 0;
-               for (i = 1; i < chg_nr; i++)  {
-                       unsigned long long curaddr, lastaddr;
-                       unsigned long long curpbaddr, lastpbaddr;
-                       curaddr = change_point[i]->addr;
-                       lastaddr = change_point[i - 1]->addr;
-                       curpbaddr = change_point[i]->pbios->addr;
-                       lastpbaddr = change_point[i - 1]->pbios->addr;
-                       /*
-                        * swap entries, when:
-                        *
-                        * curaddr > lastaddr or
-                        * curaddr == lastaddr and curaddr == curpbaddr and
-                        * lastaddr != lastpbaddr
-                        */
-                       if (curaddr < lastaddr ||
-                           (curaddr == lastaddr && curaddr == curpbaddr &&
-                            lastaddr != lastpbaddr)) {
-                               change_tmp = change_point[i];
-                               change_point[i] = change_point[i-1];
-                               change_point[i-1] = change_tmp;
-                               still_changing = 1;
-                       }
-               }
-       }
+       sort(change_point, chg_nr, sizeof *change_point, cpcompare, NULL);
  
        /* create a new bios memory map, removing overlaps */
        overlap_entries = 0;     /* number of entries in the overlap table */
@@@ -738,17 -727,35 +727,17 @@@ core_initcall(e820_mark_nvs_memory)
  /*
   * pre allocated 4k and reserved it in memblock and e820_saved
   */
 -u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
 +u64 __init early_reserve_e820(u64 size, u64 align)
  {
 -      u64 size = 0;
        u64 addr;
 -      u64 start;
  
 -      for (start = startt; ; start += size) {
 -              start = memblock_x86_find_in_range_size(start, &size, align);
 -              if (start == MEMBLOCK_ERROR)
 -                      return 0;
 -              if (size >= sizet)
 -                      break;
 +      addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
 +      if (addr) {
 +              e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED);
 +              printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
 +              update_e820_saved();
        }
  
 -#ifdef CONFIG_X86_32
 -      if (start >= MAXMEM)
 -              return 0;
 -      if (start + size > MAXMEM)
 -              size = MAXMEM - start;
 -#endif
 -
 -      addr = round_down(start + size - sizet, align);
 -      if (addr < start)
 -              return 0;
 -      memblock_x86_reserve_range(addr, addr + sizet, "new next");
 -      e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
 -      printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
 -      update_e820_saved();
 -
        return addr;
  }
  
@@@ -1072,7 -1079,7 +1061,7 @@@ void __init memblock_x86_fill(void
         * We are safe to enable resizing, beause memblock_x86_fill()
         * is rather later for x86
         */
 -      memblock_can_resize = 1;
 +      memblock_allow_resize();
  
        for (i = 0; i < e820.nr_map; i++) {
                struct e820entry *ei = &e820.map[i];
                memblock_add(ei->addr, ei->size);
        }
  
 -      memblock_analyze();
        memblock_dump_all();
  }
  
  void __init memblock_find_dma_reserve(void)
  {
  #ifdef CONFIG_X86_64
 -      u64 free_size_pfn;
 -      u64 mem_size_pfn;
 +      u64 nr_pages = 0, nr_free_pages = 0;
 +      unsigned long start_pfn, end_pfn;
 +      phys_addr_t start, end;
 +      int i;
 +      u64 u;
 +
        /*
         * need to find out used area below MAX_DMA_PFN
         * need to use memblock to get free size in [0, MAX_DMA_PFN]
         * at first, and assume boot_mem will not take below MAX_DMA_PFN
         */
 -      mem_size_pfn = memblock_x86_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
 -      free_size_pfn = memblock_x86_free_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
 -      set_dma_reserve(mem_size_pfn - free_size_pfn);
 +      for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
 +              start_pfn = min_t(unsigned long, start_pfn, MAX_DMA_PFN);
 +              end_pfn = min_t(unsigned long, end_pfn, MAX_DMA_PFN);
 +              nr_pages += end_pfn - start_pfn;
 +      }
 +
 +      for_each_free_mem_range(u, MAX_NUMNODES, &start, &end, NULL) {
 +              start_pfn = min_t(unsigned long, PFN_UP(start), MAX_DMA_PFN);
 +              end_pfn = min_t(unsigned long, PFN_DOWN(end), MAX_DMA_PFN);
 +              if (start_pfn < end_pfn)
 +                      nr_free_pages += end_pfn - start_pfn;
 +      }
 +
 +      set_dma_reserve(nr_pages - nr_free_pages);
  #endif
  }
diff --combined arch/x86/mm/init.c
@@@ -3,6 -3,7 +3,7 @@@
  #include <linux/ioport.h>
  #include <linux/swap.h>
  #include <linux/memblock.h>
+ #include <linux/bootmem.h>    /* for max_low_pfn */
  
  #include <asm/cacheflush.h>
  #include <asm/e820.h>
@@@ -15,6 -16,7 +16,7 @@@
  #include <asm/tlbflush.h>
  #include <asm/tlb.h>
  #include <asm/proto.h>
+ #include <asm/dma.h>          /* for MAX_DMA_PFN */
  
  unsigned long __initdata pgt_buf_start;
  unsigned long __meminitdata pgt_buf_end;
@@@ -67,7 -69,7 +69,7 @@@ static void __init find_early_table_spa
        good_end = max_pfn_mapped << PAGE_SHIFT;
  
        base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE);
 -      if (base == MEMBLOCK_ERROR)
 +      if (!base)
                panic("Cannot find space for the kernel page tables");
  
        pgt_buf_start = base >> PAGE_SHIFT;
@@@ -80,7 -82,7 +82,7 @@@
  
  void __init native_pagetable_reserve(u64 start, u64 end)
  {
 -      memblock_x86_reserve_range(start, end, "PGTABLE");
 +      memblock_reserve(start, end - start);
  }
  
  struct map_range {
@@@ -279,8 -281,8 +281,8 @@@ unsigned long __init_refok init_memory_
         * pgt_buf_end) and free the other ones (pgt_buf_end - pgt_buf_top)
         * so that they can be reused for other purposes.
         *
 -       * On native it just means calling memblock_x86_reserve_range, on Xen it
 -       * also means marking RW the pagetable pages that we allocated before
 +       * On native it just means calling memblock_reserve, on Xen it also
 +       * means marking RW the pagetable pages that we allocated before
         * but that haven't been used.
         *
         * In fact on xen we mark RO the whole range pgt_buf_start -
@@@ -392,3 -394,24 +394,24 @@@ void free_initrd_mem(unsigned long star
        free_init_pages("initrd memory", start, PAGE_ALIGN(end));
  }
  #endif
+ void __init zone_sizes_init(void)
+ {
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
+       memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ #ifdef CONFIG_ZONE_DMA
+       max_zone_pfns[ZONE_DMA]         = MAX_DMA_PFN;
+ #endif
+ #ifdef CONFIG_ZONE_DMA32
+       max_zone_pfns[ZONE_DMA32]       = MAX_DMA32_PFN;
+ #endif
+       max_zone_pfns[ZONE_NORMAL]      = max_low_pfn;
+ #ifdef CONFIG_HIGHMEM
+       max_zone_pfns[ZONE_HIGHMEM]     = max_pfn;
+ #endif
+       free_area_init_nodes(max_zone_pfns);
+ }
diff --combined arch/x86/mm/init_32.c
@@@ -427,17 -427,23 +427,17 @@@ static void __init add_one_highpage_ini
  void __init add_highpages_with_active_regions(int nid,
                         unsigned long start_pfn, unsigned long end_pfn)
  {
 -      struct range *range;
 -      int nr_range;
 -      int i;
 -
 -      nr_range = __get_free_all_memory_range(&range, nid, start_pfn, end_pfn);
 -
 -      for (i = 0; i < nr_range; i++) {
 -              struct page *page;
 -              int node_pfn;
 -
 -              for (node_pfn = range[i].start; node_pfn < range[i].end;
 -                   node_pfn++) {
 -                      if (!pfn_valid(node_pfn))
 -                              continue;
 -                      page = pfn_to_page(node_pfn);
 -                      add_one_highpage_init(page);
 -              }
 +      phys_addr_t start, end;
 +      u64 i;
 +
 +      for_each_free_mem_range(i, nid, &start, &end, NULL) {
 +              unsigned long pfn = clamp_t(unsigned long, PFN_UP(start),
 +                                          start_pfn, end_pfn);
 +              unsigned long e_pfn = clamp_t(unsigned long, PFN_DOWN(end),
 +                                            start_pfn, end_pfn);
 +              for ( ; pfn < e_pfn; pfn++)
 +                      if (pfn_valid(pfn))
 +                              add_one_highpage_init(pfn_to_page(pfn));
        }
  }
  #else
@@@ -644,18 -650,18 +644,18 @@@ void __init initmem_init(void
        highstart_pfn = highend_pfn = max_pfn;
        if (max_pfn > max_low_pfn)
                highstart_pfn = max_low_pfn;
 -      memblock_x86_register_active_regions(0, 0, highend_pfn);
 -      sparse_memory_present_with_active_regions(0);
        printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
                pages_to_mb(highend_pfn - highstart_pfn));
        num_physpages = highend_pfn;
        high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
  #else
 -      memblock_x86_register_active_regions(0, 0, max_low_pfn);
 -      sparse_memory_present_with_active_regions(0);
        num_physpages = max_low_pfn;
        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
  #endif
 +
 +      memblock_set_node(0, (phys_addr_t)ULLONG_MAX, 0);
 +      sparse_memory_present_with_active_regions(0);
 +
  #ifdef CONFIG_FLATMEM
        max_mapnr = num_physpages;
  #endif
  }
  #endif /* !CONFIG_NEED_MULTIPLE_NODES */
  
- static void __init zone_sizes_init(void)
- {
-       unsigned long max_zone_pfns[MAX_NR_ZONES];
-       memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
- #ifdef CONFIG_ZONE_DMA
-       max_zone_pfns[ZONE_DMA] =
-               virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
- #endif
-       max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
- #ifdef CONFIG_HIGHMEM
-       max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
- #endif
-       free_area_init_nodes(max_zone_pfns);
- }
  void __init setup_bootmem_allocator(void)
  {
        printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
@@@ -754,6 -744,17 +738,17 @@@ void __init mem_init(void
  #ifdef CONFIG_FLATMEM
        BUG_ON(!mem_map);
  #endif
+       /*
+        * With CONFIG_DEBUG_PAGEALLOC initialization of highmem pages has to
+        * be done before free_all_bootmem(). Memblock use free low memory for
+        * temporary data (see find_range_array()) and for this purpose can use
+        * pages that was already passed to the buddy allocator, hence marked as
+        * not accessible in the page tables when compiled with
+        * CONFIG_DEBUG_PAGEALLOC. Otherwise order of initialization is not
+        * important here.
+        */
+       set_highmem_pages_init();
        /* this will put all low memory onto the freelists */
        totalram_pages += free_all_bootmem();
  
                if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
                        reservedpages++;
  
-       set_highmem_pages_init();
        codesize =  (unsigned long) &_etext - (unsigned long) &_text;
        datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
        initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
diff --combined arch/x86/mm/init_64.c
@@@ -608,21 -608,12 +608,12 @@@ kernel_physical_mapping_init(unsigned l
  #ifndef CONFIG_NUMA
  void __init initmem_init(void)
  {
 -      memblock_x86_register_active_regions(0, 0, max_pfn);
 +      memblock_set_node(0, (phys_addr_t)ULLONG_MAX, 0);
  }
  #endif
  
  void __init paging_init(void)
  {
-       unsigned long max_zone_pfns[MAX_NR_ZONES];
-       memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
- #ifdef CONFIG_ZONE_DMA
-       max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
- #endif
-       max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
-       max_zone_pfns[ZONE_NORMAL] = max_pfn;
        sparse_memory_present_with_active_regions(MAX_NUMNODES);
        sparse_init();
  
         */
        node_clear_state(0, N_NORMAL_MEMORY);
  
-       free_area_init_nodes(max_zone_pfns);
+       zone_sizes_init();
  }
  
  /*
diff --combined arch/x86/mm/numa.c
@@@ -192,6 -192,8 +192,6 @@@ int __init numa_add_memblk(int nid, u6
  /* Initialize NODE_DATA for a node on the local memory */
  static void __init setup_node_data(int nid, u64 start, u64 end)
  {
 -      const u64 nd_low = PFN_PHYS(MAX_DMA_PFN);
 -      const u64 nd_high = PFN_PHYS(max_pfn_mapped);
        const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
        bool remapped = false;
        u64 nd_pa;
                nd_pa = __pa(nd);
                remapped = true;
        } else {
 -              nd_pa = memblock_x86_find_in_range_node(nid, nd_low, nd_high,
 -                                              nd_size, SMP_CACHE_BYTES);
 -              if (nd_pa == MEMBLOCK_ERROR)
 -                      nd_pa = memblock_find_in_range(nd_low, nd_high,
 -                                              nd_size, SMP_CACHE_BYTES);
 -              if (nd_pa == MEMBLOCK_ERROR) {
 +              nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid);
 +              if (!nd_pa) {
                        pr_err("Cannot find %zu bytes in node %d\n",
                               nd_size, nid);
                        return;
                }
 -              memblock_x86_reserve_range(nd_pa, nd_pa + nd_size, "NODE_DATA");
                nd = __va(nd_pa);
        }
  
@@@ -364,7 -371,8 +364,7 @@@ void __init numa_reset_distance(void
  
        /* numa_distance could be 1LU marking allocation failure, test cnt */
        if (numa_distance_cnt)
 -              memblock_x86_free_range(__pa(numa_distance),
 -                                      __pa(numa_distance) + size);
 +              memblock_free(__pa(numa_distance), size);
        numa_distance_cnt = 0;
        numa_distance = NULL;   /* enable table creation */
  }
@@@ -387,13 -395,13 +387,13 @@@ static int __init numa_alloc_distance(v
  
        phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
                                      size, PAGE_SIZE);
 -      if (phys == MEMBLOCK_ERROR) {
 +      if (!phys) {
                pr_warning("NUMA: Warning: can't allocate distance table!\n");
                /* don't retry until explicitly reset */
                numa_distance = (void *)1LU;
                return -ENOMEM;
        }
 -      memblock_x86_reserve_range(phys, phys + size, "NUMA DIST");
 +      memblock_reserve(phys, size);
  
        numa_distance = __va(phys);
        numa_distance_cnt = cnt;
   * calls are ignored until the distance table is reset with
   * numa_reset_distance().
   *
-  * If @from or @to is higher than the highest known node at the time of
-  * table creation or @distance doesn't make sense, the call is ignored.
+  * If @from or @to is higher than the highest known node or lower than zero
+  * at the time of table creation or @distance doesn't make sense, the call
+  * is ignored.
   * This is to allow simplification of specific NUMA config implementations.
   */
  void __init numa_set_distance(int from, int to, int distance)
        if (!numa_distance && numa_alloc_distance() < 0)
                return;
  
-       if (from >= numa_distance_cnt || to >= numa_distance_cnt) {
-               printk_once(KERN_DEBUG "NUMA: Debug: distance out of bound, from=%d to=%d distance=%d\n",
+       if (from >= numa_distance_cnt || to >= numa_distance_cnt ||
+                       from < 0 || to < 0) {
+               pr_warn_once("NUMA: Warning: node ids are out of bound, from=%d to=%d distance=%d\n",
                            from, to, distance);
                return;
        }
@@@ -474,8 -484,8 +476,8 @@@ static bool __init numa_meminfo_cover_m
                        numaram = 0;
        }
  
 -      e820ram = max_pfn - (memblock_x86_hole_size(0,
 -                                      PFN_PHYS(max_pfn)) >> PAGE_SHIFT);
 +      e820ram = max_pfn - absent_pages_in_range(0, max_pfn);
 +
        /* We seem to lose 3 pages somewhere. Allow 1M of slack. */
        if ((s64)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) {
                printk(KERN_ERR "NUMA: nodes only cover %LuMB of your %LuMB e820 RAM. Not used.\n",
@@@ -497,10 -507,13 +499,10 @@@ static int __init numa_register_memblks
        if (WARN_ON(nodes_empty(node_possible_map)))
                return -EINVAL;
  
 -      for (i = 0; i < mi->nr_blks; i++)
 -              memblock_x86_register_active_regions(mi->blk[i].nid,
 -                                      mi->blk[i].start >> PAGE_SHIFT,
 -                                      mi->blk[i].end >> PAGE_SHIFT);
 -
 -      /* for out of order entries */
 -      sort_node_map();
 +      for (i = 0; i < mi->nr_blks; i++) {
 +              struct numa_memblk *mb = &mi->blk[i];
 +              memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
 +      }
  
        /*
         * If sections array is gonna be used for pfn -> nid mapping, check
                        setup_node_data(nid, start, end);
        }
  
 +      /* Dump memblock with node info and return. */
 +      memblock_dump_all();
        return 0;
  }
  
@@@ -573,7 -584,7 +575,7 @@@ static int __init numa_init(int (*init_
        nodes_clear(node_possible_map);
        nodes_clear(node_online_map);
        memset(&numa_meminfo, 0, sizeof(numa_meminfo));
 -      remove_all_active_ranges();
 +      WARN_ON(memblock_set_node(0, ULLONG_MAX, MAX_NUMNODES));
        numa_reset_distance();
  
        ret = init_func();
diff --combined arch/x86/mm/pageattr.c
@@@ -998,7 -998,7 +998,7 @@@ out_err
  }
  EXPORT_SYMBOL(set_memory_uc);
  
 -int _set_memory_array(unsigned long *addr, int addrinarray,
 +static int _set_memory_array(unsigned long *addr, int addrinarray,
                unsigned long new_type)
  {
        int i, j;
@@@ -1334,12 -1334,6 +1334,6 @@@ void kernel_map_pages(struct page *page
        }
  
        /*
-        * If page allocator is not up yet then do not call c_p_a():
-        */
-       if (!debug_pagealloc_enabled)
-               return;
-       /*
         * The return value is ignored as the calls cannot fail.
         * Large pages for identity mappings are not used at boot time
         * and hence no memory allocations during large page split.
diff --combined include/linux/mm.h
@@@ -10,7 -10,6 +10,7 @@@
  #include <linux/mmzone.h>
  #include <linux/rbtree.h>
  #include <linux/prio_tree.h>
 +#include <linux/atomic.h>
  #include <linux/debug_locks.h>
  #include <linux/mm_types.h>
  #include <linux/range.h>
@@@ -1253,34 -1252,41 +1253,34 @@@ static inline void pgtable_page_dtor(st
  extern void free_area_init(unsigned long * zones_size);
  extern void free_area_init_node(int nid, unsigned long * zones_size,
                unsigned long zone_start_pfn, unsigned long *zholes_size);
 -#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
 +#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
  /*
 - * With CONFIG_ARCH_POPULATES_NODE_MAP set, an architecture may initialise its
 + * With CONFIG_HAVE_MEMBLOCK_NODE_MAP set, an architecture may initialise its
   * zones, allocate the backing mem_map and account for memory holes in a more
   * architecture independent manner. This is a substitute for creating the
   * zone_sizes[] and zholes_size[] arrays and passing them to
   * free_area_init_node()
   *
   * An architecture is expected to register range of page frames backed by
 - * physical memory with add_active_range() before calling
 + * physical memory with memblock_add[_node]() before calling
   * free_area_init_nodes() passing in the PFN each zone ends at. At a basic
   * usage, an architecture is expected to do something like
   *
   * unsigned long max_zone_pfns[MAX_NR_ZONES] = {max_dma, max_normal_pfn,
   *                                                     max_highmem_pfn};
   * for_each_valid_physical_page_range()
 - *    add_active_range(node_id, start_pfn, end_pfn)
 + *    memblock_add_node(base, size, nid)
   * free_area_init_nodes(max_zone_pfns);
   *
 - * If the architecture guarantees that there are no holes in the ranges
 - * registered with add_active_range(), free_bootmem_active_regions()
 - * will call free_bootmem_node() for each registered physical page range.
 - * Similarly sparse_memory_present_with_active_regions() calls
 - * memory_present() for each range when SPARSEMEM is enabled.
 + * free_bootmem_with_active_regions() calls free_bootmem_node() for each
 + * registered physical page range.  Similarly
 + * sparse_memory_present_with_active_regions() calls memory_present() for
 + * each range when SPARSEMEM is enabled.
   *
   * See mm/page_alloc.c for more information on each function exposed by
 - * CONFIG_ARCH_POPULATES_NODE_MAP
 + * CONFIG_HAVE_MEMBLOCK_NODE_MAP.
   */
  extern void free_area_init_nodes(unsigned long *max_zone_pfn);
 -extern void add_active_range(unsigned int nid, unsigned long start_pfn,
 -                                      unsigned long end_pfn);
 -extern void remove_active_range(unsigned int nid, unsigned long start_pfn,
 -                                      unsigned long end_pfn);
 -extern void remove_all_active_ranges(void);
 -void sort_node_map(void);
  unsigned long node_map_pfn_alignment(void);
  unsigned long __absent_pages_in_range(int nid, unsigned long start_pfn,
                                                unsigned long end_pfn);
@@@ -1293,11 -1299,14 +1293,11 @@@ extern void free_bootmem_with_active_re
                                                unsigned long max_low_pfn);
  int add_from_early_node_map(struct range *range, int az,
                                   int nr_range, int nid);
 -u64 __init find_memory_core_early(int nid, u64 size, u64 align,
 -                                      u64 goal, u64 limit);
 -typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
 -extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
  extern void sparse_memory_present_with_active_regions(int nid);
 -#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
  
 -#if !defined(CONFIG_ARCH_POPULATES_NODE_MAP) && \
 +#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
 +
 +#if !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) && \
      !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID)
  static inline int __early_pfn_to_nid(unsigned long pfn)
  {
@@@ -1482,18 -1491,6 +1482,18 @@@ static inline unsigned long vma_pages(s
        return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
  }
  
 +/* Look up the first VMA which exactly match the interval vm_start ... vm_end */
 +static inline struct vm_area_struct *find_exact_vma(struct mm_struct *mm,
 +                              unsigned long vm_start, unsigned long vm_end)
 +{
 +      struct vm_area_struct *vma = find_vma(mm, vm_start);
 +
 +      if (vma && (vma->vm_start != vm_start || vma->vm_end != vm_end))
 +              vma = NULL;
 +
 +      return vma;
 +}
 +
  #ifdef CONFIG_MMU
  pgprot_t vm_get_page_prot(unsigned long vm_flags);
  #else
@@@ -1540,23 -1537,13 +1540,13 @@@ static inline void vm_stat_account(stru
  #endif /* CONFIG_PROC_FS */
  
  #ifdef CONFIG_DEBUG_PAGEALLOC
- extern int debug_pagealloc_enabled;
  extern void kernel_map_pages(struct page *page, int numpages, int enable);
- static inline void enable_debug_pagealloc(void)
- {
-       debug_pagealloc_enabled = 1;
- }
  #ifdef CONFIG_HIBERNATION
  extern bool kernel_page_present(struct page *page);
  #endif /* CONFIG_HIBERNATION */
  #else
  static inline void
  kernel_map_pages(struct page *page, int numpages, int enable) {}
- static inline void enable_debug_pagealloc(void)
- {
- }
  #ifdef CONFIG_HIBERNATION
  static inline bool kernel_page_present(struct page *page) { return true; }
  #endif /* CONFIG_HIBERNATION */
@@@ -1630,22 -1617,5 +1620,22 @@@ extern void copy_user_huge_page(struct 
                                unsigned int pages_per_huge_page);
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
  
 +#ifdef CONFIG_DEBUG_PAGEALLOC
 +extern unsigned int _debug_guardpage_minorder;
 +
 +static inline unsigned int debug_guardpage_minorder(void)
 +{
 +      return _debug_guardpage_minorder;
 +}
 +
 +static inline bool page_is_guard(struct page *page)
 +{
 +      return test_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags);
 +}
 +#else
 +static inline unsigned int debug_guardpage_minorder(void) { return 0; }
 +static inline bool page_is_guard(struct page *page) { return false; }
 +#endif /* CONFIG_DEBUG_PAGEALLOC */
 +
  #endif /* __KERNEL__ */
  #endif /* _LINUX_MM_H */
diff --combined init/main.c
@@@ -282,10 -282,6 +282,6 @@@ static int __init unknown_bootoption(ch
        return 0;
  }
  
- #ifdef CONFIG_DEBUG_PAGEALLOC
- int __read_mostly debug_pagealloc_enabled = 0;
- #endif
  static int __init init_setup(char *str)
  {
        unsigned int i;
@@@ -469,12 -465,13 +465,12 @@@ asmlinkage void __init start_kernel(voi
        char * command_line;
        extern const struct kernel_param __start___param[], __stop___param[];
  
 -      smp_setup_processor_id();
 -
        /*
         * Need to run as early as possible, to initialize the
         * lockdep hash:
         */
        lockdep_init();
 +      smp_setup_processor_id();
        debug_objects_early_init();
  
        /*
        }
  #endif
        page_cgroup_init();
-       enable_debug_pagealloc();
        debug_objects_mem_init();
        kmemleak_init();
        setup_per_cpu_pageset();