diff options
-rw-r--r-- | arch/x86_64/kernel/setup.c | 64 | ||||
-rw-r--r-- | arch/x86_64/mm/k8topology.c | 13 | ||||
-rw-r--r-- | arch/x86_64/mm/numa.c | 10 | ||||
-rw-r--r-- | include/asm-x86_64/apicdef.h | 1 |
4 files changed, 63 insertions, 25 deletions
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 976ebcf96f3e..df55a63f8866 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
@@ -755,6 +755,24 @@ static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) | |||
755 | } | 755 | } |
756 | } | 756 | } |
757 | 757 | ||
758 | #ifdef CONFIG_NUMA | ||
759 | static int nearby_node(int apicid) | ||
760 | { | ||
761 | int i; | ||
762 | for (i = apicid - 1; i >= 0; i--) { | ||
763 | int node = apicid_to_node[i]; | ||
764 | if (node != NUMA_NO_NODE && node_online(node)) | ||
765 | return node; | ||
766 | } | ||
767 | for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) { | ||
768 | int node = apicid_to_node[i]; | ||
769 | if (node != NUMA_NO_NODE && node_online(node)) | ||
770 | return node; | ||
771 | } | ||
772 | return first_node(node_online_map); /* Shouldn't happen */ | ||
773 | } | ||
774 | #endif | ||
775 | |||
758 | /* | 776 | /* |
759 | * On a AMD dual core setup the lower bits of the APIC id distingush the cores. | 777 | * On a AMD dual core setup the lower bits of the APIC id distingush the cores. |
760 | * Assumes number of cores is a power of two. | 778 | * Assumes number of cores is a power of two. |
@@ -763,9 +781,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
763 | { | 781 | { |
764 | #ifdef CONFIG_SMP | 782 | #ifdef CONFIG_SMP |
765 | int cpu = smp_processor_id(); | 783 | int cpu = smp_processor_id(); |
766 | int node = 0; | ||
767 | unsigned bits; | 784 | unsigned bits; |
785 | #ifdef CONFIG_NUMA | ||
786 | int node = 0; | ||
768 | unsigned apicid = phys_proc_id[cpu]; | 787 | unsigned apicid = phys_proc_id[cpu]; |
788 | #endif | ||
769 | 789 | ||
770 | bits = 0; | 790 | bits = 0; |
771 | while ((1 << bits) < c->x86_num_cores) | 791 | while ((1 << bits) < c->x86_num_cores) |
@@ -777,24 +797,32 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
777 | phys_proc_id[cpu] >>= bits; | 797 | phys_proc_id[cpu] >>= bits; |
778 | 798 | ||
779 | #ifdef CONFIG_NUMA | 799 | #ifdef CONFIG_NUMA |
780 | /* When an ACPI SRAT table is available use the mappings from SRAT | 800 | node = phys_proc_id[cpu]; |
781 | instead. */ | 801 | if (apicid_to_node[apicid] != NUMA_NO_NODE) |
782 | node = phys_proc_id[cpu]; | 802 | node = apicid_to_node[apicid]; |
783 | if (acpi_numa > 0) { | 803 | if (!node_online(node)) { |
784 | if (apicid_to_node[apicid] != NUMA_NO_NODE) | 804 | /* Two possibilities here: |
785 | node = apicid_to_node[apicid]; | 805 | - The CPU is missing memory and no node was created. |
786 | else | 806 | In that case try picking one from a nearby CPU |
787 | printk(KERN_ERR | 807 | - The APIC IDs differ from the HyperTransport node IDs |
788 | "SRAT: Didn't specify node for CPU %d(%d)\n", | 808 | which the K8 northbridge parsing fills in. |
789 | cpu, apicid); | 809 | Assume they are all increased by a constant offset, |
790 | } | 810 | but in the same order as the HT nodeids. |
791 | if (!node_online(node)) | 811 | If that doesn't result in a usable node fall back to the |
792 | node = first_node(node_online_map); | 812 | path for the previous case. */ |
793 | cpu_to_node[cpu] = node; | 813 | int ht_nodeid = apicid - (phys_proc_id[0] << bits); |
814 | if (ht_nodeid >= 0 && | ||
815 | apicid_to_node[ht_nodeid] != NUMA_NO_NODE) | ||
816 | node = apicid_to_node[ht_nodeid]; | ||
817 | /* Pick a nearby node */ | ||
818 | if (!node_online(node)) | ||
819 | node = nearby_node(apicid); | ||
820 | } | ||
821 | cpu_to_node[cpu] = node; | ||
822 | |||
823 | printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", | ||
824 | cpu, c->x86_num_cores, node, cpu_core_id[cpu]); | ||
794 | #endif | 825 | #endif |
795 | |||
796 | printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", | ||
797 | cpu, c->x86_num_cores, node, cpu_core_id[cpu]); | ||
798 | #endif | 826 | #endif |
799 | } | 827 | } |
800 | 828 | ||
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index ec35747aacd7..65417b040c1b 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c | |||
@@ -45,10 +45,12 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) | |||
45 | unsigned long prevbase; | 45 | unsigned long prevbase; |
46 | struct node nodes[8]; | 46 | struct node nodes[8]; |
47 | int nodeid, i, nb; | 47 | int nodeid, i, nb; |
48 | unsigned char nodeids[8]; | ||
48 | int found = 0; | 49 | int found = 0; |
49 | u32 reg; | 50 | u32 reg; |
50 | unsigned numnodes; | 51 | unsigned numnodes; |
51 | nodemask_t nodes_parsed; | 52 | nodemask_t nodes_parsed; |
53 | unsigned dualcore = 0; | ||
52 | 54 | ||
53 | nodes_clear(nodes_parsed); | 55 | nodes_clear(nodes_parsed); |
54 | 56 | ||
@@ -67,11 +69,15 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) | |||
67 | prevbase = 0; | 69 | prevbase = 0; |
68 | for (i = 0; i < 8; i++) { | 70 | for (i = 0; i < 8; i++) { |
69 | unsigned long base,limit; | 71 | unsigned long base,limit; |
70 | 72 | u32 nodeid; | |
73 | |||
74 | /* Undefined before E stepping, but hopefully 0 */ | ||
75 | dualcore |= ((read_pci_config(0, nb, 3, 0xe8) >> 12) & 3) == 1; | ||
71 | base = read_pci_config(0, nb, 1, 0x40 + i*8); | 76 | base = read_pci_config(0, nb, 1, 0x40 + i*8); |
72 | limit = read_pci_config(0, nb, 1, 0x44 + i*8); | 77 | limit = read_pci_config(0, nb, 1, 0x44 + i*8); |
73 | 78 | ||
74 | nodeid = limit & 7; | 79 | nodeid = limit & 7; |
80 | nodeids[i] = nodeid; | ||
75 | if ((base & 3) == 0) { | 81 | if ((base & 3) == 0) { |
76 | if (i < numnodes) | 82 | if (i < numnodes) |
77 | printk("Skipping disabled node %d\n", i); | 83 | printk("Skipping disabled node %d\n", i); |
@@ -157,8 +163,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) | |||
157 | 163 | ||
158 | for (i = 0; i < 8; i++) { | 164 | for (i = 0; i < 8; i++) { |
159 | if (nodes[i].start != nodes[i].end) { | 165 | if (nodes[i].start != nodes[i].end) { |
160 | /* assume 1:1 NODE:CPU */ | 166 | nodeid = nodeids[i]; |
161 | cpu_to_node[i] = i; | 167 | apicid_to_node[nodeid << dualcore] = i; |
168 | apicid_to_node[(nodeid << dualcore) + dualcore] = i; | ||
162 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 169 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
163 | } | 170 | } |
164 | } | 171 | } |
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 5b1518629893..80a49d9bd8a7 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c | |||
@@ -28,11 +28,13 @@ bootmem_data_t plat_node_bdata[MAX_NUMNODES]; | |||
28 | int memnode_shift; | 28 | int memnode_shift; |
29 | u8 memnodemap[NODEMAPSIZE]; | 29 | u8 memnodemap[NODEMAPSIZE]; |
30 | 30 | ||
31 | unsigned char cpu_to_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = NUMA_NO_NODE }; | 31 | unsigned char cpu_to_node[NR_CPUS] __read_mostly = { |
32 | unsigned char apicid_to_node[256] __cpuinitdata = { | 32 | [0 ... NR_CPUS-1] = NUMA_NO_NODE |
33 | [0 ... NR_CPUS-1] = NUMA_NO_NODE | ||
34 | }; | 33 | }; |
35 | cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly; | 34 | unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = { |
35 | [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE | ||
36 | }; | ||
37 | cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly; | ||
36 | 38 | ||
37 | int numa_off __initdata; | 39 | int numa_off __initdata; |
38 | 40 | ||
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h index 9388062c4f6e..fb1c99ac669f 100644 --- a/include/asm-x86_64/apicdef.h +++ b/include/asm-x86_64/apicdef.h | |||
@@ -113,6 +113,7 @@ | |||
113 | #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) | 113 | #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) |
114 | 114 | ||
115 | #define MAX_IO_APICS 128 | 115 | #define MAX_IO_APICS 128 |
116 | #define MAX_LOCAL_APIC 256 | ||
116 | 117 | ||
117 | /* | 118 | /* |
118 | * All x86-64 systems are xAPIC compatible. | 119 | * All x86-64 systems are xAPIC compatible. |