aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/mm/k8topology.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-09-12 12:49:24 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-12 13:49:56 -0400
commit3f098c2605bdf50176b26f4fa724e9b9c99e5242 (patch)
treed4632bc555c52afed6ae4c0444659dca49e3e406 /arch/x86_64/mm/k8topology.c
parentb91691164be174b780f5c1bb145a7ab5d33fce2f (diff)
[PATCH] x86-64: Support dualcore and 8 socket systems in k8 fallback node parsing
In particular on systems where the local APIC space and node space is very different from the Linux CPU number space. Previously the older NUMA setup code directly parsing the K8 northbridge registers had some issues on 8 socket or dual core systems. This patch fixes them. This is mainly done by fixing some confusion between Linux CPU numbers and local APIC ids. We now pass the local APIC IDs to later code, which avoids mismatches. Also add some heuristics to detect cases where the Hypertransport nodeids and the local APIC IDs don't match, but are shifted by a constant offset. This is still all quite hackish, hopefully BIOS writers fill in correct SRATs instead. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/mm/k8topology.c')
-rw-r--r--arch/x86_64/mm/k8topology.c13
1 files changed, 10 insertions, 3 deletions
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 }