acpi, numa, mem_hotplug: mark all nodes the kernel resides un-hotpluggable
[platform/adaptation/renesas_rcar/renesas_kernel.git] / arch / x86 / mm / numa.c
index 24aec58..81b2750 100644 (file)
@@ -211,9 +211,13 @@ static void __init setup_node_data(int nid, u64 start, u64 end)
         */
        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;
+               nd_pa = __memblock_alloc_base(nd_size, SMP_CACHE_BYTES,
+                                             MEMBLOCK_ALLOC_ACCESSIBLE);
+               if (!nd_pa) {
+                       pr_err("Cannot find %zu bytes in node %d\n",
+                              nd_size, nid);
+                       return;
+               }
        }
        nd = __va(nd_pa);
 
@@ -487,7 +491,16 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 
        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);
+               memblock_set_node(mb->start, mb->end - mb->start,
+                                 &memblock.memory, mb->nid);
+
+               /*
+                * At this time, all memory regions reserved by memblock are
+                * used by the kernel. Set the nid in memblock.reserved will
+                * mark out all the nodes the kernel resides in.
+                */
+               memblock_set_node(mb->start, mb->end - mb->start,
+                                 &memblock.reserved, mb->nid);
        }
 
        /*
@@ -549,6 +562,30 @@ static void __init numa_init_array(void)
        }
 }
 
+static void __init numa_clear_kernel_node_hotplug(void)
+{
+       int i, nid;
+       nodemask_t numa_kernel_nodes;
+       unsigned long start, end;
+       struct memblock_type *type = &memblock.reserved;
+
+       /* Mark all kernel nodes. */
+       for (i = 0; i < type->cnt; i++)
+               node_set(type->regions[i].nid, numa_kernel_nodes);
+
+       /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
+       for (i = 0; i < numa_meminfo.nr_blks; i++) {
+               nid = numa_meminfo.blk[i].nid;
+               if (!node_isset(nid, numa_kernel_nodes))
+                       continue;
+
+               start = numa_meminfo.blk[i].start;
+               end = numa_meminfo.blk[i].end;
+
+               memblock_clear_hotplug(start, end - start);
+       }
+}
+
 static int __init numa_init(int (*init_func)(void))
 {
        int i;
@@ -561,7 +598,12 @@ static int __init numa_init(int (*init_func)(void))
        nodes_clear(node_possible_map);
        nodes_clear(node_online_map);
        memset(&numa_meminfo, 0, sizeof(numa_meminfo));
-       WARN_ON(memblock_set_node(0, ULLONG_MAX, MAX_NUMNODES));
+       WARN_ON(memblock_set_node(0, ULLONG_MAX, &memblock.memory,
+                                 MAX_NUMNODES));
+       WARN_ON(memblock_set_node(0, ULLONG_MAX, &memblock.reserved,
+                                 MAX_NUMNODES));
+       /* In case that parsing SRAT failed. */
+       WARN_ON(memblock_clear_hotplug(0, ULLONG_MAX));
        numa_reset_distance();
 
        ret = init_func();
@@ -597,6 +639,16 @@ static int __init numa_init(int (*init_func)(void))
                        numa_clear_node(i);
        }
        numa_init_array();
+
+       /*
+        * At very early time, the kernel have to use some memory such as
+        * loading the kernel image. We cannot prevent this anyway. So any
+        * node the kernel resides in should be un-hotpluggable.
+        *
+        * And when we come here, numa_init() won't fail.
+        */
+       numa_clear_kernel_node_hotplug();
+
        return 0;
 }