diff options
Diffstat (limited to 'arch/arm64/mm/numa.c')
-rw-r--r-- | arch/arm64/mm/numa.c | 115 |
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 | ||
28 | struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; | 31 | struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; |
29 | EXPORT_SYMBOL(node_data); | 32 | EXPORT_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 | } |
47 | early_param("numa", numa_parse_early_param); | 49 | early_param("numa", numa_parse_early_param); |
@@ -93,7 +95,6 @@ void numa_clear_node(unsigned int cpu) | |||
93 | */ | 95 | */ |
94 | static void __init setup_node_to_cpumask_map(void) | 96 | static 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 | */ |
119 | void numa_store_cpu_info(unsigned int cpu) | 117 | void 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 | ||
124 | void __init early_map_cpu_to_node(unsigned int cpu, int nid) | 122 | void __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 | ||
140 | unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; | ||
141 | EXPORT_SYMBOL(__per_cpu_offset); | ||
142 | |||
143 | static int __init early_cpu_to_node(int cpu) | ||
144 | { | ||
145 | return cpu_to_node_map[cpu]; | ||
146 | } | ||
147 | |||
148 | static int __init pcpu_cpu_distance(unsigned int from, unsigned int to) | ||
149 | { | ||
150 | return node_distance(from, to); | ||
131 | } | 151 | } |
132 | 152 | ||
153 | static 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 | |||
162 | static void __init pcpu_fc_free(void *ptr, size_t size) | ||
163 | { | ||
164 | memblock_free_early(__pa(ptr), size); | ||
165 | } | ||
166 | |||
167 | void __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) | |||
257 | void __init numa_set_distance(int from, int to, int distance) | 312 | void __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); |