aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/mm')
-rw-r--r--arch/x86_64/mm/numa.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 0ae2d9d5d7ea..5ee07bc41eb5 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -362,6 +362,21 @@ static int __init split_nodes_equally(struct bootnode *nodes, u64 *addr,
362} 362}
363 363
364/* 364/*
365 * Splits the remaining system RAM into chunks of size. The remaining memory is
366 * always assigned to a final node and can be asymmetric. Returns the number of
367 * nodes split.
368 */
369static int __init split_nodes_by_size(struct bootnode *nodes, u64 *addr,
370 u64 max_addr, int node_start, u64 size)
371{
372 int i = node_start;
373 size = (size << 20) & FAKE_NODE_MIN_HASH_MASK;
374 while (!setup_node_range(i++, nodes, addr, size, max_addr))
375 ;
376 return i - node_start;
377}
378
379/*
365 * Sets up the system RAM area from start_pfn to end_pfn according to the 380 * Sets up the system RAM area from start_pfn to end_pfn according to the
366 * numa=fake command-line option. 381 * numa=fake command-line option.
367 */ 382 */
@@ -370,9 +385,10 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
370 struct bootnode nodes[MAX_NUMNODES]; 385 struct bootnode nodes[MAX_NUMNODES];
371 u64 addr = start_pfn << PAGE_SHIFT; 386 u64 addr = start_pfn << PAGE_SHIFT;
372 u64 max_addr = end_pfn << PAGE_SHIFT; 387 u64 max_addr = end_pfn << PAGE_SHIFT;
373 unsigned int coeff;
374 unsigned int num = 0;
375 int num_nodes = 0; 388 int num_nodes = 0;
389 int coeff_flag;
390 int coeff = -1;
391 int num = 0;
376 u64 size; 392 u64 size;
377 int i; 393 int i;
378 394
@@ -390,29 +406,34 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
390 } 406 }
391 407
392 /* Parse the command line. */ 408 /* Parse the command line. */
393 for (coeff = 1; ; cmdline++) { 409 for (coeff_flag = 0; ; cmdline++) {
394 if (*cmdline && isdigit(*cmdline)) { 410 if (*cmdline && isdigit(*cmdline)) {
395 num = num * 10 + *cmdline - '0'; 411 num = num * 10 + *cmdline - '0';
396 continue; 412 continue;
397 } 413 }
398 if (*cmdline == '*') 414 if (*cmdline == '*') {
399 coeff = num; 415 if (num > 0)
416 coeff = num;
417 coeff_flag = 1;
418 }
400 if (!*cmdline || *cmdline == ',') { 419 if (!*cmdline || *cmdline == ',') {
420 if (!coeff_flag)
421 coeff = 1;
401 /* 422 /*
402 * Round down to the nearest FAKE_NODE_MIN_SIZE. 423 * Round down to the nearest FAKE_NODE_MIN_SIZE.
403 * Command-line coefficients are in megabytes. 424 * Command-line coefficients are in megabytes.
404 */ 425 */
405 size = ((u64)num << 20) & FAKE_NODE_MIN_HASH_MASK; 426 size = ((u64)num << 20) & FAKE_NODE_MIN_HASH_MASK;
406 if (size) { 427 if (size)
407 for (i = 0; i < coeff; i++, num_nodes++) 428 for (i = 0; i < coeff; i++, num_nodes++)
408 if (setup_node_range(num_nodes, nodes, 429 if (setup_node_range(num_nodes, nodes,
409 &addr, size, max_addr) < 0) 430 &addr, size, max_addr) < 0)
410 goto done; 431 goto done;
411 coeff = 1; 432 if (!*cmdline)
412 } 433 break;
434 coeff_flag = 0;
435 coeff = -1;
413 } 436 }
414 if (!*cmdline)
415 break;
416 num = 0; 437 num = 0;
417 } 438 }
418done: 439done:
@@ -420,6 +441,12 @@ done:
420 return -1; 441 return -1;
421 /* Fill remainder of system RAM, if appropriate. */ 442 /* Fill remainder of system RAM, if appropriate. */
422 if (addr < max_addr) { 443 if (addr < max_addr) {
444 if (coeff_flag && coeff < 0) {
445 /* Split remaining nodes into num-sized chunks */
446 num_nodes += split_nodes_by_size(nodes, &addr, max_addr,
447 num_nodes, num);
448 goto out;
449 }
423 switch (*(cmdline - 1)) { 450 switch (*(cmdline - 1)) {
424 case '*': 451 case '*':
425 /* Split remaining nodes into coeff chunks */ 452 /* Split remaining nodes into coeff chunks */