diff options
| -rw-r--r-- | arch/x86/include/asm/cpufeature.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 64 |
2 files changed, 64 insertions, 1 deletions
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 4a28d22d4793..847fee6493a2 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
| @@ -95,6 +95,7 @@ | |||
| 95 | #define X86_FEATURE_NONSTOP_TSC (3*32+24) /* TSC does not stop in C states */ | 95 | #define X86_FEATURE_NONSTOP_TSC (3*32+24) /* TSC does not stop in C states */ |
| 96 | #define X86_FEATURE_CLFLUSH_MONITOR (3*32+25) /* "" clflush reqd with monitor */ | 96 | #define X86_FEATURE_CLFLUSH_MONITOR (3*32+25) /* "" clflush reqd with monitor */ |
| 97 | #define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */ | 97 | #define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */ |
| 98 | #define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */ | ||
| 98 | 99 | ||
| 99 | /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ | 100 | /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ |
| 100 | #define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */ | 101 | #define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */ |
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)) { |
