]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - 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
CommitLineData
82094b55
AF
1From: Andreas Herrmann <andreas.herrmann3@amd.com>
2Subject: x86: Fix CPU llc_shared_map information for AMD Magny-Cours
3References: fate#307306
4Patch-Mainline: yes
5Commit-ID: 4a376ec3a2599c02207cd4cbd5dbf73783548463
6
7Signed-off-by: Thomas Renninger <trenn@suse.de>
8
9Construct entire NodeID and use it as cpu_llc_id. Thus internal node
10siblings are stored in llc_shared_map.
11
12Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
13Signed-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
21Index: 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) {
108Index: 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 */
120Index: 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;