2 * include/asm-i386/bugs.h
4 * Copyright (C) 1994 Linus Torvalds
6 * Cyrix stuff, June 1998 by:
7 * - Rafael R. Reilova (moved everything from head.S),
8 * <rreilova@ececs.uc.edu>
9 * - Channing Corn (tests & fixes),
10 * - Andrew D. Balsa (code cleanup).
14 * This is included by init/main.c to check for architecture-dependent bugs.
17 * void check_bugs(void);
20 #include <linux/config.h>
21 #include <asm/processor.h>
24 #define CONFIG_BUGi386
26 static int __init
no_halt(char *s
)
28 boot_cpu_data
.hlt_works_ok
= 0;
32 __setup("no-hlt", no_halt
);
34 static int __init
mca_pentium(char *s
)
40 __setup("mca-pentium", mca_pentium
);
42 static int __init
no_387(char *s
)
44 boot_cpu_data
.hard_math
= 0;
45 write_cr0(0xE | read_cr0());
49 __setup("no387", no_387
);
51 static char __initdata fpu_error
= 0;
53 static void __init
copro_timeout(void)
56 timer_table
[COPRO_TIMER
].expires
= jiffies
+HZ
;
57 timer_active
|= 1<<COPRO_TIMER
;
58 printk(KERN_ERR
"387 failed: trying to reset\n");
59 send_sig(SIGFPE
, current
, 1);
64 static double __initdata x
= 4195835.0;
65 static double __initdata y
= 3145727.0;
67 static void __init
check_fpu(void)
69 unsigned short control_word
;
71 if (!boot_cpu_data
.hard_math
) {
72 #ifndef CONFIG_MATH_EMULATION
73 printk(KERN_EMERG
"No coprocessor found and no math emulation present.\n");
74 printk(KERN_EMERG
"Giving up.\n");
79 if (mca_pentium_flag
) {
80 /* The IBM Model 95 machines with pentiums lock up on
81 * fpu test, so we avoid it. All pentiums have inbuilt
82 * FPU and thus should use exception 16. We still do
83 * the FDIV test, although I doubt there where ever any
84 * MCA boxes built with non-FDIV-bug cpus.
91 "fsubp %%st,%%st(1)\n\t"
95 : "=m" (*&boot_cpu_data
.fdiv_bug
)
96 : "m" (*&x
), "m" (*&y
));
97 printk("mca-pentium specified, avoiding FPU coupling test... ");
98 if (!boot_cpu_data
.fdiv_bug
)
99 printk("??? No FDIV bug? Lucky you...\n");
101 printk("detected FDIV bug though.\n");
105 * check if exception 16 works correctly.. This is truly evil
106 * code: it disables the high 8 interrupts to make sure that
107 * the irq13 doesn't happen. But as this will lead to a lockup
108 * if no exception16 arrives, it depends on the fact that the
109 * high 8 interrupts will be re-enabled by the next timer tick.
110 * So the irq13 will happen eventually, but the exception 16
111 * should get there first..
113 printk(KERN_INFO
"Checking 386/387 coupling... ");
114 timer_table
[COPRO_TIMER
].expires
= jiffies
+HZ
/2;
115 timer_table
[COPRO_TIMER
].fn
= copro_timeout
;
116 timer_active
|= 1<<COPRO_TIMER
;
117 __asm__("clts ; fninit ; fnstcw %0 ; fwait":"=m" (*&control_word
));
118 control_word
&= 0xffc0;
119 __asm__("fldcw %0 ; fwait": :"m" (*&control_word
));
120 outb_p(inb_p(0x21) | (1 << 2), 0x21);
121 __asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait");
122 timer_active
&= ~(1<<COPRO_TIMER
);
126 printk("OK, FPU using old IRQ 13 error reporting\n");
134 "fsubp %%st,%%st(1)\n\t"
138 : "=m" (*&boot_cpu_data
.fdiv_bug
)
139 : "m" (*&x
), "m" (*&y
));
140 if (!boot_cpu_data
.fdiv_bug
)
141 printk("OK, FPU using exception 16 error reporting.\n");
143 printk("Hmm, FPU using exception 16 error reporting with FDIV bug.\n");
146 static void __init
check_hlt(void)
148 printk(KERN_INFO
"Checking 'hlt' instruction... ");
149 if (!boot_cpu_data
.hlt_works_ok
) {
150 printk("disabled\n");
153 __asm__
__volatile__("hlt ; hlt ; hlt ; hlt");
158 * Most 386 processors have a bug where a POPAD can lock the
159 * machine even from user space.
162 static void __init
check_popad(void)
164 #ifndef CONFIG_X86_POPAD_OK
165 int res
, inp
= (int) &res
;
167 printk(KERN_INFO
"Checking for popad bug... ");
168 __asm__
__volatile__(
169 "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
173 /* If this fails, it means that any user program may lock the CPU hard. Too bad. */
174 if (res
!= 12345678) printk( "Buggy.\n" );
175 else printk( "OK.\n" );
180 * B step AMD K6 before B 9730xxxx have hardware bugs that can cause
181 * misexecution of code under Linux. Owners of such processors should
182 * contact AMD for precise details and a CPU swap.
184 * See http://www.mygale.com/~poulot/k6bug.html
185 * http://www.amd.com/K6/k6docs/revgd.html
187 * The following test is erm.. interesting. AMD neglected to up
188 * the chip setting when fixing the bug but they also tweaked some
189 * performance at the same time..
192 extern void vide(void);
193 __asm__(".align 4\nvide: ret");
195 static void __init
check_amd_k6(void)
197 if (boot_cpu_data
.x86_vendor
== X86_VENDOR_AMD
&&
198 boot_cpu_data
.x86_model
== 6 &&
199 boot_cpu_data
.x86_mask
== 1)
202 void (*f_vide
)(void);
205 printk(KERN_INFO
"AMD K6 stepping B detected - ");
207 #define K6_BUG_LOOP 1000000
210 * It looks like AMD fixed the 2.6.2 bug and improved indirect
211 * calls at the same time.
222 /* Knock these two lines out if it debugs out ok */
223 printk(KERN_INFO
"K6 BUG %ld %d (Report these if test report is incorrect)\n", d
, 20*K6_BUG_LOOP
);
224 printk(KERN_INFO
"AMD K6 stepping B detected - ");
226 if (d
> 20*K6_BUG_LOOP
)
227 printk("system stability may be impaired when more than 32 MB are used.\n");
229 printk("probably OK (after B9730xxxx).\n");
230 printk(KERN_INFO
"Please see http://www.mygale.com/~poulot/k6bug.html\n");
235 * All current models of Pentium and Pentium with MMX technology CPUs
236 * have the F0 0F bug, which lets nonpriviledged users lock up the system:
239 extern void trap_init_f00f_bug(void);
241 static void __init
check_pentium_f00f(void)
244 * Pentium and Pentium MMX
246 boot_cpu_data
.f00f_bug
= 0;
247 if (boot_cpu_data
.x86
== 5 && boot_cpu_data
.x86_vendor
== X86_VENDOR_INTEL
) {
248 printk(KERN_INFO
"Intel Pentium with F0 0F bug - workaround enabled.\n");
249 boot_cpu_data
.f00f_bug
= 1;
250 trap_init_f00f_bug();
255 * Perform the Cyrix 5/2 test. A Cyrix won't change
256 * the flags, while other 486 chips will.
259 static inline int test_cyrix_52div(void)
263 __asm__
__volatile__(
264 "sahf\n\t" /* clear flags (%eax = 0x0005) */
265 "div %b2\n\t" /* divide 5 by 2 */
266 "lahf" /* store flags into %ah */
271 /* AH is 0x02 on Cyrix after the divide.. */
272 return (unsigned char) (test
>> 8) == 0x02;
276 * Fix cpuid problems with Cyrix CPU's:
277 * -- on the Cx686(L) the cpuid is disabled on power up.
278 * -- braindamaged BIOS disable cpuid on the Cx686MX.
281 extern unsigned char Cx86_dir0_msb
; /* exported HACK from cyrix_model() */
283 static void __init
check_cx686_cpuid(void)
285 if (boot_cpu_data
.cpuid_level
== -1 &&
286 ((Cx86_dir0_msb
== 5) || (Cx86_dir0_msb
== 3))) {
288 unsigned char ccr3
, ccr4
;
292 ccr3
= getCx86(CX86_CCR3
);
293 setCx86(CX86_CCR3
, (ccr3
& 0x0f) | 0x10); /* enable MAPEN */
294 ccr4
= getCx86(CX86_CCR4
);
295 setCx86(CX86_CCR4
, ccr4
| 0x80); /* enable cpuid */
296 setCx86(CX86_CCR3
, ccr3
); /* disable MAPEN */
299 /* we have up to level 1 available on the Cx6x86(L|MX) */
300 boot_cpu_data
.cpuid_level
= 1;
301 /* Need to preserve some externally computed capabilities */
302 old_cap
= boot_cpu_data
.x86_capability
& X86_FEATURE_MTRR
;
303 cpuid(1, &eax
, &dummy
, &dummy
,
304 &boot_cpu_data
.x86_capability
);
305 boot_cpu_data
.x86_capability
|= old_cap
;
307 boot_cpu_data
.x86
= (eax
>> 8) & 15;
309 * we already have a cooked step/rev number from DIR1
310 * so we don't use the cpuid-provided ones.
316 * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old
317 * BIOSes for compatability with DOS games. This makes the udelay loop
318 * work correctly, and improves performance.
321 extern void calibrate_delay(void) __init
;
323 static void __init
check_cx686_slop(void)
325 if (Cx86_dir0_msb
== 3) {
326 unsigned char ccr3
, ccr5
;
329 ccr3
= getCx86(CX86_CCR3
);
330 setCx86(CX86_CCR3
, (ccr3
& 0x0f) | 0x10); /* enable MAPEN */
331 ccr5
= getCx86(CX86_CCR5
);
333 setCx86(CX86_CCR5
, ccr5
& 0xfd); /* reset SLOP */
334 setCx86(CX86_CCR3
, ccr3
); /* disable MAPEN */
337 if (ccr5
& 2) { /* possible wrong calibration done */
338 printk(KERN_INFO
"Recalibrating delay loop with SLOP bit reset\n");
340 boot_cpu_data
.loops_per_sec
= loops_per_sec
;
346 * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
347 * by the fact that they preserve the flags across the division of 5/2.
348 * PII and PPro exhibit this behavior too, but they have cpuid available.
351 static void __init
check_cyrix_cpu(void)
353 if ((boot_cpu_data
.cpuid_level
== -1) && (boot_cpu_data
.x86
== 4)
354 && test_cyrix_52div()) {
356 strcpy(boot_cpu_data
.x86_vendor_id
, "CyrixInstead");
361 * In setup.c's cyrix_model() we have set the boot_cpu_data.coma_bug
362 * on certain processors that we know contain this bug and now we
363 * enable the workaround for it.
366 static void __init
check_cyrix_coma(void)
371 * Check wether we are able to run this kernel safely on SMP.
373 * - In order to run on a i386, we need to be compiled for i386
374 * (for due to lack of "invlpg" and working WP on a i386)
375 * - In order to run on anything without a TSC, we need to be
376 * compiled for a i486.
377 * - In order to work on a Pentium/SMP machine, we need to be
378 * compiled for a Pentium or lower, as a PPro config implies
379 * a properly working local APIC without the need to do extra
380 * reads from the APIC.
383 static void __init
check_config(void)
386 * We'd better not be a i386 if we're configured to use some
387 * i486+ only features! (WP works in supervisor mode and the
388 * new "invlpg" and "bswap" instructions)
390 #if defined(CONFIG_X86_WP_WORKS_OK) || defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_BSWAP)
391 if (boot_cpu_data
.x86
== 3)
392 panic("Kernel requires i486+ for 'invlpg' and other features");
396 * If we configured ourselves for a TSC, we'd better have one!
398 #ifdef CONFIG_X86_TSC
399 if (!(boot_cpu_data
.x86_capability
& X86_FEATURE_TSC
))
400 panic("Kernel compiled for Pentium+, requires TSC");
404 * If we were told we had a good APIC for SMP, we'd better be a PPro
406 #if defined(CONFIG_X86_GOOD_APIC) && defined(CONFIG_SMP)
407 if (smp_found_config
&& boot_cpu_data
.x86
<= 5)
408 panic("Kernel compiled for PPro+, assumes local APIC without read-before-write bug");
412 static void __init
check_bugs(void)
415 identify_cpu(&boot_cpu_data
);
420 print_cpu_info(&boot_cpu_data
);
427 check_pentium_f00f();
429 system_utsname
.machine
[1] = '0' + boot_cpu_data
.x86
;