]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.arch/amd_magny_cour_topology_fix.patch
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / amd_magny_cour_topology_fix.patch
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
4 Patch-Mainline: yes
5 Commit-ID: 4a376ec3a2599c02207cd4cbd5dbf73783548463
6
7 Signed-off-by: Thomas Renninger <trenn@suse.de>
8
9 Construct entire NodeID and use it as cpu_llc_id. Thus internal node
10 siblings are stored in llc_shared_map.
11
12 Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
13 Signed-off-by: H. Peter Anvin <hpa@zytor.com>
14
15 ---
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(+)
20
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
25 @@ -4,6 +4,7 @@
26 #include <asm/io.h>
27 #include <asm/processor.h>
28 #include <asm/apic.h>
29 +#include <asm/pci-direct.h>
30
31 #include <mach_apic.h>
32 #include "cpu.h"
33 @@ -38,6 +39,64 @@ static void __cpuinit early_init_amd(str
34 set_cpu_cap(c, X86_FEATURE_K6_MTRR);
35 }
36
37 +/*
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.
42 + */
43 +#ifdef CONFIG_X86_HT
44 +static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
45 +{
46 +#ifdef CONFIG_PCI
47 + u32 t, cpn;
48 + u8 n, n_id;
49 + int cpu = smp_processor_id();
50 +
51 + /* fixup topology information only once for a core */
52 + if (cpu_has(c, X86_FEATURE_AMD_DCM))
53 + return;
54 +
55 + /* check for multi-node processor on boot cpu */
56 + t = read_pci_config(0, 24, 3, 0xe8);
57 + if (!(t & (1 << 29)))
58 + return;
59 +
60 + set_cpu_cap(c, X86_FEATURE_AMD_DCM);
61 +
62 + /* cores per node: each internal node has half the number of cores */
63 + cpn = c->x86_max_cores >> 1;
64 +
65 + /* even-numbered NB_id of this dual-node processor */
66 + n = c->phys_proc_id << 1;
67 +
68 + /*
69 + * determine internal node id and assign cores fifty-fifty to
70 + * each node of the dual-node processor
71 + */
72 + t = read_pci_config(0, 24 + n, 3, 0xe8);
73 + n = (t>>30) & 0x3;
74 + if (n == 0) {
75 + if (c->cpu_core_id < cpn)
76 + n_id = 0;
77 + else
78 + n_id = 1;
79 + } else {
80 + if (c->cpu_core_id < cpn)
81 + n_id = 1;
82 + else
83 + n_id = 0;
84 + }
85 +
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;
88 +
89 + /* fixup core id to be in range from 0 to cpn */
90 + c->cpu_core_id = c->cpu_core_id % cpn;
91 +#endif
92 +}
93 +#endif
94 +
95 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
96 {
97 u32 l, h;
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);
101 }
102 + /* fixup topology information on multi-node processors */
103 + if ((c->x86 == 0x10) && (c->x86_model == 9))
104 + amd_fixup_dcm(c);
105 #endif
106
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
112 @@ -84,6 +84,7 @@
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 */
117
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
124 @@ -4,6 +4,7 @@
125 #include <asm/numa_64.h>
126 #include <asm/mmconfig.h>
127 #include <asm/cacheflush.h>
128 +#include <asm/pci-direct.h>
129
130 #include <mach_apic.h>
131
132 @@ -31,6 +32,64 @@ static int __cpuinit nearby_node(int api
133 #endif
134
135 /*
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.
140 + */
141 +#ifdef CONFIG_X86_HT
142 +static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
143 +{
144 +#ifdef CONFIG_PCI
145 + u32 t, cpn;
146 + u8 n, n_id;
147 + int cpu = smp_processor_id();
148 +
149 + /* fixup topology information only once for a core */
150 + if (cpu_has(c, X86_FEATURE_AMD_DCM))
151 + return;
152 +
153 + /* check for multi-node processor on boot cpu */
154 + t = read_pci_config(0, 24, 3, 0xe8);
155 + if (!(t & (1 << 29)))
156 + return;
157 +
158 + set_cpu_cap(c, X86_FEATURE_AMD_DCM);
159 +
160 + /* cores per node: each internal node has half the number of cores */
161 + cpn = c->x86_max_cores >> 1;
162 +
163 + /* even-numbered NB_id of this dual-node processor */
164 + n = c->phys_proc_id << 1;
165 +
166 + /*
167 + * determine internal node id and assign cores fifty-fifty to
168 + * each node of the dual-node processor
169 + */
170 + t = read_pci_config(0, 24 + n, 3, 0xe8);
171 + n = (t>>30) & 0x3;
172 + if (n == 0) {
173 + if (c->cpu_core_id < cpn)
174 + n_id = 0;
175 + else
176 + n_id = 1;
177 + } else {
178 + if (c->cpu_core_id < cpn)
179 + n_id = 1;
180 + else
181 + n_id = 0;
182 + }
183 +
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;
186 +
187 + /* fixup core id to be in range from 0 to cpn */
188 + c->cpu_core_id = c->cpu_core_id % cpn;
189 +#endif
190 +}
191 +#endif
192 +
193 +/*
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.
196 */
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))
204 + amd_fixup_dcm(c);
205 +#endif
206
207 #ifdef CONFIG_NUMA
208 node = c->phys_proc_id;