diff options
author | Andreas Herrmann <andreas.herrmann3@amd.com> | 2009-09-03 03:40:21 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-09-03 18:09:59 -0400 |
commit | 4a376ec3a2599c02207cd4cbd5dbf73783548463 (patch) | |
tree | acca6af3b2f9aeccc760e393b53b1b07dcff8d4f /arch/x86/kernel/cpu/amd.c | |
parent | 8adf65cfae2d6c2ec5c06e4521f089c62f9eff05 (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.c | 64 |
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 | ||
260 | static 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)) { |