diff options
-rw-r--r-- | arch/x86/mm/numa_64.c | 99 |
1 files changed, 79 insertions, 20 deletions
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index cc390f3a1bde..dd300c491f1f 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -260,7 +260,7 @@ void __init numa_init_array(void) | |||
260 | #ifdef CONFIG_NUMA_EMU | 260 | #ifdef CONFIG_NUMA_EMU |
261 | /* Numa emulation */ | 261 | /* Numa emulation */ |
262 | static struct bootnode nodes[MAX_NUMNODES] __initdata; | 262 | static struct bootnode nodes[MAX_NUMNODES] __initdata; |
263 | static struct bootnode physnodes[MAX_NUMNODES] __initdata; | 263 | static struct bootnode physnodes[MAX_NUMNODES] __cpuinitdata; |
264 | static char *cmdline __initdata; | 264 | static char *cmdline __initdata; |
265 | 265 | ||
266 | static int __init setup_physnodes(unsigned long start, unsigned long end, | 266 | static int __init setup_physnodes(unsigned long start, unsigned long end, |
@@ -270,6 +270,7 @@ static int __init setup_physnodes(unsigned long start, unsigned long end, | |||
270 | int ret = 0; | 270 | int ret = 0; |
271 | int i; | 271 | int i; |
272 | 272 | ||
273 | memset(physnodes, 0, sizeof(physnodes)); | ||
273 | #ifdef CONFIG_ACPI_NUMA | 274 | #ifdef CONFIG_ACPI_NUMA |
274 | if (acpi) | 275 | if (acpi) |
275 | nr_nodes = acpi_get_nodes(physnodes); | 276 | nr_nodes = acpi_get_nodes(physnodes); |
@@ -370,8 +371,7 @@ static int __init setup_node_range(int nid, u64 *addr, u64 size, u64 max_addr) | |||
370 | * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr | 371 | * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr |
371 | * to max_addr. The return value is the number of nodes allocated. | 372 | * to max_addr. The return value is the number of nodes allocated. |
372 | */ | 373 | */ |
373 | static int __init split_nodes_interleave(u64 addr, u64 max_addr, | 374 | static int __init split_nodes_interleave(u64 addr, u64 max_addr, int nr_nodes) |
374 | int nr_phys_nodes, int nr_nodes) | ||
375 | { | 375 | { |
376 | nodemask_t physnode_mask = NODE_MASK_NONE; | 376 | nodemask_t physnode_mask = NODE_MASK_NONE; |
377 | u64 size; | 377 | u64 size; |
@@ -402,7 +402,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr, | |||
402 | return -1; | 402 | return -1; |
403 | } | 403 | } |
404 | 404 | ||
405 | for (i = 0; i < nr_phys_nodes; i++) | 405 | for (i = 0; i < MAX_NUMNODES; i++) |
406 | if (physnodes[i].start != physnodes[i].end) | 406 | if (physnodes[i].start != physnodes[i].end) |
407 | node_set(i, physnode_mask); | 407 | node_set(i, physnode_mask); |
408 | 408 | ||
@@ -571,11 +571,9 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
571 | { | 571 | { |
572 | u64 addr = start_pfn << PAGE_SHIFT; | 572 | u64 addr = start_pfn << PAGE_SHIFT; |
573 | u64 max_addr = last_pfn << PAGE_SHIFT; | 573 | u64 max_addr = last_pfn << PAGE_SHIFT; |
574 | int num_phys_nodes; | ||
575 | int num_nodes; | 574 | int num_nodes; |
576 | int i; | 575 | int i; |
577 | 576 | ||
578 | num_phys_nodes = setup_physnodes(addr, max_addr, acpi, amd); | ||
579 | /* | 577 | /* |
580 | * If the numa=fake command-line contains a 'M' or 'G', it represents | 578 | * If the numa=fake command-line contains a 'M' or 'G', it represents |
581 | * the fixed node size. Otherwise, if it is just a single number N, | 579 | * the fixed node size. Otherwise, if it is just a single number N, |
@@ -590,7 +588,7 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
590 | unsigned long n; | 588 | unsigned long n; |
591 | 589 | ||
592 | n = simple_strtoul(cmdline, NULL, 0); | 590 | n = simple_strtoul(cmdline, NULL, 0); |
593 | num_nodes = split_nodes_interleave(addr, max_addr, num_phys_nodes, n); | 591 | num_nodes = split_nodes_interleave(addr, max_addr, n); |
594 | } | 592 | } |
595 | 593 | ||
596 | if (num_nodes < 0) | 594 | if (num_nodes < 0) |
@@ -613,6 +611,7 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
613 | nodes[i].end >> PAGE_SHIFT); | 611 | nodes[i].end >> PAGE_SHIFT); |
614 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 612 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
615 | } | 613 | } |
614 | setup_physnodes(addr, max_addr, acpi, amd); | ||
616 | fake_physnodes(acpi, amd, num_nodes); | 615 | fake_physnodes(acpi, amd, num_nodes); |
617 | numa_init_array(); | 616 | numa_init_array(); |
618 | return 0; | 617 | return 0; |
@@ -628,8 +627,12 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, | |||
628 | nodes_clear(node_online_map); | 627 | nodes_clear(node_online_map); |
629 | 628 | ||
630 | #ifdef CONFIG_NUMA_EMU | 629 | #ifdef CONFIG_NUMA_EMU |
630 | setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT, | ||
631 | acpi, amd); | ||
631 | if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd)) | 632 | if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd)) |
632 | return; | 633 | return; |
634 | setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT, | ||
635 | acpi, amd); | ||
633 | nodes_clear(node_possible_map); | 636 | nodes_clear(node_possible_map); |
634 | nodes_clear(node_online_map); | 637 | nodes_clear(node_online_map); |
635 | #endif | 638 | #endif |
@@ -785,6 +788,7 @@ void __cpuinit numa_clear_node(int cpu) | |||
785 | 788 | ||
786 | #ifndef CONFIG_DEBUG_PER_CPU_MAPS | 789 | #ifndef CONFIG_DEBUG_PER_CPU_MAPS |
787 | 790 | ||
791 | #ifndef CONFIG_NUMA_EMU | ||
788 | void __cpuinit numa_add_cpu(int cpu) | 792 | void __cpuinit numa_add_cpu(int cpu) |
789 | { | 793 | { |
790 | cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); | 794 | cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); |
@@ -794,6 +798,51 @@ void __cpuinit numa_remove_cpu(int cpu) | |||
794 | { | 798 | { |
795 | cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); | 799 | cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); |
796 | } | 800 | } |
801 | #else | ||
802 | void __cpuinit numa_add_cpu(int cpu) | ||
803 | { | ||
804 | unsigned long addr; | ||
805 | u16 apicid; | ||
806 | int physnid; | ||
807 | int nid = NUMA_NO_NODE; | ||
808 | |||
809 | apicid = early_per_cpu(x86_cpu_to_apicid, cpu); | ||
810 | if (apicid != BAD_APICID) | ||
811 | nid = apicid_to_node[apicid]; | ||
812 | if (nid == NUMA_NO_NODE) | ||
813 | nid = early_cpu_to_node(cpu); | ||
814 | BUG_ON(nid == NUMA_NO_NODE || !node_online(nid)); | ||
815 | |||
816 | /* | ||
817 | * Use the starting address of the emulated node to find which physical | ||
818 | * node it is allocated on. | ||
819 | */ | ||
820 | addr = node_start_pfn(nid) << PAGE_SHIFT; | ||
821 | for (physnid = 0; physnid < MAX_NUMNODES; physnid++) | ||
822 | if (addr >= physnodes[physnid].start && | ||
823 | addr < physnodes[physnid].end) | ||
824 | break; | ||
825 | |||
826 | /* | ||
827 | * Map the cpu to each emulated node that is allocated on the physical | ||
828 | * node of the cpu's apic id. | ||
829 | */ | ||
830 | for_each_online_node(nid) { | ||
831 | addr = node_start_pfn(nid) << PAGE_SHIFT; | ||
832 | if (addr >= physnodes[physnid].start && | ||
833 | addr < physnodes[physnid].end) | ||
834 | cpumask_set_cpu(cpu, node_to_cpumask_map[nid]); | ||
835 | } | ||
836 | } | ||
837 | |||
838 | void __cpuinit numa_remove_cpu(int cpu) | ||
839 | { | ||
840 | int i; | ||
841 | |||
842 | for_each_online_node(i) | ||
843 | cpumask_clear_cpu(cpu, node_to_cpumask_map[i]); | ||
844 | } | ||
845 | #endif /* !CONFIG_NUMA_EMU */ | ||
797 | 846 | ||
798 | #else /* CONFIG_DEBUG_PER_CPU_MAPS */ | 847 | #else /* CONFIG_DEBUG_PER_CPU_MAPS */ |
799 | 848 | ||
@@ -805,22 +854,32 @@ static void __cpuinit numa_set_cpumask(int cpu, int enable) | |||
805 | int node = early_cpu_to_node(cpu); | 854 | int node = early_cpu_to_node(cpu); |
806 | struct cpumask *mask; | 855 | struct cpumask *mask; |
807 | char buf[64]; | 856 | char buf[64]; |
857 | int i; | ||
808 | 858 | ||
809 | mask = node_to_cpumask_map[node]; | 859 | for_each_online_node(i) { |
810 | if (mask == NULL) { | 860 | unsigned long addr; |
811 | printk(KERN_ERR "node_to_cpumask_map[%i] NULL\n", node); | ||
812 | dump_stack(); | ||
813 | return; | ||
814 | } | ||
815 | 861 | ||
816 | if (enable) | 862 | addr = node_start_pfn(i) << PAGE_SHIFT; |
817 | cpumask_set_cpu(cpu, mask); | 863 | if (addr < physnodes[node].start || |
818 | else | 864 | addr >= physnodes[node].end) |
819 | cpumask_clear_cpu(cpu, mask); | 865 | continue; |
866 | mask = node_to_cpumask_map[node]; | ||
867 | if (mask == NULL) { | ||
868 | pr_err("node_to_cpumask_map[%i] NULL\n", i); | ||
869 | dump_stack(); | ||
870 | return; | ||
871 | } | ||
872 | |||
873 | if (enable) | ||
874 | cpumask_set_cpu(cpu, mask); | ||
875 | else | ||
876 | cpumask_clear_cpu(cpu, mask); | ||
820 | 877 | ||
821 | cpulist_scnprintf(buf, sizeof(buf), mask); | 878 | cpulist_scnprintf(buf, sizeof(buf), mask); |
822 | printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", | 879 | printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", |
823 | enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node, buf); | 880 | enable ? "numa_add_cpu" : "numa_remove_cpu", |
881 | cpu, node, buf); | ||
882 | } | ||
824 | } | 883 | } |
825 | 884 | ||
826 | void __cpuinit numa_add_cpu(int cpu) | 885 | void __cpuinit numa_add_cpu(int cpu) |