aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-02-16 11:11:07 -0500
committerTejun Heo <tj@kernel.org>2011-02-16 11:11:07 -0500
commitef396ec96c1a8ffd2b0bc67f1f79c7274de02b95 (patch)
treec0c996ba7b3d60195beb4e4b65790df1a9d79419 /arch/x86/mm
parent19095548704ecd0f32fd5deba01d56430ad7a344 (diff)
x86-64, NUMA: Factor out memblk handling into numa_{add|register}_memblk()
Factor out memblk handling from srat_64.c into two functions in numa_64.c. This patch doesn't introduce any behavior change. The next patch will make all init methods use these functions. - v2: Fixed build failure on 32bit due to misplaced NR_NODE_MEMBLKS. Reported by Ingo. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Brian Gerst <brgerst@gmail.com> Cc: Cyrill Gorcunov <gorcunov@gmail.com> Cc: Shaohui Zheng <shaohui.zheng@intel.com> Cc: David Rientjes <rientjes@google.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r--arch/x86/mm/numa_64.c109
-rw-r--r--arch/x86/mm/srat_64.c96
2 files changed, 112 insertions, 93 deletions
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 82ee3083b094..a1d702d2584c 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -33,6 +33,10 @@ struct memnode memnode;
33static unsigned long __initdata nodemap_addr; 33static unsigned long __initdata nodemap_addr;
34static unsigned long __initdata nodemap_size; 34static unsigned long __initdata nodemap_size;
35 35
36static int num_node_memblks __initdata;
37static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
38static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
39
36struct bootnode numa_nodes[MAX_NUMNODES] __initdata; 40struct bootnode numa_nodes[MAX_NUMNODES] __initdata;
37 41
38/* 42/*
@@ -184,6 +188,43 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
184 return NULL; 188 return NULL;
185} 189}
186 190
191static __init int conflicting_memblks(unsigned long start, unsigned long end)
192{
193 int i;
194 for (i = 0; i < num_node_memblks; i++) {
195 struct bootnode *nd = &node_memblk_range[i];
196 if (nd->start == nd->end)
197 continue;
198 if (nd->end > start && nd->start < end)
199 return memblk_nodeid[i];
200 if (nd->end == end && nd->start == start)
201 return memblk_nodeid[i];
202 }
203 return -1;
204}
205
206int __init numa_add_memblk(int nid, u64 start, u64 end)
207{
208 int i;
209
210 i = conflicting_memblks(start, end);
211 if (i == nid) {
212 printk(KERN_WARNING "NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
213 nid, start, end, numa_nodes[i].start, numa_nodes[i].end);
214 } else if (i >= 0) {
215 printk(KERN_ERR "NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
216 nid, start, end, i,
217 numa_nodes[i].start, numa_nodes[i].end);
218 return -EINVAL;
219 }
220
221 node_memblk_range[num_node_memblks].start = start;
222 node_memblk_range[num_node_memblks].end = end;
223 memblk_nodeid[num_node_memblks] = nid;
224 num_node_memblks++;
225 return 0;
226}
227
187static __init void cutoff_node(int i, unsigned long start, unsigned long end) 228static __init void cutoff_node(int i, unsigned long start, unsigned long end)
188{ 229{
189 struct bootnode *nd = &numa_nodes[i]; 230 struct bootnode *nd = &numa_nodes[i];
@@ -246,6 +287,71 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
246 node_set_online(nodeid); 287 node_set_online(nodeid);
247} 288}
248 289
290int __init numa_register_memblks(void)
291{
292 int i;
293
294 /*
295 * Join together blocks on the same node, holes between
296 * which don't overlap with memory on other nodes.
297 */
298 for (i = 0; i < num_node_memblks; ++i) {
299 int j, k;
300
301 for (j = i + 1; j < num_node_memblks; ++j) {
302 unsigned long start, end;
303
304 if (memblk_nodeid[i] != memblk_nodeid[j])
305 continue;
306 start = min(node_memblk_range[i].end,
307 node_memblk_range[j].end);
308 end = max(node_memblk_range[i].start,
309 node_memblk_range[j].start);
310 for (k = 0; k < num_node_memblks; ++k) {
311 if (memblk_nodeid[i] == memblk_nodeid[k])
312 continue;
313 if (start < node_memblk_range[k].end &&
314 end > node_memblk_range[k].start)
315 break;
316 }
317 if (k < num_node_memblks)
318 continue;
319 start = min(node_memblk_range[i].start,
320 node_memblk_range[j].start);
321 end = max(node_memblk_range[i].end,
322 node_memblk_range[j].end);
323 printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
324 memblk_nodeid[i],
325 node_memblk_range[i].start,
326 node_memblk_range[i].end,
327 node_memblk_range[j].start,
328 node_memblk_range[j].end,
329 start, end);
330 node_memblk_range[i].start = start;
331 node_memblk_range[i].end = end;
332 k = --num_node_memblks - j;
333 memmove(memblk_nodeid + j, memblk_nodeid + j+1,
334 k * sizeof(*memblk_nodeid));
335 memmove(node_memblk_range + j, node_memblk_range + j+1,
336 k * sizeof(*node_memblk_range));
337 --j;
338 }
339 }
340
341 memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
342 memblk_nodeid);
343 if (memnode_shift < 0) {
344 printk(KERN_ERR "NUMA: No NUMA node hash function found. Contact maintainer\n");
345 return -EINVAL;
346 }
347
348 for (i = 0; i < num_node_memblks; i++)
349 memblock_x86_register_active_regions(memblk_nodeid[i],
350 node_memblk_range[i].start >> PAGE_SHIFT,
351 node_memblk_range[i].end >> PAGE_SHIFT);
352 return 0;
353}
354
249#ifdef CONFIG_NUMA_EMU 355#ifdef CONFIG_NUMA_EMU
250/* Numa emulation */ 356/* Numa emulation */
251static struct bootnode nodes[MAX_NUMNODES] __initdata; 357static struct bootnode nodes[MAX_NUMNODES] __initdata;
@@ -653,6 +759,9 @@ void __init initmem_init(void)
653 nodes_clear(mem_nodes_parsed); 759 nodes_clear(mem_nodes_parsed);
654 nodes_clear(node_possible_map); 760 nodes_clear(node_possible_map);
655 nodes_clear(node_online_map); 761 nodes_clear(node_online_map);
762 num_node_memblks = 0;
763 memset(node_memblk_range, 0, sizeof(node_memblk_range));
764 memset(memblk_nodeid, 0, sizeof(memblk_nodeid));
656 memset(numa_nodes, 0, sizeof(numa_nodes)); 765 memset(numa_nodes, 0, sizeof(numa_nodes));
657 766
658 if (numa_init[i]() < 0) 767 if (numa_init[i]() < 0)
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index 82b1087963a2..341b37193c76 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -30,30 +30,11 @@ static struct acpi_table_slit *acpi_slit;
30 30
31static struct bootnode nodes_add[MAX_NUMNODES]; 31static struct bootnode nodes_add[MAX_NUMNODES];
32 32
33static int num_node_memblks __initdata;
34static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
35static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
36
37static __init int setup_node(int pxm) 33static __init int setup_node(int pxm)
38{ 34{
39 return acpi_map_pxm_to_node(pxm); 35 return acpi_map_pxm_to_node(pxm);
40} 36}
41 37
42static __init int conflicting_memblks(unsigned long start, unsigned long end)
43{
44 int i;
45 for (i = 0; i < num_node_memblks; i++) {
46 struct bootnode *nd = &node_memblk_range[i];
47 if (nd->start == nd->end)
48 continue;
49 if (nd->end > start && nd->start < end)
50 return memblk_nodeid[i];
51 if (nd->end == end && nd->start == start)
52 return memblk_nodeid[i];
53 }
54 return -1;
55}
56
57static __init void bad_srat(void) 38static __init void bad_srat(void)
58{ 39{
59 int i; 40 int i;
@@ -233,7 +214,6 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
233 struct bootnode *nd; 214 struct bootnode *nd;
234 unsigned long start, end; 215 unsigned long start, end;
235 int node, pxm; 216 int node, pxm;
236 int i;
237 217
238 if (srat_disabled()) 218 if (srat_disabled())
239 return; 219 return;
@@ -255,16 +235,8 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
255 bad_srat(); 235 bad_srat();
256 return; 236 return;
257 } 237 }
258 i = conflicting_memblks(start, end); 238
259 if (i == node) { 239 if (numa_add_memblk(node, start, end) < 0) {
260 printk(KERN_WARNING
261 "SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
262 pxm, start, end, numa_nodes[i].start, numa_nodes[i].end);
263 } else if (i >= 0) {
264 printk(KERN_ERR
265 "SRAT: PXM %d (%lx-%lx) overlaps with PXM %d (%Lx-%Lx)\n",
266 pxm, start, end, node_to_pxm(i),
267 numa_nodes[i].start, numa_nodes[i].end);
268 bad_srat(); 240 bad_srat();
269 return; 241 return;
270 } 242 }
@@ -285,11 +257,6 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
285 } 257 }
286 } else 258 } else
287 update_nodes_add(node, start, end); 259 update_nodes_add(node, start, end);
288
289 node_memblk_range[num_node_memblks].start = start;
290 node_memblk_range[num_node_memblks].end = end;
291 memblk_nodeid[num_node_memblks] = node;
292 num_node_memblks++;
293} 260}
294 261
295/* Sanity check to catch more bad SRATs (they are amazingly common). 262/* Sanity check to catch more bad SRATs (they are amazingly common).
@@ -341,68 +308,11 @@ int __init acpi_scan_nodes(void)
341 if (acpi_numa <= 0) 308 if (acpi_numa <= 0)
342 return -1; 309 return -1;
343 310
344 /* 311 if (numa_register_memblks() < 0) {
345 * Join together blocks on the same node, holes between
346 * which don't overlap with memory on other nodes.
347 */
348 for (i = 0; i < num_node_memblks; ++i) {
349 int j, k;
350
351 for (j = i + 1; j < num_node_memblks; ++j) {
352 unsigned long start, end;
353
354 if (memblk_nodeid[i] != memblk_nodeid[j])
355 continue;
356 start = min(node_memblk_range[i].end,
357 node_memblk_range[j].end);
358 end = max(node_memblk_range[i].start,
359 node_memblk_range[j].start);
360 for (k = 0; k < num_node_memblks; ++k) {
361 if (memblk_nodeid[i] == memblk_nodeid[k])
362 continue;
363 if (start < node_memblk_range[k].end &&
364 end > node_memblk_range[k].start)
365 break;
366 }
367 if (k < num_node_memblks)
368 continue;
369 start = min(node_memblk_range[i].start,
370 node_memblk_range[j].start);
371 end = max(node_memblk_range[i].end,
372 node_memblk_range[j].end);
373 printk(KERN_INFO "SRAT: Node %d "
374 "[%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
375 memblk_nodeid[i],
376 node_memblk_range[i].start,
377 node_memblk_range[i].end,
378 node_memblk_range[j].start,
379 node_memblk_range[j].end,
380 start, end);
381 node_memblk_range[i].start = start;
382 node_memblk_range[i].end = end;
383 k = --num_node_memblks - j;
384 memmove(memblk_nodeid + j, memblk_nodeid + j+1,
385 k * sizeof(*memblk_nodeid));
386 memmove(node_memblk_range + j, node_memblk_range + j+1,
387 k * sizeof(*node_memblk_range));
388 --j;
389 }
390 }
391
392 memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
393 memblk_nodeid);
394 if (memnode_shift < 0) {
395 printk(KERN_ERR
396 "SRAT: No NUMA node hash function found. Contact maintainer\n");
397 bad_srat(); 312 bad_srat();
398 return -1; 313 return -1;
399 } 314 }
400 315
401 for (i = 0; i < num_node_memblks; i++)
402 memblock_x86_register_active_regions(memblk_nodeid[i],
403 node_memblk_range[i].start >> PAGE_SHIFT,
404 node_memblk_range[i].end >> PAGE_SHIFT);
405
406 /* for out of order entries in SRAT */ 316 /* for out of order entries in SRAT */
407 sort_node_map(); 317 sort_node_map();
408 if (!nodes_cover_memory(numa_nodes)) { 318 if (!nodes_cover_memory(numa_nodes)) {