|
@@ -361,6 +361,21 @@ static int __init split_nodes_equally(struct bootnode *nodes, u64 *addr,
|
|
|
return i - node_start + 1;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Splits the remaining system RAM into chunks of size. The remaining memory is
|
|
|
+ * always assigned to a final node and can be asymmetric. Returns the number of
|
|
|
+ * nodes split.
|
|
|
+ */
|
|
|
+static int __init split_nodes_by_size(struct bootnode *nodes, u64 *addr,
|
|
|
+ u64 max_addr, int node_start, u64 size)
|
|
|
+{
|
|
|
+ int i = node_start;
|
|
|
+ size = (size << 20) & FAKE_NODE_MIN_HASH_MASK;
|
|
|
+ while (!setup_node_range(i++, nodes, addr, size, max_addr))
|
|
|
+ ;
|
|
|
+ return i - node_start;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Sets up the system RAM area from start_pfn to end_pfn according to the
|
|
|
* numa=fake command-line option.
|
|
@@ -370,9 +385,10 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
|
|
|
struct bootnode nodes[MAX_NUMNODES];
|
|
|
u64 addr = start_pfn << PAGE_SHIFT;
|
|
|
u64 max_addr = end_pfn << PAGE_SHIFT;
|
|
|
- unsigned int coeff;
|
|
|
- unsigned int num = 0;
|
|
|
int num_nodes = 0;
|
|
|
+ int coeff_flag;
|
|
|
+ int coeff = -1;
|
|
|
+ int num = 0;
|
|
|
u64 size;
|
|
|
int i;
|
|
|
|
|
@@ -390,29 +406,34 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
|
|
|
}
|
|
|
|
|
|
/* Parse the command line. */
|
|
|
- for (coeff = 1; ; cmdline++) {
|
|
|
+ for (coeff_flag = 0; ; cmdline++) {
|
|
|
if (*cmdline && isdigit(*cmdline)) {
|
|
|
num = num * 10 + *cmdline - '0';
|
|
|
continue;
|
|
|
}
|
|
|
- if (*cmdline == '*')
|
|
|
- coeff = num;
|
|
|
+ if (*cmdline == '*') {
|
|
|
+ if (num > 0)
|
|
|
+ coeff = num;
|
|
|
+ coeff_flag = 1;
|
|
|
+ }
|
|
|
if (!*cmdline || *cmdline == ',') {
|
|
|
+ if (!coeff_flag)
|
|
|
+ coeff = 1;
|
|
|
/*
|
|
|
* Round down to the nearest FAKE_NODE_MIN_SIZE.
|
|
|
* Command-line coefficients are in megabytes.
|
|
|
*/
|
|
|
size = ((u64)num << 20) & FAKE_NODE_MIN_HASH_MASK;
|
|
|
- if (size) {
|
|
|
+ if (size)
|
|
|
for (i = 0; i < coeff; i++, num_nodes++)
|
|
|
if (setup_node_range(num_nodes, nodes,
|
|
|
&addr, size, max_addr) < 0)
|
|
|
goto done;
|
|
|
- coeff = 1;
|
|
|
- }
|
|
|
+ if (!*cmdline)
|
|
|
+ break;
|
|
|
+ coeff_flag = 0;
|
|
|
+ coeff = -1;
|
|
|
}
|
|
|
- if (!*cmdline)
|
|
|
- break;
|
|
|
num = 0;
|
|
|
}
|
|
|
done:
|
|
@@ -420,6 +441,12 @@ done:
|
|
|
return -1;
|
|
|
/* Fill remainder of system RAM, if appropriate. */
|
|
|
if (addr < max_addr) {
|
|
|
+ if (coeff_flag && coeff < 0) {
|
|
|
+ /* Split remaining nodes into num-sized chunks */
|
|
|
+ num_nodes += split_nodes_by_size(nodes, &addr, max_addr,
|
|
|
+ num_nodes, num);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
switch (*(cmdline - 1)) {
|
|
|
case '*':
|
|
|
/* Split remaining nodes into coeff chunks */
|