aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/amd.c
diff options
context:
space:
mode:
authorAndreas Herrmann <andreas.herrmann3@amd.com>2009-09-03 03:40:21 -0400
committerH. Peter Anvin <hpa@zytor.com>2009-09-03 18:09:59 -0400
commit4a376ec3a2599c02207cd4cbd5dbf73783548463 (patch)
treeacca6af3b2f9aeccc760e393b53b1b07dcff8d4f /arch/x86/kernel/cpu/amd.c
parent8adf65cfae2d6c2ec5c06e4521f089c62f9eff05 (diff)
x86: Fix CPU llc_shared_map information for AMD Magny-Cours
Construct entire NodeID and use it as cpu_llc_id. Thus internal node siblings are stored in llc_shared_map. Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/cpu/amd.c')
-rw-r--r--arch/x86/kernel/cpu/amd.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 0a717fc6aeb6..a76d2c18f150 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -251,6 +251,64 @@ static int __cpuinit nearby_node(int apicid)
251#endif 251#endif
252 252
253/* 253/*
254 * Fixup core topology information for AMD multi-node processors.
255 * Assumption 1: Number of cores in each internal node is the same.
256 * Assumption 2: Mixed systems with both single-node and dual-node
257 * processors are not supported.
258 */
259#ifdef CONFIG_X86_HT
260static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
261{
262#ifdef CONFIG_PCI
263 u32 t, cpn;
264 u8 n, n_id;
265 int cpu = smp_processor_id();
266
267 /* fixup topology information only once for a core */
268 if (cpu_has(c, X86_FEATURE_AMD_DCM))
269 return;
270
271 /* check for multi-node processor on boot cpu */
272 t = read_pci_config(0, 24, 3, 0xe8);
273 if (!(t & (1 << 29)))
274 return;
275
276 set_cpu_cap(c, X86_FEATURE_AMD_DCM);
277
278 /* cores per node: each internal node has half the number of cores */
279 cpn = c->x86_max_cores >> 1;
280
281 /* even-numbered NB_id of this dual-node processor */
282 n = c->phys_proc_id << 1;
283
284 /*
285 * determine internal node id and assign cores fifty-fifty to
286 * each node of the dual-node processor
287 */
288 t = read_pci_config(0, 24 + n, 3, 0xe8);
289 n = (t>>30) & 0x3;
290 if (n == 0) {
291 if (c->cpu_core_id < cpn)
292 n_id = 0;
293 else
294 n_id = 1;
295 } else {
296 if (c->cpu_core_id < cpn)
297 n_id = 1;
298 else
299 n_id = 0;
300 }
301
302 /* compute entire NodeID, use llc_shared_map to store sibling info */
303 per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id;
304
305 /* fixup core id to be in range from 0 to cpn */
306 c->cpu_core_id = c->cpu_core_id % cpn;
307#endif
308}
309#endif
310
311/*
254 * On a AMD dual core setup the lower bits of the APIC id distingush the cores. 312 * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
255 * Assumes number of cores is a power of two. 313 * Assumes number of cores is a power of two.
256 */ 314 */
@@ -267,6 +325,9 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
267 c->phys_proc_id = c->initial_apicid >> bits; 325 c->phys_proc_id = c->initial_apicid >> bits;
268 /* use socket ID also for last level cache */ 326 /* use socket ID also for last level cache */
269 per_cpu(cpu_llc_id, cpu) = c->phys_proc_id; 327 per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
328 /* fixup topology information on multi-node processors */
329 if ((c->x86 == 0x10) && (c->x86_model == 9))
330 amd_fixup_dcm(c);
270#endif 331#endif
271} 332}
272 333
@@ -277,7 +338,8 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
277 int node; 338 int node;
278 unsigned apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid; 339 unsigned apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid;
279 340
280 node = c->phys_proc_id; 341 node = per_cpu(cpu_llc_id, cpu);
342
281 if (apicid_to_node[apicid] != NUMA_NO_NODE) 343 if (apicid_to_node[apicid] != NUMA_NO_NODE)
282 node = apicid_to_node[apicid]; 344 node = apicid_to_node[apicid];
283 if (!node_online(node)) { 345 if (!node_online(node)) {