aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/mm/numa.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/mm/numa.c')
-rw-r--r--arch/arm64/mm/numa.c115
1 files changed, 83 insertions, 32 deletions
diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 5bb15eab6f00..778a985c8a70 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -17,6 +17,8 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20#define pr_fmt(fmt) "NUMA: " fmt
21
20#include <linux/acpi.h> 22#include <linux/acpi.h>
21#include <linux/bootmem.h> 23#include <linux/bootmem.h>
22#include <linux/memblock.h> 24#include <linux/memblock.h>
@@ -24,6 +26,7 @@
24#include <linux/of.h> 26#include <linux/of.h>
25 27
26#include <asm/acpi.h> 28#include <asm/acpi.h>
29#include <asm/sections.h>
27 30
28struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; 31struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
29EXPORT_SYMBOL(node_data); 32EXPORT_SYMBOL(node_data);
@@ -38,10 +41,9 @@ static __init int numa_parse_early_param(char *opt)
38{ 41{
39 if (!opt) 42 if (!opt)
40 return -EINVAL; 43 return -EINVAL;
41 if (!strncmp(opt, "off", 3)) { 44 if (!strncmp(opt, "off", 3))
42 pr_info("%s\n", "NUMA turned off");
43 numa_off = true; 45 numa_off = true;
44 } 46
45 return 0; 47 return 0;
46} 48}
47early_param("numa", numa_parse_early_param); 49early_param("numa", numa_parse_early_param);
@@ -93,7 +95,6 @@ void numa_clear_node(unsigned int cpu)
93 */ 95 */
94static void __init setup_node_to_cpumask_map(void) 96static void __init setup_node_to_cpumask_map(void)
95{ 97{
96 unsigned int cpu;
97 int node; 98 int node;
98 99
99 /* setup nr_node_ids if not done yet */ 100 /* setup nr_node_ids if not done yet */
@@ -106,11 +107,8 @@ static void __init setup_node_to_cpumask_map(void)
106 cpumask_clear(node_to_cpumask_map[node]); 107 cpumask_clear(node_to_cpumask_map[node]);
107 } 108 }
108 109
109 for_each_possible_cpu(cpu)
110 set_cpu_numa_node(cpu, NUMA_NO_NODE);
111
112 /* cpumask_of_node() will now work */ 110 /* cpumask_of_node() will now work */
113 pr_debug("NUMA: Node to cpumask map for %d nodes\n", nr_node_ids); 111 pr_debug("Node to cpumask map for %d nodes\n", nr_node_ids);
114} 112}
115 113
116/* 114/*
@@ -118,18 +116,77 @@ static void __init setup_node_to_cpumask_map(void)
118 */ 116 */
119void numa_store_cpu_info(unsigned int cpu) 117void numa_store_cpu_info(unsigned int cpu)
120{ 118{
121 map_cpu_to_node(cpu, numa_off ? 0 : cpu_to_node_map[cpu]); 119 map_cpu_to_node(cpu, cpu_to_node_map[cpu]);
122} 120}
123 121
124void __init early_map_cpu_to_node(unsigned int cpu, int nid) 122void __init early_map_cpu_to_node(unsigned int cpu, int nid)
125{ 123{
126 /* fallback to node 0 */ 124 /* fallback to node 0 */
127 if (nid < 0 || nid >= MAX_NUMNODES) 125 if (nid < 0 || nid >= MAX_NUMNODES || numa_off)
128 nid = 0; 126 nid = 0;
129 127
130 cpu_to_node_map[cpu] = nid; 128 cpu_to_node_map[cpu] = nid;
129
130 /*
131 * We should set the numa node of cpu0 as soon as possible, because it
132 * has already been set up online before. cpu_to_node(0) will soon be
133 * called.
134 */
135 if (!cpu)
136 set_cpu_numa_node(cpu, nid);
137}
138
139#ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA
140unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
141EXPORT_SYMBOL(__per_cpu_offset);
142
143static int __init early_cpu_to_node(int cpu)
144{
145 return cpu_to_node_map[cpu];
146}
147
148static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
149{
150 return node_distance(from, to);
131} 151}
132 152
153static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size,
154 size_t align)
155{
156 int nid = early_cpu_to_node(cpu);
157
158 return memblock_virt_alloc_try_nid(size, align,
159 __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid);
160}
161
162static void __init pcpu_fc_free(void *ptr, size_t size)
163{
164 memblock_free_early(__pa(ptr), size);
165}
166
167void __init setup_per_cpu_areas(void)
168{
169 unsigned long delta;
170 unsigned int cpu;
171 int rc;
172
173 /*
174 * Always reserve area for module percpu variables. That's
175 * what the legacy allocator did.
176 */
177 rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
178 PERCPU_DYNAMIC_RESERVE, PAGE_SIZE,
179 pcpu_cpu_distance,
180 pcpu_fc_alloc, pcpu_fc_free);
181 if (rc < 0)
182 panic("Failed to initialize percpu areas.");
183
184 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
185 for_each_possible_cpu(cpu)
186 __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
187}
188#endif
189
133/** 190/**
134 * numa_add_memblk - Set node id to memblk 191 * numa_add_memblk - Set node id to memblk
135 * @nid: NUMA node ID of the new memblk 192 * @nid: NUMA node ID of the new memblk
@@ -145,13 +202,13 @@ int __init numa_add_memblk(int nid, u64 start, u64 end)
145 202
146 ret = memblock_set_node(start, (end - start), &memblock.memory, nid); 203 ret = memblock_set_node(start, (end - start), &memblock.memory, nid);
147 if (ret < 0) { 204 if (ret < 0) {
148 pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n", 205 pr_err("memblock [0x%llx - 0x%llx] failed to add on node %d\n",
149 start, (end - 1), nid); 206 start, (end - 1), nid);
150 return ret; 207 return ret;
151 } 208 }
152 209
153 node_set(nid, numa_nodes_parsed); 210 node_set(nid, numa_nodes_parsed);
154 pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n", 211 pr_info("Adding memblock [0x%llx - 0x%llx] on node %d\n",
155 start, (end - 1), nid); 212 start, (end - 1), nid);
156 return ret; 213 return ret;
157} 214}
@@ -166,19 +223,18 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
166 void *nd; 223 void *nd;
167 int tnid; 224 int tnid;
168 225
169 pr_info("NUMA: Initmem setup node %d [mem %#010Lx-%#010Lx]\n", 226 pr_info("Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
170 nid, start_pfn << PAGE_SHIFT, 227 nid, start_pfn << PAGE_SHIFT, (end_pfn << PAGE_SHIFT) - 1);
171 (end_pfn << PAGE_SHIFT) - 1);
172 228
173 nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); 229 nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
174 nd = __va(nd_pa); 230 nd = __va(nd_pa);
175 231
176 /* report and initialize */ 232 /* report and initialize */
177 pr_info("NUMA: NODE_DATA [mem %#010Lx-%#010Lx]\n", 233 pr_info("NODE_DATA [mem %#010Lx-%#010Lx]\n",
178 nd_pa, nd_pa + nd_size - 1); 234 nd_pa, nd_pa + nd_size - 1);
179 tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); 235 tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
180 if (tnid != nid) 236 if (tnid != nid)
181 pr_info("NUMA: NODE_DATA(%d) on node %d\n", nid, tnid); 237 pr_info("NODE_DATA(%d) on node %d\n", nid, tnid);
182 238
183 node_data[nid] = nd; 239 node_data[nid] = nd;
184 memset(NODE_DATA(nid), 0, sizeof(pg_data_t)); 240 memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
@@ -235,8 +291,7 @@ static int __init numa_alloc_distance(void)
235 numa_distance[i * numa_distance_cnt + j] = i == j ? 291 numa_distance[i * numa_distance_cnt + j] = i == j ?
236 LOCAL_DISTANCE : REMOTE_DISTANCE; 292 LOCAL_DISTANCE : REMOTE_DISTANCE;
237 293
238 pr_debug("NUMA: Initialized distance table, cnt=%d\n", 294 pr_debug("Initialized distance table, cnt=%d\n", numa_distance_cnt);
239 numa_distance_cnt);
240 295
241 return 0; 296 return 0;
242} 297}
@@ -257,20 +312,20 @@ static int __init numa_alloc_distance(void)
257void __init numa_set_distance(int from, int to, int distance) 312void __init numa_set_distance(int from, int to, int distance)
258{ 313{
259 if (!numa_distance) { 314 if (!numa_distance) {
260 pr_warn_once("NUMA: Warning: distance table not allocated yet\n"); 315 pr_warn_once("Warning: distance table not allocated yet\n");
261 return; 316 return;
262 } 317 }
263 318
264 if (from >= numa_distance_cnt || to >= numa_distance_cnt || 319 if (from >= numa_distance_cnt || to >= numa_distance_cnt ||
265 from < 0 || to < 0) { 320 from < 0 || to < 0) {
266 pr_warn_once("NUMA: Warning: node ids are out of bound, from=%d to=%d distance=%d\n", 321 pr_warn_once("Warning: node ids are out of bound, from=%d to=%d distance=%d\n",
267 from, to, distance); 322 from, to, distance);
268 return; 323 return;
269 } 324 }
270 325
271 if ((u8)distance != distance || 326 if ((u8)distance != distance ||
272 (from == to && distance != LOCAL_DISTANCE)) { 327 (from == to && distance != LOCAL_DISTANCE)) {
273 pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n", 328 pr_warn_once("Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
274 from, to, distance); 329 from, to, distance);
275 return; 330 return;
276 } 331 }
@@ -297,7 +352,7 @@ static int __init numa_register_nodes(void)
297 /* Check that valid nid is set to memblks */ 352 /* Check that valid nid is set to memblks */
298 for_each_memblock(memory, mblk) 353 for_each_memblock(memory, mblk)
299 if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) { 354 if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) {
300 pr_warn("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n", 355 pr_warn("Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
301 mblk->nid, mblk->base, 356 mblk->nid, mblk->base,
302 mblk->base + mblk->size - 1); 357 mblk->base + mblk->size - 1);
303 return -EINVAL; 358 return -EINVAL;
@@ -335,8 +390,10 @@ static int __init numa_init(int (*init_func)(void))
335 if (ret < 0) 390 if (ret < 0)
336 return ret; 391 return ret;
337 392
338 if (nodes_empty(numa_nodes_parsed)) 393 if (nodes_empty(numa_nodes_parsed)) {
394 pr_info("No NUMA configuration found\n");
339 return -EINVAL; 395 return -EINVAL;
396 }
340 397
341 ret = numa_register_nodes(); 398 ret = numa_register_nodes();
342 if (ret < 0) 399 if (ret < 0)
@@ -344,10 +401,6 @@ static int __init numa_init(int (*init_func)(void))
344 401
345 setup_node_to_cpumask_map(); 402 setup_node_to_cpumask_map();
346 403
347 /* init boot processor */
348 cpu_to_node_map[0] = 0;
349 map_cpu_to_node(0, 0);
350
351 return 0; 404 return 0;
352} 405}
353 406
@@ -367,10 +420,8 @@ static int __init dummy_numa_init(void)
367 420
368 if (numa_off) 421 if (numa_off)
369 pr_info("NUMA disabled\n"); /* Forced off on command line. */ 422 pr_info("NUMA disabled\n"); /* Forced off on command line. */
370 else 423 pr_info("Faking a node at [mem %#018Lx-%#018Lx]\n",
371 pr_info("No NUMA configuration found\n"); 424 0LLU, PFN_PHYS(max_pfn) - 1);
372 pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
373 0LLU, PFN_PHYS(max_pfn) - 1);
374 425
375 for_each_memblock(memory, mblk) { 426 for_each_memblock(memory, mblk) {
376 ret = numa_add_memblk(0, mblk->base, mblk->base + mblk->size); 427 ret = numa_add_memblk(0, mblk->base, mblk->base + mblk->size);