1 From: Andreas Herrmann <andreas.herrmann3@amd.com>
2 Subject: x86: Fix CPU llc_shared_map information for AMD Magny-Cours
3 References: fate#307306
5 Commit-ID: 4a376ec3a2599c02207cd4cbd5dbf73783548463
7 Signed-off-by: Thomas Renninger <trenn@suse.de>
9 Construct entire NodeID and use it as cpu_llc_id. Thus internal node
10 siblings are stored in llc_shared_map.
12 Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
13 Signed-off-by: H. Peter Anvin <hpa@zytor.com>
16 arch/x86/kernel/cpu/amd.c | 62 +++++++++++++++++++++++++++++++++++++++++
17 arch/x86/kernel/cpu/amd_64.c | 64 +++++++++++++++++++++++++++++++++++++++++++
18 include/asm-x86/cpufeature.h | 1
19 3 files changed, 127 insertions(+)
21 Index: linux-2.6.27-SLE11_BRANCH/arch/x86/kernel/cpu/amd.c
22 ===================================================================
23 --- linux-2.6.27-SLE11_BRANCH.orig/arch/x86/kernel/cpu/amd.c
24 +++ linux-2.6.27-SLE11_BRANCH/arch/x86/kernel/cpu/amd.c
27 #include <asm/processor.h>
29 +#include <asm/pci-direct.h>
31 #include <mach_apic.h>
33 @@ -38,6 +39,64 @@ static void __cpuinit early_init_amd(str
34 set_cpu_cap(c, X86_FEATURE_K6_MTRR);
38 + * Fixup core topology information for AMD multi-node processors.
39 + * Assumption 1: Number of cores in each internal node is the same.
40 + * Assumption 2: Mixed systems with both single-node and dual-node
41 + * processors are not supported.
44 +static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
49 + int cpu = smp_processor_id();
51 + /* fixup topology information only once for a core */
52 + if (cpu_has(c, X86_FEATURE_AMD_DCM))
55 + /* check for multi-node processor on boot cpu */
56 + t = read_pci_config(0, 24, 3, 0xe8);
57 + if (!(t & (1 << 29)))
60 + set_cpu_cap(c, X86_FEATURE_AMD_DCM);
62 + /* cores per node: each internal node has half the number of cores */
63 + cpn = c->x86_max_cores >> 1;
65 + /* even-numbered NB_id of this dual-node processor */
66 + n = c->phys_proc_id << 1;
69 + * determine internal node id and assign cores fifty-fifty to
70 + * each node of the dual-node processor
72 + t = read_pci_config(0, 24 + n, 3, 0xe8);
75 + if (c->cpu_core_id < cpn)
80 + if (c->cpu_core_id < cpn)
86 + /* compute entire NodeID, use llc_shared_map to store sibling info */
87 + per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id;
89 + /* fixup core id to be in range from 0 to cpn */
90 + c->cpu_core_id = c->cpu_core_id % cpn;
95 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
98 @@ -250,6 +309,9 @@ static void __cpuinit init_amd(struct cp
99 printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
100 cpu, c->x86_max_cores, c->cpu_core_id);
102 + /* fixup topology information on multi-node processors */
103 + if ((c->x86 == 0x10) && (c->x86_model == 9))
107 if (cpuid_eax(0x80000000) >= 0x80000006) {
108 Index: linux-2.6.27-SLE11_BRANCH/include/asm-x86/cpufeature.h
109 ===================================================================
110 --- linux-2.6.27-SLE11_BRANCH.orig/include/asm-x86/cpufeature.h
111 +++ linux-2.6.27-SLE11_BRANCH/include/asm-x86/cpufeature.h
113 #define X86_FEATURE_AMDC1E (3*32+21) /* AMD C1E detected */
114 #define X86_FEATURE_XTOPOLOGY (3*32+22) /* cpu topology enum extensions */
115 #define X86_FEATURE_TSC_RELIABLE (3*32+23) /* TSC is known to be reliable */
116 +#define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */
118 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
119 #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
120 Index: linux-2.6.27-SLE11_BRANCH/arch/x86/kernel/cpu/amd_64.c
121 ===================================================================
122 --- linux-2.6.27-SLE11_BRANCH.orig/arch/x86/kernel/cpu/amd_64.c
123 +++ linux-2.6.27-SLE11_BRANCH/arch/x86/kernel/cpu/amd_64.c
125 #include <asm/numa_64.h>
126 #include <asm/mmconfig.h>
127 #include <asm/cacheflush.h>
128 +#include <asm/pci-direct.h>
130 #include <mach_apic.h>
132 @@ -31,6 +32,64 @@ static int __cpuinit nearby_node(int api
136 + * Fixup core topology information for AMD multi-node processors.
137 + * Assumption 1: Number of cores in each internal node is the same.
138 + * Assumption 2: Mixed systems with both single-node and dual-node
139 + * processors are not supported.
141 +#ifdef CONFIG_X86_HT
142 +static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
147 + int cpu = smp_processor_id();
149 + /* fixup topology information only once for a core */
150 + if (cpu_has(c, X86_FEATURE_AMD_DCM))
153 + /* check for multi-node processor on boot cpu */
154 + t = read_pci_config(0, 24, 3, 0xe8);
155 + if (!(t & (1 << 29)))
158 + set_cpu_cap(c, X86_FEATURE_AMD_DCM);
160 + /* cores per node: each internal node has half the number of cores */
161 + cpn = c->x86_max_cores >> 1;
163 + /* even-numbered NB_id of this dual-node processor */
164 + n = c->phys_proc_id << 1;
167 + * determine internal node id and assign cores fifty-fifty to
168 + * each node of the dual-node processor
170 + t = read_pci_config(0, 24 + n, 3, 0xe8);
173 + if (c->cpu_core_id < cpn)
178 + if (c->cpu_core_id < cpn)
184 + /* compute entire NodeID, use llc_shared_map to store sibling info */
185 + per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id;
187 + /* fixup core id to be in range from 0 to cpn */
188 + c->cpu_core_id = c->cpu_core_id % cpn;
194 * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
195 * Assumes number of cores is a power of two.
197 @@ -49,6 +108,11 @@ static void __cpuinit amd_detect_cmp(str
198 c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
199 /* Convert the initial APIC ID into the socket ID */
200 c->phys_proc_id = c->initial_apicid >> bits;
201 +#ifdef CONFIG_X86_HT
202 + /* fixup topology information on multi-node processors */
203 + if ((c->x86 == 0x10) && (c->x86_model == 9))
208 node = c->phys_proc_id;