1 From: Suresh Siddha <suresh.b.siddha@intel.com>
2 Subject: x86: use cpuid vector 0xb when available for detecting cpu topology
3 References: fate #303948 and fate #303984
4 Patch-Mainline: queued for .28
5 Commit-ID: bbb65d2d365efe9951290e61678dcf81ec60add4
7 Signed-off-by: Thomas Renninger <trenn@suse.de>
9 cpuid leaf 0xb provides extended topology enumeration. This interface provides
10 the 32-bit x2APIC id of the logical processor and it also provides a new
11 mechanism to detect SMT and core siblings (which provides increased
14 Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
15 Signed-off-by: Ingo Molnar <mingo@elte.hu>
18 arch/x86/kernel/cpu/addon_cpuid_features.c | 86 +++++++++++++++++++++++++++++
19 arch/x86/kernel/cpu/common_64.c | 3 +
20 arch/x86/kernel/cpu/intel.c | 11 +++
21 arch/x86/kernel/cpu/intel_64.c | 5 +
22 include/asm-x86/cpufeature.h | 2
23 include/asm-x86/processor.h | 1
24 6 files changed, 105 insertions(+), 3 deletions(-)
26 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c
27 +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c
30 #include <asm/processor.h>
32 +#include <mach_apic.h>
37 @@ -48,6 +50,90 @@ void __cpuinit init_scattered_cpuid_feat
41 +/* leaf 0xb SMT level */
44 +/* leaf 0xb sub-leaf types */
45 +#define INVALID_TYPE 0
49 +#define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff)
50 +#define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f)
51 +#define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff)
54 + * Check for extended topology enumeration cpuid leaf 0xb and if it
55 + * exists, use it for populating initial_apicid and cpu topology
58 +void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c)
60 + unsigned int eax, ebx, ecx, edx, sub_index;
61 + unsigned int ht_mask_width, core_plus_mask_width;
62 + unsigned int core_select_mask, core_level_siblings;
64 + if (c->cpuid_level < 0xb)
67 + cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
70 + * check if the cpuid leaf 0xb is actually implemented.
72 + if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
75 + set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
78 + * initial apic id, which also represents 32-bit extended x2apic id.
80 + c->initial_apicid = edx;
83 + * Populate HT related information from sub-leaf level 0.
85 + core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
86 + core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
90 + cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx);
93 + * Check for the Core type in the implemented sub leaves.
95 + if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
96 + core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
97 + core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
102 + } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
104 + core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
106 +#ifdef CONFIG_X86_32
107 + c->cpu_core_id = phys_pkg_id(c->initial_apicid, ht_mask_width)
108 + & core_select_mask;
109 + c->phys_proc_id = phys_pkg_id(c->initial_apicid, core_plus_mask_width);
111 + c->cpu_core_id = phys_pkg_id(ht_mask_width) & core_select_mask;
112 + c->phys_proc_id = phys_pkg_id(core_plus_mask_width);
114 + c->x86_max_cores = (core_level_siblings / smp_num_siblings);
117 + printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
119 + if (c->x86_max_cores > 1)
120 + printk(KERN_INFO "CPU: Processor Core ID: %d\n",
125 #ifdef CONFIG_X86_PAT
126 void __cpuinit validate_pat_support(struct cpuinfo_x86 *c)
128 --- a/arch/x86/kernel/cpu/common_64.c
129 +++ b/arch/x86/kernel/cpu/common_64.c
130 @@ -128,6 +128,9 @@ void __cpuinit detect_ht(struct cpuinfo_
131 u32 eax, ebx, ecx, edx;
132 int index_msb, core_bits;
134 + if (cpu_has(c, X86_FEATURE_XTOPOLOGY))
137 cpuid(1, &eax, &ebx, &ecx, &edx);
140 --- a/arch/x86/kernel/cpu/intel_64.c
141 +++ b/arch/x86/kernel/cpu/intel_64.c
142 @@ -93,7 +93,10 @@ static void __cpuinit init_intel(struct
144 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
145 set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
146 - c->x86_max_cores = intel_num_cpu_cores(c);
148 + detect_extended_topology(c);
149 + if (!cpu_has(c, X86_FEATURE_XTOPOLOGY))
150 + c->x86_max_cores = intel_num_cpu_cores(c);
154 --- a/arch/x86/kernel/cpu/intel.c
155 +++ b/arch/x86/kernel/cpu/intel.c
156 @@ -196,9 +196,16 @@ static void __cpuinit init_intel(struct
158 strcpy(c->x86_model_id, p);
160 - c->x86_max_cores = num_cpu_cores(c);
161 + detect_extended_topology(c);
164 + if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) {
166 + * let's use the legacy cpuid vector 0x1 and 0x4 for topology
169 + c->x86_max_cores = num_cpu_cores(c);
173 /* Work around errata */
174 Intel_errata_workarounds(c);
175 --- a/include/asm-x86/cpufeature.h
176 +++ b/include/asm-x86/cpufeature.h
178 #define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */
179 #define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */
180 #define X86_FEATURE_AMDC1E (3*32+21) /* AMD C1E detected */
181 +#define X86_FEATURE_XTOPOLOGY (3*32+22) /* cpu topology enum extensions */
184 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
185 #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
186 --- a/include/asm-x86/processor.h
187 +++ b/include/asm-x86/processor.h
188 @@ -161,6 +161,7 @@ extern void init_scattered_cpuid_feature
189 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
190 extern unsigned short num_cache_leaves;
192 +extern void detect_extended_topology(struct cpuinfo_x86 *c);
193 #if defined(CONFIG_X86_HT) || defined(CONFIG_X86_64)
194 extern void detect_ht(struct cpuinfo_x86 *c);