Import 2.3.18pre1
[davej-history.git] / include / asm-i386 / bugs.h
blob1914385eb940b18630c783b17111d3779c21508d
1 /*
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.
16 * Needs:
17 * void check_bugs(void);
20 #include <linux/config.h>
21 #include <asm/processor.h>
22 #include <asm/msr.h>
24 #define CONFIG_BUGi386
26 static int __init no_halt(char *s)
28 boot_cpu_data.hlt_works_ok = 0;
29 return 1;
32 __setup("no-hlt", no_halt);
34 static int __init mca_pentium(char *s)
36 mca_pentium_flag = 1;
37 return 1;
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());
46 return 1;
49 __setup("no387", no_387);
51 static char __initdata fpu_error = 0;
53 static void __init copro_timeout(void)
55 fpu_error = 1;
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);
60 outb_p(0,0xf1);
61 outb_p(0,0xf0);
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");
75 for (;;) ;
76 #endif
77 return;
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.
86 __asm__("fninit\n\t"
87 "fldl %1\n\t"
88 "fdivl %2\n\t"
89 "fmull %2\n\t"
90 "fldl %1\n\t"
91 "fsubp %%st,%%st(1)\n\t"
92 "fistpl %0\n\t"
93 "fwait\n\t"
94 "fninit"
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");
100 else
101 printk("detected FDIV bug though.\n");
102 return;
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);
123 if (fpu_error)
124 return;
125 if (!ignore_irq13) {
126 printk("OK, FPU using old IRQ 13 error reporting\n");
127 return;
129 __asm__("fninit\n\t"
130 "fldl %1\n\t"
131 "fdivl %2\n\t"
132 "fmull %2\n\t"
133 "fldl %1\n\t"
134 "fsubp %%st,%%st(1)\n\t"
135 "fistpl %0\n\t"
136 "fwait\n\t"
137 "fninit"
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");
142 else
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");
151 return;
153 __asm__ __volatile__("hlt ; hlt ; hlt ; hlt");
154 printk("OK.\n");
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 "
170 : "=&a" (res)
171 : "d" (inp)
172 : "ecx", "edi" );
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" );
176 #endif
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)
201 int n;
202 void (*f_vide)(void);
203 unsigned long d, d2;
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.
214 n = K6_BUG_LOOP;
215 f_vide = vide;
216 rdtscl(d);
217 while (n--)
218 f_vide();
219 rdtscl(d2);
220 d = d2-d;
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 - ");
225 /* -- cut here -- */
226 if (d > 20*K6_BUG_LOOP)
227 printk("system stability may be impaired when more than 32 MB are used.\n");
228 else
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)
261 unsigned int test;
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 */
267 : "=a" (test)
268 : "0" (5), "q" (2)
269 : "cc");
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))) {
287 int eax, dummy;
288 unsigned char ccr3, ccr4;
289 __u32 old_cap;
291 cli();
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 */
297 sti();
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;
328 cli();
329 ccr3 = getCx86(CX86_CCR3);
330 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
331 ccr5 = getCx86(CX86_CCR5);
332 if (ccr5 & 2)
333 setCx86(CX86_CCR5, ccr5 & 0xfd); /* reset SLOP */
334 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
335 sti();
337 if (ccr5 & 2) { /* possible wrong calibration done */
338 printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n");
339 calibrate_delay();
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");
393 #endif
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");
401 #endif
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");
409 #endif
412 static void __init check_bugs(void)
414 check_cyrix_cpu();
415 identify_cpu(&boot_cpu_data);
416 check_cx686_cpuid();
417 check_cx686_slop();
418 #ifndef __SMP__
419 printk("CPU: ");
420 print_cpu_info(&boot_cpu_data);
421 #endif
422 check_config();
423 check_fpu();
424 check_hlt();
425 check_popad();
426 check_amd_k6();
427 check_pentium_f00f();
428 check_cyrix_coma();
429 system_utsname.machine[1] = '0' + boot_cpu_data.x86;