diff options
-rw-r--r-- | arch/x86/kernel/cpu/addon_cpuid_features.c | 86 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common_64.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 13 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel_64.c | 5 | ||||
-rw-r--r-- | include/asm-x86/cpufeature.h | 1 | ||||
-rw-r--r-- | include/asm-x86/processor.h | 1 |
6 files changed, 105 insertions, 4 deletions
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 84a8220a6072..aa9641ae6703 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #include <asm/pat.h> | 7 | #include <asm/pat.h> |
8 | #include <asm/processor.h> | 8 | #include <asm/processor.h> |
9 | 9 | ||
10 | #include <mach_apic.h> | ||
11 | |||
10 | struct cpuid_bit { | 12 | struct cpuid_bit { |
11 | u16 feature; | 13 | u16 feature; |
12 | u8 reg; | 14 | u8 reg; |
@@ -48,6 +50,90 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |||
48 | } | 50 | } |
49 | } | 51 | } |
50 | 52 | ||
53 | /* leaf 0xb SMT level */ | ||
54 | #define SMT_LEVEL 0 | ||
55 | |||
56 | /* leaf 0xb sub-leaf types */ | ||
57 | #define INVALID_TYPE 0 | ||
58 | #define SMT_TYPE 1 | ||
59 | #define CORE_TYPE 2 | ||
60 | |||
61 | #define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff) | ||
62 | #define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f) | ||
63 | #define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff) | ||
64 | |||
65 | /* | ||
66 | * Check for extended topology enumeration cpuid leaf 0xb and if it | ||
67 | * exists, use it for populating initial_apicid and cpu topology | ||
68 | * detection. | ||
69 | */ | ||
70 | void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) | ||
71 | { | ||
72 | unsigned int eax, ebx, ecx, edx, sub_index; | ||
73 | unsigned int ht_mask_width, core_plus_mask_width; | ||
74 | unsigned int core_select_mask, core_level_siblings; | ||
75 | |||
76 | if (c->cpuid_level < 0xb) | ||
77 | return; | ||
78 | |||
79 | cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); | ||
80 | |||
81 | /* | ||
82 | * check if the cpuid leaf 0xb is actually implemented. | ||
83 | */ | ||
84 | if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) | ||
85 | return; | ||
86 | |||
87 | set_cpu_cap(c, X86_FEATURE_XTOPOLOGY); | ||
88 | |||
89 | /* | ||
90 | * initial apic id, which also represents 32-bit extended x2apic id. | ||
91 | */ | ||
92 | c->initial_apicid = edx; | ||
93 | |||
94 | /* | ||
95 | * Populate HT related information from sub-leaf level 0. | ||
96 | */ | ||
97 | core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); | ||
98 | core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); | ||
99 | |||
100 | sub_index = 1; | ||
101 | do { | ||
102 | cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx); | ||
103 | |||
104 | /* | ||
105 | * Check for the Core type in the implemented sub leaves. | ||
106 | */ | ||
107 | if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) { | ||
108 | core_level_siblings = LEVEL_MAX_SIBLINGS(ebx); | ||
109 | core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | sub_index++; | ||
114 | } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE); | ||
115 | |||
116 | core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; | ||
117 | |||
118 | #ifdef CONFIG_X86_32 | ||
119 | c->cpu_core_id = phys_pkg_id(c->initial_apicid, ht_mask_width) | ||
120 | & core_select_mask; | ||
121 | c->phys_proc_id = phys_pkg_id(c->initial_apicid, core_plus_mask_width); | ||
122 | #else | ||
123 | c->cpu_core_id = phys_pkg_id(ht_mask_width) & core_select_mask; | ||
124 | c->phys_proc_id = phys_pkg_id(core_plus_mask_width); | ||
125 | #endif | ||
126 | c->x86_max_cores = (core_level_siblings / smp_num_siblings); | ||
127 | |||
128 | |||
129 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | ||
130 | c->phys_proc_id); | ||
131 | if (c->x86_max_cores > 1) | ||
132 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | ||
133 | c->cpu_core_id); | ||
134 | return; | ||
135 | } | ||
136 | |||
51 | #ifdef CONFIG_X86_PAT | 137 | #ifdef CONFIG_X86_PAT |
52 | void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) | 138 | void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) |
53 | { | 139 | { |
diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index af569a964e74..a2888c7b56ac 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c | |||
@@ -128,6 +128,9 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) | |||
128 | u32 eax, ebx, ecx, edx; | 128 | u32 eax, ebx, ecx, edx; |
129 | int index_msb, core_bits; | 129 | int index_msb, core_bits; |
130 | 130 | ||
131 | if (cpu_has(c, X86_FEATURE_XTOPOLOGY)) | ||
132 | return; | ||
133 | |||
131 | cpuid(1, &eax, &ebx, &ecx, &edx); | 134 | cpuid(1, &eax, &ebx, &ecx, &edx); |
132 | 135 | ||
133 | 136 | ||
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 77618c717d76..58a6f1a0b297 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -176,9 +176,16 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
176 | if (p) | 176 | if (p) |
177 | strcpy(c->x86_model_id, p); | 177 | strcpy(c->x86_model_id, p); |
178 | 178 | ||
179 | c->x86_max_cores = num_cpu_cores(c); | 179 | detect_extended_topology(c); |
180 | 180 | ||
181 | detect_ht(c); | 181 | if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) { |
182 | /* | ||
183 | * let's use the legacy cpuid vector 0x1 and 0x4 for topology | ||
184 | * detection. | ||
185 | */ | ||
186 | c->x86_max_cores = num_cpu_cores(c); | ||
187 | detect_ht(c); | ||
188 | } | ||
182 | 189 | ||
183 | /* Work around errata */ | 190 | /* Work around errata */ |
184 | Intel_errata_workarounds(c); | 191 | Intel_errata_workarounds(c); |
diff --git a/arch/x86/kernel/cpu/intel_64.c b/arch/x86/kernel/cpu/intel_64.c index 1019c58d39f0..42d501a8c418 100644 --- a/arch/x86/kernel/cpu/intel_64.c +++ b/arch/x86/kernel/cpu/intel_64.c | |||
@@ -80,7 +80,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
80 | if (c->x86 == 6) | 80 | if (c->x86 == 6) |
81 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); | 81 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); |
82 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | 82 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); |
83 | c->x86_max_cores = intel_num_cpu_cores(c); | 83 | |
84 | detect_extended_topology(c); | ||
85 | if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) | ||
86 | c->x86_max_cores = intel_num_cpu_cores(c); | ||
84 | 87 | ||
85 | srat_detect_node(); | 88 | srat_detect_node(); |
86 | } | 89 | } |
diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 5fc4d55906d4..8d842af4cf7a 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h | |||
@@ -81,6 +81,7 @@ | |||
81 | #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */ | 81 | #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */ |
82 | #define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ | 82 | #define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ |
83 | #define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ | 83 | #define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ |
84 | #define X86_FEATURE_XTOPOLOGY (3*32+21) /* cpu topology enum extensions */ | ||
84 | 85 | ||
85 | /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ | 86 | /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ |
86 | #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ | 87 | #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ |
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 5f58da401b43..79338fe965d2 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h | |||
@@ -161,6 +161,7 @@ extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c); | |||
161 | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); | 161 | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); |
162 | extern unsigned short num_cache_leaves; | 162 | extern unsigned short num_cache_leaves; |
163 | 163 | ||
164 | extern void detect_extended_topology(struct cpuinfo_x86 *c); | ||
164 | #if defined(CONFIG_X86_HT) || defined(CONFIG_X86_64) | 165 | #if defined(CONFIG_X86_HT) || defined(CONFIG_X86_64) |
165 | extern void detect_ht(struct cpuinfo_x86 *c); | 166 | extern void detect_ht(struct cpuinfo_x86 *c); |
166 | #else | 167 | #else |