diff options
author | Andreas Herrmann <herrmann.der.user@googlemail.com> | 2009-12-16 09:43:55 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-12-16 18:06:23 -0500 |
commit | 9d260ebc09a0ad6b5c73e17676df42c7bc75ff64 (patch) | |
tree | dfe26197b99955c590796c671e25d21dc3c28c7e | |
parent | 5df974009fe513c664303de24725ea0f8b47f12e (diff) |
x86, amd: Get multi-node CPU info from NodeId MSR instead of PCI config space
Use NodeId MSR to get NodeId and number of nodes per processor.
Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
LKML-Reference: <20091216144355.GB28798@alberich.amd.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | arch/x86/include/asm/cpufeature.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/msr-index.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/amd.c | 53 |
3 files changed, 17 insertions, 38 deletions
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 613700f27a4a..637e1ec963c3 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
@@ -153,6 +153,7 @@ | |||
153 | #define X86_FEATURE_SSE5 (6*32+11) /* SSE-5 */ | 153 | #define X86_FEATURE_SSE5 (6*32+11) /* SSE-5 */ |
154 | #define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */ | 154 | #define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */ |
155 | #define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */ | 155 | #define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */ |
156 | #define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */ | ||
156 | 157 | ||
157 | /* | 158 | /* |
158 | * Auxiliary flags: Linux defined - For features scattered in various | 159 | * Auxiliary flags: Linux defined - For features scattered in various |
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index ac98d2914ebf..1cd58cdbc03f 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h | |||
@@ -124,6 +124,7 @@ | |||
124 | #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2 | 124 | #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2 |
125 | #define FAM10H_MMIO_CONF_BASE_MASK 0xfffffff | 125 | #define FAM10H_MMIO_CONF_BASE_MASK 0xfffffff |
126 | #define FAM10H_MMIO_CONF_BASE_SHIFT 20 | 126 | #define FAM10H_MMIO_CONF_BASE_SHIFT 20 |
127 | #define MSR_FAM10H_NODE_ID 0xc001100c | ||
127 | 128 | ||
128 | /* K8 MSRs */ | 129 | /* K8 MSRs */ |
129 | #define MSR_K8_TOP_MEM1 0xc001001a | 130 | #define MSR_K8_TOP_MEM1 0xc001001a |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 8dc3ea145c97..e485825130d2 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -254,59 +254,36 @@ static int __cpuinit nearby_node(int apicid) | |||
254 | 254 | ||
255 | /* | 255 | /* |
256 | * Fixup core topology information for AMD multi-node processors. | 256 | * Fixup core topology information for AMD multi-node processors. |
257 | * Assumption 1: Number of cores in each internal node is the same. | 257 | * Assumption: Number of cores in each internal node is the same. |
258 | * Assumption 2: Mixed systems with both single-node and dual-node | ||
259 | * processors are not supported. | ||
260 | */ | 258 | */ |
261 | #ifdef CONFIG_X86_HT | 259 | #ifdef CONFIG_X86_HT |
262 | static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c) | 260 | static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c) |
263 | { | 261 | { |
264 | #ifdef CONFIG_PCI | 262 | unsigned long long value; |
265 | u32 t, cpn; | 263 | u32 nodes, cores_per_node; |
266 | u8 n, n_id; | ||
267 | int cpu = smp_processor_id(); | 264 | int cpu = smp_processor_id(); |
268 | 265 | ||
266 | if (!cpu_has(c, X86_FEATURE_NODEID_MSR)) | ||
267 | return; | ||
268 | |||
269 | /* fixup topology information only once for a core */ | 269 | /* fixup topology information only once for a core */ |
270 | if (cpu_has(c, X86_FEATURE_AMD_DCM)) | 270 | if (cpu_has(c, X86_FEATURE_AMD_DCM)) |
271 | return; | 271 | return; |
272 | 272 | ||
273 | /* check for multi-node processor on boot cpu */ | 273 | rdmsrl(MSR_FAM10H_NODE_ID, value); |
274 | t = read_pci_config(0, 24, 3, 0xe8); | 274 | |
275 | if (!(t & (1 << 29))) | 275 | nodes = ((value >> 3) & 7) + 1; |
276 | if (nodes == 1) | ||
276 | return; | 277 | return; |
277 | 278 | ||
278 | set_cpu_cap(c, X86_FEATURE_AMD_DCM); | 279 | set_cpu_cap(c, X86_FEATURE_AMD_DCM); |
280 | cores_per_node = c->x86_max_cores / nodes; | ||
279 | 281 | ||
280 | /* cores per node: each internal node has half the number of cores */ | 282 | /* store NodeID, use llc_shared_map to store sibling info */ |
281 | cpn = c->x86_max_cores >> 1; | 283 | per_cpu(cpu_llc_id, cpu) = value & 7; |
282 | 284 | ||
283 | /* even-numbered NB_id of this dual-node processor */ | 285 | /* fixup core id to be in range from 0 to (cores_per_node - 1) */ |
284 | n = c->phys_proc_id << 1; | 286 | c->cpu_core_id = c->cpu_core_id % cores_per_node; |
285 | |||
286 | /* | ||
287 | * determine internal node id and assign cores fifty-fifty to | ||
288 | * each node of the dual-node processor | ||
289 | */ | ||
290 | t = read_pci_config(0, 24 + n, 3, 0xe8); | ||
291 | n = (t>>30) & 0x3; | ||
292 | if (n == 0) { | ||
293 | if (c->cpu_core_id < cpn) | ||
294 | n_id = 0; | ||
295 | else | ||
296 | n_id = 1; | ||
297 | } else { | ||
298 | if (c->cpu_core_id < cpn) | ||
299 | n_id = 1; | ||
300 | else | ||
301 | n_id = 0; | ||
302 | } | ||
303 | |||
304 | /* compute entire NodeID, use llc_shared_map to store sibling info */ | ||
305 | per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id; | ||
306 | |||
307 | /* fixup core id to be in range from 0 to cpn */ | ||
308 | c->cpu_core_id = c->cpu_core_id % cpn; | ||
309 | #endif | ||
310 | } | 287 | } |
311 | #endif | 288 | #endif |
312 | 289 | ||