diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-09-09 19:40:38 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-10 02:21:06 -0400 |
commit | 4052704d92c3172ebc13cc0cc8df8ba2bd446a5c (patch) | |
tree | 79747c641eda4de67e1b37b06a0cf45aa6fb812e /arch | |
parent | 879d792b66d633bbe466974f61d1acc9aa8c78eb (diff) |
x86: intel.c put workaround for old cpus together
consolidate the code some more.
No change in functionality intended.
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 192 |
1 files changed, 98 insertions, 94 deletions
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 365a008080c2..5f76bf139fda 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -63,15 +63,54 @@ int __cpuinit ppro_with_ram_bug(void) | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | #ifdef CONFIG_X86_F00F_BUG | ||
67 | static void __cpuinit trap_init_f00f_bug(void) | ||
68 | { | ||
69 | __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); | ||
66 | 70 | ||
67 | /* | 71 | /* |
68 | * P4 Xeon errata 037 workaround. | 72 | * Update the IDT descriptor and reload the IDT so that |
69 | * Hardware prefetcher may cause stale data to be loaded into the cache. | 73 | * it uses the read-only mapped virtual address. |
70 | */ | 74 | */ |
71 | static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) | 75 | idt_descr.address = fix_to_virt(FIX_F00F_IDT); |
76 | load_idt(&idt_descr); | ||
77 | } | ||
78 | #endif | ||
79 | |||
80 | static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) | ||
72 | { | 81 | { |
73 | unsigned long lo, hi; | 82 | unsigned long lo, hi; |
74 | 83 | ||
84 | #ifdef CONFIG_X86_F00F_BUG | ||
85 | /* | ||
86 | * All current models of Pentium and Pentium with MMX technology CPUs | ||
87 | * have the F0 0F bug, which lets nonprivileged users lock up the system. | ||
88 | * Note that the workaround only should be initialized once... | ||
89 | */ | ||
90 | c->f00f_bug = 0; | ||
91 | if (!paravirt_enabled() && c->x86 == 5) { | ||
92 | static int f00f_workaround_enabled; | ||
93 | |||
94 | c->f00f_bug = 1; | ||
95 | if (!f00f_workaround_enabled) { | ||
96 | trap_init_f00f_bug(); | ||
97 | printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); | ||
98 | f00f_workaround_enabled = 1; | ||
99 | } | ||
100 | } | ||
101 | #endif | ||
102 | |||
103 | /* | ||
104 | * SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until | ||
105 | * model 3 mask 3 | ||
106 | */ | ||
107 | if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) | ||
108 | clear_cpu_cap(c, X86_FEATURE_SEP); | ||
109 | |||
110 | /* | ||
111 | * P4 Xeon errata 037 workaround. | ||
112 | * Hardware prefetcher may cause stale data to be loaded into the cache. | ||
113 | */ | ||
75 | if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) { | 114 | if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) { |
76 | rdmsr(MSR_IA32_MISC_ENABLE, lo, hi); | 115 | rdmsr(MSR_IA32_MISC_ENABLE, lo, hi); |
77 | if ((lo & (1<<9)) == 0) { | 116 | if ((lo & (1<<9)) == 0) { |
@@ -81,23 +120,44 @@ static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) | |||
81 | wrmsr (MSR_IA32_MISC_ENABLE, lo, hi); | 120 | wrmsr (MSR_IA32_MISC_ENABLE, lo, hi); |
82 | } | 121 | } |
83 | } | 122 | } |
84 | } | ||
85 | |||
86 | 123 | ||
124 | /* | ||
125 | * See if we have a good local APIC by checking for buggy Pentia, | ||
126 | * i.e. all B steppings and the C2 stepping of P54C when using their | ||
127 | * integrated APIC (see 11AP erratum in "Pentium Processor | ||
128 | * Specification Update"). | ||
129 | */ | ||
130 | if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 && | ||
131 | (c->x86_mask < 0x6 || c->x86_mask == 0xb)) | ||
132 | set_cpu_cap(c, X86_FEATURE_11AP); | ||
87 | 133 | ||
88 | #ifdef CONFIG_X86_F00F_BUG | ||
89 | static void __cpuinit trap_init_f00f_bug(void) | ||
90 | { | ||
91 | __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); | ||
92 | 134 | ||
135 | #ifdef CONFIG_X86_INTEL_USERCOPY | ||
93 | /* | 136 | /* |
94 | * Update the IDT descriptor and reload the IDT so that | 137 | * Set up the preferred alignment for movsl bulk memory moves |
95 | * it uses the read-only mapped virtual address. | ||
96 | */ | 138 | */ |
97 | idt_descr.address = fix_to_virt(FIX_F00F_IDT); | 139 | switch (c->x86) { |
98 | load_idt(&idt_descr); | 140 | case 4: /* 486: untested */ |
99 | } | 141 | break; |
142 | case 5: /* Old Pentia: untested */ | ||
143 | break; | ||
144 | case 6: /* PII/PIII only like movsl with 8-byte alignment */ | ||
145 | movsl_mask.mask = 7; | ||
146 | break; | ||
147 | case 15: /* P4 is OK down to 8-byte alignment */ | ||
148 | movsl_mask.mask = 7; | ||
149 | break; | ||
150 | } | ||
100 | #endif | 151 | #endif |
152 | |||
153 | #ifdef CONFIG_X86_NUMAQ | ||
154 | numaq_tsc_disable(); | ||
155 | #endif | ||
156 | } | ||
157 | #else | ||
158 | static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) | ||
159 | { | ||
160 | } | ||
101 | #endif | 161 | #endif |
102 | 162 | ||
103 | static void __cpuinit srat_detect_node(void) | 163 | static void __cpuinit srat_detect_node(void) |
@@ -139,28 +199,10 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) | |||
139 | static void __cpuinit init_intel(struct cpuinfo_x86 *c) | 199 | static void __cpuinit init_intel(struct cpuinfo_x86 *c) |
140 | { | 200 | { |
141 | unsigned int l2 = 0; | 201 | unsigned int l2 = 0; |
142 | char *p = NULL; | ||
143 | 202 | ||
144 | early_init_intel(c); | 203 | early_init_intel(c); |
145 | 204 | ||
146 | #ifdef CONFIG_X86_F00F_BUG | 205 | intel_workarounds(c); |
147 | /* | ||
148 | * All current models of Pentium and Pentium with MMX technology CPUs | ||
149 | * have the F0 0F bug, which lets nonprivileged users lock up the system. | ||
150 | * Note that the workaround only should be initialized once... | ||
151 | */ | ||
152 | c->f00f_bug = 0; | ||
153 | if (!paravirt_enabled() && c->x86 == 5) { | ||
154 | static int f00f_workaround_enabled; | ||
155 | |||
156 | c->f00f_bug = 1; | ||
157 | if (!f00f_workaround_enabled) { | ||
158 | trap_init_f00f_bug(); | ||
159 | printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); | ||
160 | f00f_workaround_enabled = 1; | ||
161 | } | ||
162 | } | ||
163 | #endif | ||
164 | 206 | ||
165 | l2 = init_intel_cacheinfo(c); | 207 | l2 = init_intel_cacheinfo(c); |
166 | if (c->cpuid_level > 9) { | 208 | if (c->cpuid_level > 9) { |
@@ -170,17 +212,32 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
170 | set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); | 212 | set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); |
171 | } | 213 | } |
172 | 214 | ||
173 | #ifdef CONFIG_X86_32 | 215 | if (cpu_has_xmm2) |
174 | /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */ | 216 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); |
175 | if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) | 217 | if (cpu_has_ds) { |
176 | clear_cpu_cap(c, X86_FEATURE_SEP); | 218 | unsigned int l1; |
219 | rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); | ||
220 | if (!(l1 & (1<<11))) | ||
221 | set_cpu_cap(c, X86_FEATURE_BTS); | ||
222 | if (!(l1 & (1<<12))) | ||
223 | set_cpu_cap(c, X86_FEATURE_PEBS); | ||
224 | ds_init_intel(c); | ||
225 | } | ||
177 | 226 | ||
227 | #ifdef CONFIG_X86_64 | ||
228 | if (c->x86 == 15) | ||
229 | c->x86_cache_alignment = c->x86_clflush_size * 2; | ||
230 | if (c->x86 == 6) | ||
231 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); | ||
232 | #else | ||
178 | /* | 233 | /* |
179 | * Names for the Pentium II/Celeron processors | 234 | * Names for the Pentium II/Celeron processors |
180 | * detectable only by also checking the cache size. | 235 | * detectable only by also checking the cache size. |
181 | * Dixon is NOT a Celeron. | 236 | * Dixon is NOT a Celeron. |
182 | */ | 237 | */ |
183 | if (c->x86 == 6) { | 238 | if (c->x86 == 6) { |
239 | char *p = NULL; | ||
240 | |||
184 | switch (c->x86_model) { | 241 | switch (c->x86_model) { |
185 | case 5: | 242 | case 5: |
186 | if (c->x86_mask == 0) { | 243 | if (c->x86_mask == 0) { |
@@ -203,51 +260,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
203 | p = "Celeron (Coppermine)"; | 260 | p = "Celeron (Coppermine)"; |
204 | break; | 261 | break; |
205 | } | 262 | } |
206 | } | ||
207 | 263 | ||
208 | if (p) | 264 | if (p) |
209 | strcpy(c->x86_model_id, p); | 265 | strcpy(c->x86_model_id, p); |
210 | |||
211 | Intel_errata_workarounds(c); | ||
212 | |||
213 | #ifdef CONFIG_X86_INTEL_USERCOPY | ||
214 | /* | ||
215 | * Set up the preferred alignment for movsl bulk memory moves | ||
216 | */ | ||
217 | switch (c->x86) { | ||
218 | case 4: /* 486: untested */ | ||
219 | break; | ||
220 | case 5: /* Old Pentia: untested */ | ||
221 | break; | ||
222 | case 6: /* PII/PIII only like movsl with 8-byte alignment */ | ||
223 | movsl_mask.mask = 7; | ||
224 | break; | ||
225 | case 15: /* P4 is OK down to 8-byte alignment */ | ||
226 | movsl_mask.mask = 7; | ||
227 | break; | ||
228 | } | 266 | } |
229 | #endif | ||
230 | |||
231 | #endif | ||
232 | 267 | ||
233 | if (cpu_has_xmm2) | ||
234 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | ||
235 | if (cpu_has_ds) { | ||
236 | unsigned int l1; | ||
237 | rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); | ||
238 | if (!(l1 & (1<<11))) | ||
239 | set_cpu_cap(c, X86_FEATURE_BTS); | ||
240 | if (!(l1 & (1<<12))) | ||
241 | set_cpu_cap(c, X86_FEATURE_PEBS); | ||
242 | ds_init_intel(c); | ||
243 | } | ||
244 | |||
245 | #ifdef CONFIG_X86_64 | ||
246 | if (c->x86 == 15) | ||
247 | c->x86_cache_alignment = c->x86_clflush_size * 2; | ||
248 | if (c->x86 == 6) | ||
249 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); | ||
250 | #else | ||
251 | if (c->x86 == 15) | 268 | if (c->x86 == 15) |
252 | set_cpu_cap(c, X86_FEATURE_P4); | 269 | set_cpu_cap(c, X86_FEATURE_P4); |
253 | if (c->x86 == 6) | 270 | if (c->x86 == 6) |
@@ -256,19 +273,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
256 | if (cpu_has_bts) | 273 | if (cpu_has_bts) |
257 | ptrace_bts_init_intel(c); | 274 | ptrace_bts_init_intel(c); |
258 | 275 | ||
259 | /* | ||
260 | * See if we have a good local APIC by checking for buggy Pentia, | ||
261 | * i.e. all B steppings and the C2 stepping of P54C when using their | ||
262 | * integrated APIC (see 11AP erratum in "Pentium Processor | ||
263 | * Specification Update"). | ||
264 | */ | ||
265 | if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 && | ||
266 | (c->x86_mask < 0x6 || c->x86_mask == 0xb)) | ||
267 | set_cpu_cap(c, X86_FEATURE_11AP); | ||
268 | |||
269 | #ifdef CONFIG_X86_NUMAQ | ||
270 | numaq_tsc_disable(); | ||
271 | #endif | ||
272 | #endif | 276 | #endif |
273 | 277 | ||
274 | detect_extended_topology(c); | 278 | detect_extended_topology(c); |