diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/mm/numa_64.c | 213 |
1 files changed, 111 insertions, 102 deletions
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index e7f3f4e9ec85..4faed6a8f3ae 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Generic VM initialization for x86-64 NUMA setups. | 2 | * Generic VM initialization for x86-64 NUMA setups. |
3 | * Copyright 2002,2003 Andi Kleen, SuSE Labs. | 3 | * Copyright 2002,2003 Andi Kleen, SuSE Labs. |
4 | */ | 4 | */ |
5 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
6 | #include <linux/mm.h> | 6 | #include <linux/mm.h> |
7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
@@ -24,6 +24,8 @@ | |||
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; | 26 | struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; |
27 | EXPORT_SYMBOL(node_data); | ||
28 | |||
27 | bootmem_data_t plat_node_bdata[MAX_NUMNODES]; | 29 | bootmem_data_t plat_node_bdata[MAX_NUMNODES]; |
28 | 30 | ||
29 | struct memnode memnode; | 31 | struct memnode memnode; |
@@ -31,16 +33,19 @@ struct memnode memnode; | |||
31 | unsigned char cpu_to_node[NR_CPUS] __read_mostly = { | 33 | unsigned char cpu_to_node[NR_CPUS] __read_mostly = { |
32 | [0 ... NR_CPUS-1] = NUMA_NO_NODE | 34 | [0 ... NR_CPUS-1] = NUMA_NO_NODE |
33 | }; | 35 | }; |
36 | EXPORT_SYMBOL(cpu_to_node); | ||
37 | |||
34 | unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = { | 38 | unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = { |
35 | [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE | 39 | [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE |
36 | }; | 40 | }; |
41 | |||
37 | cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly; | 42 | cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly; |
43 | EXPORT_SYMBOL(node_to_cpumask); | ||
38 | 44 | ||
39 | int numa_off __initdata; | 45 | int numa_off __initdata; |
40 | unsigned long __initdata nodemap_addr; | 46 | unsigned long __initdata nodemap_addr; |
41 | unsigned long __initdata nodemap_size; | 47 | unsigned long __initdata nodemap_size; |
42 | 48 | ||
43 | |||
44 | /* | 49 | /* |
45 | * Given a shift value, try to populate memnodemap[] | 50 | * Given a shift value, try to populate memnodemap[] |
46 | * Returns : | 51 | * Returns : |
@@ -48,12 +53,11 @@ unsigned long __initdata nodemap_size; | |||
48 | * 0 if memnodmap[] too small (of shift too small) | 53 | * 0 if memnodmap[] too small (of shift too small) |
49 | * -1 if node overlap or lost ram (shift too big) | 54 | * -1 if node overlap or lost ram (shift too big) |
50 | */ | 55 | */ |
51 | static int __init | 56 | static int __init populate_memnodemap(const struct bootnode *nodes, |
52 | populate_memnodemap(const struct bootnode *nodes, int numnodes, int shift) | 57 | int numnodes, int shift) |
53 | { | 58 | { |
54 | int i; | ||
55 | int res = -1; | ||
56 | unsigned long addr, end; | 59 | unsigned long addr, end; |
60 | int i, res = -1; | ||
57 | 61 | ||
58 | memset(memnodemap, 0xff, memnodemapsize); | 62 | memset(memnodemap, 0xff, memnodemapsize); |
59 | for (i = 0; i < numnodes; i++) { | 63 | for (i = 0; i < numnodes; i++) { |
@@ -70,7 +74,7 @@ populate_memnodemap(const struct bootnode *nodes, int numnodes, int shift) | |||
70 | addr += (1UL << shift); | 74 | addr += (1UL << shift); |
71 | } while (addr < end); | 75 | } while (addr < end); |
72 | res = 1; | 76 | res = 1; |
73 | } | 77 | } |
74 | return res; | 78 | return res; |
75 | } | 79 | } |
76 | 80 | ||
@@ -105,8 +109,8 @@ static int __init allocate_cachealigned_memnodemap(void) | |||
105 | * The LSB of all start and end addresses in the node map is the value of the | 109 | * The LSB of all start and end addresses in the node map is the value of the |
106 | * maximum possible shift. | 110 | * maximum possible shift. |
107 | */ | 111 | */ |
108 | static int __init | 112 | static int __init extract_lsb_from_nodes(const struct bootnode *nodes, |
109 | extract_lsb_from_nodes (const struct bootnode *nodes, int numnodes) | 113 | int numnodes) |
110 | { | 114 | { |
111 | int i, nodes_used = 0; | 115 | int i, nodes_used = 0; |
112 | unsigned long start, end; | 116 | unsigned long start, end; |
@@ -141,10 +145,9 @@ int __init compute_hash_shift(struct bootnode *nodes, int numnodes) | |||
141 | shift); | 145 | shift); |
142 | 146 | ||
143 | if (populate_memnodemap(nodes, numnodes, shift) != 1) { | 147 | if (populate_memnodemap(nodes, numnodes, shift) != 1) { |
144 | printk(KERN_INFO | 148 | printk(KERN_INFO "Your memory is not aligned you need to " |
145 | "Your memory is not aligned you need to rebuild your kernel " | 149 | "rebuild your kernel with a bigger NODEMAPSIZE " |
146 | "with a bigger NODEMAPSIZE shift=%d\n", | 150 | "shift=%d\n", shift); |
147 | shift); | ||
148 | return -1; | 151 | return -1; |
149 | } | 152 | } |
150 | return shift; | 153 | return shift; |
@@ -157,35 +160,37 @@ int early_pfn_to_nid(unsigned long pfn) | |||
157 | } | 160 | } |
158 | #endif | 161 | #endif |
159 | 162 | ||
160 | static void * __init | 163 | static void * __init early_node_mem(int nodeid, unsigned long start, |
161 | early_node_mem(int nodeid, unsigned long start, unsigned long end, | 164 | unsigned long end, unsigned long size) |
162 | unsigned long size) | ||
163 | { | 165 | { |
164 | unsigned long mem = find_e820_area(start, end, size); | 166 | unsigned long mem = find_e820_area(start, end, size); |
165 | void *ptr; | 167 | void *ptr; |
168 | |||
166 | if (mem != -1L) | 169 | if (mem != -1L) |
167 | return __va(mem); | 170 | return __va(mem); |
168 | ptr = __alloc_bootmem_nopanic(size, | 171 | ptr = __alloc_bootmem_nopanic(size, |
169 | SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)); | 172 | SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)); |
170 | if (ptr == NULL) { | 173 | if (ptr == NULL) { |
171 | printk(KERN_ERR "Cannot find %lu bytes in node %d\n", | 174 | printk(KERN_ERR "Cannot find %lu bytes in node %d\n", |
172 | size, nodeid); | 175 | size, nodeid); |
173 | return NULL; | 176 | return NULL; |
174 | } | 177 | } |
175 | return ptr; | 178 | return ptr; |
176 | } | 179 | } |
177 | 180 | ||
178 | /* Initialize bootmem allocator for a node */ | 181 | /* Initialize bootmem allocator for a node */ |
179 | void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) | 182 | void __init setup_node_bootmem(int nodeid, unsigned long start, |
180 | { | 183 | unsigned long end) |
181 | unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start; | 184 | { |
182 | unsigned long nodedata_phys; | 185 | unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size; |
186 | unsigned long bootmap_start, nodedata_phys; | ||
183 | void *bootmap; | 187 | void *bootmap; |
184 | const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); | 188 | const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); |
185 | 189 | ||
186 | start = round_up(start, ZONE_ALIGN); | 190 | start = round_up(start, ZONE_ALIGN); |
187 | 191 | ||
188 | printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid, start, end); | 192 | printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid, |
193 | start, end); | ||
189 | 194 | ||
190 | start_pfn = start >> PAGE_SHIFT; | 195 | start_pfn = start >> PAGE_SHIFT; |
191 | end_pfn = end >> PAGE_SHIFT; | 196 | end_pfn = end >> PAGE_SHIFT; |
@@ -201,75 +206,81 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
201 | NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn; | 206 | NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn; |
202 | 207 | ||
203 | /* Find a place for the bootmem map */ | 208 | /* Find a place for the bootmem map */ |
204 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); | 209 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); |
205 | bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); | 210 | bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); |
206 | bootmap = early_node_mem(nodeid, bootmap_start, end, | 211 | bootmap = early_node_mem(nodeid, bootmap_start, end, |
207 | bootmap_pages<<PAGE_SHIFT); | 212 | bootmap_pages<<PAGE_SHIFT); |
208 | if (bootmap == NULL) { | 213 | if (bootmap == NULL) { |
209 | if (nodedata_phys < start || nodedata_phys >= end) | 214 | if (nodedata_phys < start || nodedata_phys >= end) |
210 | free_bootmem((unsigned long)node_data[nodeid],pgdat_size); | 215 | free_bootmem((unsigned long)node_data[nodeid], |
216 | pgdat_size); | ||
211 | node_data[nodeid] = NULL; | 217 | node_data[nodeid] = NULL; |
212 | return; | 218 | return; |
213 | } | 219 | } |
214 | bootmap_start = __pa(bootmap); | 220 | bootmap_start = __pa(bootmap); |
215 | Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); | 221 | Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); |
216 | 222 | ||
217 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), | 223 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), |
218 | bootmap_start >> PAGE_SHIFT, | 224 | bootmap_start >> PAGE_SHIFT, |
219 | start_pfn, end_pfn); | 225 | start_pfn, end_pfn); |
220 | 226 | ||
221 | free_bootmem_with_active_regions(nodeid, end); | 227 | free_bootmem_with_active_regions(nodeid, end); |
222 | 228 | ||
223 | reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); | 229 | reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); |
224 | reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT); | 230 | reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, |
231 | bootmap_pages<<PAGE_SHIFT); | ||
225 | #ifdef CONFIG_ACPI_NUMA | 232 | #ifdef CONFIG_ACPI_NUMA |
226 | srat_reserve_add_area(nodeid); | 233 | srat_reserve_add_area(nodeid); |
227 | #endif | 234 | #endif |
228 | node_set_online(nodeid); | 235 | node_set_online(nodeid); |
229 | } | 236 | } |
230 | 237 | ||
231 | /* Initialize final allocator for a zone */ | 238 | /* Initialize final allocator for a zone */ |
232 | void __init setup_node_zones(int nodeid) | 239 | void __init setup_node_zones(int nodeid) |
233 | { | 240 | { |
234 | unsigned long start_pfn, end_pfn, memmapsize, limit; | 241 | unsigned long start_pfn, end_pfn, memmapsize, limit; |
235 | 242 | ||
236 | start_pfn = node_start_pfn(nodeid); | 243 | start_pfn = node_start_pfn(nodeid); |
237 | end_pfn = node_end_pfn(nodeid); | 244 | end_pfn = node_end_pfn(nodeid); |
238 | 245 | ||
239 | Dprintk(KERN_INFO "Setting up memmap for node %d %lx-%lx\n", | 246 | Dprintk(KERN_INFO "Setting up memmap for node %d %lx-%lx\n", |
240 | nodeid, start_pfn, end_pfn); | 247 | nodeid, start_pfn, end_pfn); |
241 | 248 | ||
242 | /* Try to allocate mem_map at end to not fill up precious <4GB | 249 | /* |
243 | memory. */ | 250 | * Try to allocate mem_map at end to not fill up precious <4GB |
251 | * memory. | ||
252 | */ | ||
244 | memmapsize = sizeof(struct page) * (end_pfn-start_pfn); | 253 | memmapsize = sizeof(struct page) * (end_pfn-start_pfn); |
245 | limit = end_pfn << PAGE_SHIFT; | 254 | limit = end_pfn << PAGE_SHIFT; |
246 | #ifdef CONFIG_FLAT_NODE_MEM_MAP | 255 | #ifdef CONFIG_FLAT_NODE_MEM_MAP |
247 | NODE_DATA(nodeid)->node_mem_map = | 256 | NODE_DATA(nodeid)->node_mem_map = |
248 | __alloc_bootmem_core(NODE_DATA(nodeid)->bdata, | 257 | __alloc_bootmem_core(NODE_DATA(nodeid)->bdata, |
249 | memmapsize, SMP_CACHE_BYTES, | 258 | memmapsize, SMP_CACHE_BYTES, |
250 | round_down(limit - memmapsize, PAGE_SIZE), | 259 | round_down(limit - memmapsize, PAGE_SIZE), |
251 | limit); | 260 | limit); |
252 | #endif | 261 | #endif |
253 | } | 262 | } |
254 | 263 | ||
264 | /* | ||
265 | * There are unfortunately some poorly designed mainboards around that | ||
266 | * only connect memory to a single CPU. This breaks the 1:1 cpu->node | ||
267 | * mapping. To avoid this fill in the mapping for all possible CPUs, | ||
268 | * as the number of CPUs is not known yet. We round robin the existing | ||
269 | * nodes. | ||
270 | */ | ||
255 | void __init numa_init_array(void) | 271 | void __init numa_init_array(void) |
256 | { | 272 | { |
257 | int rr, i; | 273 | int rr, i; |
258 | /* There are unfortunately some poorly designed mainboards around | 274 | |
259 | that only connect memory to a single CPU. This breaks the 1:1 cpu->node | ||
260 | mapping. To avoid this fill in the mapping for all possible | ||
261 | CPUs, as the number of CPUs is not known yet. | ||
262 | We round robin the existing nodes. */ | ||
263 | rr = first_node(node_online_map); | 275 | rr = first_node(node_online_map); |
264 | for (i = 0; i < NR_CPUS; i++) { | 276 | for (i = 0; i < NR_CPUS; i++) { |
265 | if (cpu_to_node(i) != NUMA_NO_NODE) | 277 | if (cpu_to_node(i) != NUMA_NO_NODE) |
266 | continue; | 278 | continue; |
267 | numa_set_node(i, rr); | 279 | numa_set_node(i, rr); |
268 | rr = next_node(rr, node_online_map); | 280 | rr = next_node(rr, node_online_map); |
269 | if (rr == MAX_NUMNODES) | 281 | if (rr == MAX_NUMNODES) |
270 | rr = first_node(node_online_map); | 282 | rr = first_node(node_online_map); |
271 | } | 283 | } |
272 | |||
273 | } | 284 | } |
274 | 285 | ||
275 | #ifdef CONFIG_NUMA_EMU | 286 | #ifdef CONFIG_NUMA_EMU |
@@ -277,15 +288,17 @@ void __init numa_init_array(void) | |||
277 | char *cmdline __initdata; | 288 | char *cmdline __initdata; |
278 | 289 | ||
279 | /* | 290 | /* |
280 | * Setups up nid to range from addr to addr + size. If the end boundary is | 291 | * Setups up nid to range from addr to addr + size. If the end |
281 | * greater than max_addr, then max_addr is used instead. The return value is 0 | 292 | * boundary is greater than max_addr, then max_addr is used instead. |
282 | * if there is additional memory left for allocation past addr and -1 otherwise. | 293 | * The return value is 0 if there is additional memory left for |
283 | * addr is adjusted to be at the end of the node. | 294 | * allocation past addr and -1 otherwise. addr is adjusted to be at |
295 | * the end of the node. | ||
284 | */ | 296 | */ |
285 | static int __init setup_node_range(int nid, struct bootnode *nodes, u64 *addr, | 297 | static int __init setup_node_range(int nid, struct bootnode *nodes, u64 *addr, |
286 | u64 size, u64 max_addr) | 298 | u64 size, u64 max_addr) |
287 | { | 299 | { |
288 | int ret = 0; | 300 | int ret = 0; |
301 | |||
289 | nodes[nid].start = *addr; | 302 | nodes[nid].start = *addr; |
290 | *addr += size; | 303 | *addr += size; |
291 | if (*addr >= max_addr) { | 304 | if (*addr >= max_addr) { |
@@ -336,6 +349,7 @@ static int __init split_nodes_equally(struct bootnode *nodes, u64 *addr, | |||
336 | 349 | ||
337 | for (i = node_start; i < num_nodes + node_start; i++) { | 350 | for (i = node_start; i < num_nodes + node_start; i++) { |
338 | u64 end = *addr + size; | 351 | u64 end = *addr + size; |
352 | |||
339 | if (i < big) | 353 | if (i < big) |
340 | end += FAKE_NODE_MIN_SIZE; | 354 | end += FAKE_NODE_MIN_SIZE; |
341 | /* | 355 | /* |
@@ -381,14 +395,9 @@ static int __init split_nodes_by_size(struct bootnode *nodes, u64 *addr, | |||
381 | static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn) | 395 | static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn) |
382 | { | 396 | { |
383 | struct bootnode nodes[MAX_NUMNODES]; | 397 | struct bootnode nodes[MAX_NUMNODES]; |
384 | u64 addr = start_pfn << PAGE_SHIFT; | 398 | u64 size, addr = start_pfn << PAGE_SHIFT; |
385 | u64 max_addr = end_pfn << PAGE_SHIFT; | 399 | u64 max_addr = end_pfn << PAGE_SHIFT; |
386 | int num_nodes = 0; | 400 | int num_nodes = 0, num = 0, coeff_flag, coeff = -1, i; |
387 | int coeff_flag; | ||
388 | int coeff = -1; | ||
389 | int num = 0; | ||
390 | u64 size; | ||
391 | int i; | ||
392 | 401 | ||
393 | memset(&nodes, 0, sizeof(nodes)); | 402 | memset(&nodes, 0, sizeof(nodes)); |
394 | /* | 403 | /* |
@@ -396,8 +405,9 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn) | |||
396 | * system RAM into N fake nodes. | 405 | * system RAM into N fake nodes. |
397 | */ | 406 | */ |
398 | if (!strchr(cmdline, '*') && !strchr(cmdline, ',')) { | 407 | if (!strchr(cmdline, '*') && !strchr(cmdline, ',')) { |
399 | num_nodes = split_nodes_equally(nodes, &addr, max_addr, 0, | 408 | long n = simple_strtol(cmdline, NULL, 0); |
400 | simple_strtol(cmdline, NULL, 0)); | 409 | |
410 | num_nodes = split_nodes_equally(nodes, &addr, max_addr, 0, n); | ||
401 | if (num_nodes < 0) | 411 | if (num_nodes < 0) |
402 | return num_nodes; | 412 | return num_nodes; |
403 | goto out; | 413 | goto out; |
@@ -484,46 +494,47 @@ out: | |||
484 | for_each_node_mask(i, node_possible_map) { | 494 | for_each_node_mask(i, node_possible_map) { |
485 | e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT, | 495 | e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT, |
486 | nodes[i].end >> PAGE_SHIFT); | 496 | nodes[i].end >> PAGE_SHIFT); |
487 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 497 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
488 | } | 498 | } |
489 | acpi_fake_nodes(nodes, num_nodes); | 499 | acpi_fake_nodes(nodes, num_nodes); |
490 | numa_init_array(); | 500 | numa_init_array(); |
491 | return 0; | 501 | return 0; |
492 | } | 502 | } |
493 | #endif /* CONFIG_NUMA_EMU */ | 503 | #endif /* CONFIG_NUMA_EMU */ |
494 | 504 | ||
495 | void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) | 505 | void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) |
496 | { | 506 | { |
497 | int i; | 507 | int i; |
498 | 508 | ||
499 | nodes_clear(node_possible_map); | 509 | nodes_clear(node_possible_map); |
500 | 510 | ||
501 | #ifdef CONFIG_NUMA_EMU | 511 | #ifdef CONFIG_NUMA_EMU |
502 | if (cmdline && !numa_emulation(start_pfn, end_pfn)) | 512 | if (cmdline && !numa_emulation(start_pfn, end_pfn)) |
503 | return; | 513 | return; |
504 | nodes_clear(node_possible_map); | 514 | nodes_clear(node_possible_map); |
505 | #endif | 515 | #endif |
506 | 516 | ||
507 | #ifdef CONFIG_ACPI_NUMA | 517 | #ifdef CONFIG_ACPI_NUMA |
508 | if (!numa_off && !acpi_scan_nodes(start_pfn << PAGE_SHIFT, | 518 | if (!numa_off && !acpi_scan_nodes(start_pfn << PAGE_SHIFT, |
509 | end_pfn << PAGE_SHIFT)) | 519 | end_pfn << PAGE_SHIFT)) |
510 | return; | 520 | return; |
511 | nodes_clear(node_possible_map); | 521 | nodes_clear(node_possible_map); |
512 | #endif | 522 | #endif |
513 | 523 | ||
514 | #ifdef CONFIG_K8_NUMA | 524 | #ifdef CONFIG_K8_NUMA |
515 | if (!numa_off && !k8_scan_nodes(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT)) | 525 | if (!numa_off && !k8_scan_nodes(start_pfn<<PAGE_SHIFT, |
526 | end_pfn<<PAGE_SHIFT)) | ||
516 | return; | 527 | return; |
517 | nodes_clear(node_possible_map); | 528 | nodes_clear(node_possible_map); |
518 | #endif | 529 | #endif |
519 | printk(KERN_INFO "%s\n", | 530 | printk(KERN_INFO "%s\n", |
520 | numa_off ? "NUMA turned off" : "No NUMA configuration found"); | 531 | numa_off ? "NUMA turned off" : "No NUMA configuration found"); |
521 | 532 | ||
522 | printk(KERN_INFO "Faking a node at %016lx-%016lx\n", | 533 | printk(KERN_INFO "Faking a node at %016lx-%016lx\n", |
523 | start_pfn << PAGE_SHIFT, | 534 | start_pfn << PAGE_SHIFT, |
524 | end_pfn << PAGE_SHIFT); | 535 | end_pfn << PAGE_SHIFT); |
525 | /* setup dummy node covering all memory */ | 536 | /* setup dummy node covering all memory */ |
526 | memnode_shift = 63; | 537 | memnode_shift = 63; |
527 | memnodemap = memnode.embedded_map; | 538 | memnodemap = memnode.embedded_map; |
528 | memnodemap[0] = 0; | 539 | memnodemap[0] = 0; |
529 | nodes_clear(node_online_map); | 540 | nodes_clear(node_online_map); |
@@ -539,7 +550,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) | |||
539 | __cpuinit void numa_add_cpu(int cpu) | 550 | __cpuinit void numa_add_cpu(int cpu) |
540 | { | 551 | { |
541 | set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); | 552 | set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); |
542 | } | 553 | } |
543 | 554 | ||
544 | void __cpuinit numa_set_node(int cpu, int node) | 555 | void __cpuinit numa_set_node(int cpu, int node) |
545 | { | 556 | { |
@@ -547,20 +558,22 @@ void __cpuinit numa_set_node(int cpu, int node) | |||
547 | cpu_to_node(cpu) = node; | 558 | cpu_to_node(cpu) = node; |
548 | } | 559 | } |
549 | 560 | ||
550 | unsigned long __init numa_free_all_bootmem(void) | 561 | unsigned long __init numa_free_all_bootmem(void) |
551 | { | 562 | { |
552 | int i; | ||
553 | unsigned long pages = 0; | 563 | unsigned long pages = 0; |
554 | for_each_online_node(i) { | 564 | int i; |
565 | |||
566 | for_each_online_node(i) | ||
555 | pages += free_all_bootmem_node(NODE_DATA(i)); | 567 | pages += free_all_bootmem_node(NODE_DATA(i)); |
556 | } | 568 | |
557 | return pages; | 569 | return pages; |
558 | } | 570 | } |
559 | 571 | ||
560 | void __init paging_init(void) | 572 | void __init paging_init(void) |
561 | { | 573 | { |
562 | int i; | ||
563 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 574 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
575 | int i; | ||
576 | |||
564 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); | 577 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); |
565 | max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; | 578 | max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; |
566 | max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; | 579 | max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; |
@@ -569,32 +582,30 @@ void __init paging_init(void) | |||
569 | sparse_memory_present_with_active_regions(MAX_NUMNODES); | 582 | sparse_memory_present_with_active_regions(MAX_NUMNODES); |
570 | sparse_init(); | 583 | sparse_init(); |
571 | 584 | ||
572 | for_each_online_node(i) { | 585 | for_each_online_node(i) |
573 | setup_node_zones(i); | 586 | setup_node_zones(i); |
574 | } | ||
575 | 587 | ||
576 | free_area_init_nodes(max_zone_pfns); | 588 | free_area_init_nodes(max_zone_pfns); |
577 | } | 589 | } |
578 | 590 | ||
579 | static __init int numa_setup(char *opt) | 591 | static __init int numa_setup(char *opt) |
580 | { | 592 | { |
581 | if (!opt) | 593 | if (!opt) |
582 | return -EINVAL; | 594 | return -EINVAL; |
583 | if (!strncmp(opt,"off",3)) | 595 | if (!strncmp(opt, "off", 3)) |
584 | numa_off = 1; | 596 | numa_off = 1; |
585 | #ifdef CONFIG_NUMA_EMU | 597 | #ifdef CONFIG_NUMA_EMU |
586 | if (!strncmp(opt, "fake=", 5)) | 598 | if (!strncmp(opt, "fake=", 5)) |
587 | cmdline = opt + 5; | 599 | cmdline = opt + 5; |
588 | #endif | 600 | #endif |
589 | #ifdef CONFIG_ACPI_NUMA | 601 | #ifdef CONFIG_ACPI_NUMA |
590 | if (!strncmp(opt,"noacpi",6)) | 602 | if (!strncmp(opt, "noacpi", 6)) |
591 | acpi_numa = -1; | 603 | acpi_numa = -1; |
592 | if (!strncmp(opt,"hotadd=", 7)) | 604 | if (!strncmp(opt, "hotadd=", 7)) |
593 | hotadd_percent = simple_strtoul(opt+7, NULL, 10); | 605 | hotadd_percent = simple_strtoul(opt+7, NULL, 10); |
594 | #endif | 606 | #endif |
595 | return 0; | 607 | return 0; |
596 | } | 608 | } |
597 | |||
598 | early_param("numa", numa_setup); | 609 | early_param("numa", numa_setup); |
599 | 610 | ||
600 | /* | 611 | /* |
@@ -612,20 +623,18 @@ early_param("numa", numa_setup); | |||
612 | void __init init_cpu_to_node(void) | 623 | void __init init_cpu_to_node(void) |
613 | { | 624 | { |
614 | int i; | 625 | int i; |
615 | for (i = 0; i < NR_CPUS; i++) { | 626 | |
627 | for (i = 0; i < NR_CPUS; i++) { | ||
616 | u8 apicid = x86_cpu_to_apicid_init[i]; | 628 | u8 apicid = x86_cpu_to_apicid_init[i]; |
629 | |||
617 | if (apicid == BAD_APICID) | 630 | if (apicid == BAD_APICID) |
618 | continue; | 631 | continue; |
619 | if (apicid_to_node[apicid] == NUMA_NO_NODE) | 632 | if (apicid_to_node[apicid] == NUMA_NO_NODE) |
620 | continue; | 633 | continue; |
621 | numa_set_node(i,apicid_to_node[apicid]); | 634 | numa_set_node(i, apicid_to_node[apicid]); |
622 | } | 635 | } |
623 | } | 636 | } |
624 | 637 | ||
625 | EXPORT_SYMBOL(cpu_to_node); | ||
626 | EXPORT_SYMBOL(node_to_cpumask); | ||
627 | EXPORT_SYMBOL(node_data); | ||
628 | |||
629 | #ifdef CONFIG_DISCONTIGMEM | 638 | #ifdef CONFIG_DISCONTIGMEM |
630 | /* | 639 | /* |
631 | * Functions to convert PFNs from/to per node page addresses. | 640 | * Functions to convert PFNs from/to per node page addresses. |