diff options
Diffstat (limited to 'include/asm-i386/bugs.h')
-rw-r--r-- | include/asm-i386/bugs.h | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h index c9ca53c66..ebd9a4f1a 100644 --- a/include/asm-i386/bugs.h +++ b/include/asm-i386/bugs.h @@ -19,6 +19,7 @@ #include <linux/config.h> #include <asm/processor.h> +#include <asm/msr.h> #define CONFIG_BUGi386 @@ -27,6 +28,11 @@ __initfunc(static void no_halt(char *s, int *ints)) boot_cpu_data.hlt_works_ok = 0; } +__initfunc(static void mca_pentium(char *s, int *ints)) +{ + mca_pentium_flag = 1; +} + __initfunc(static void no_387(char *s, int *ints)) { boot_cpu_data.hard_math = 0; @@ -61,6 +67,31 @@ __initfunc(static void check_fpu(void)) #endif return; } + if (mca_pentium_flag) { + /* The IBM Model 95 machines with pentiums lock up on + * fpu test, so we avoid it. All pentiums have inbuilt + * FPU and thus should use exception 16. We still do + * the FDIV test, although I doubt there where ever any + * MCA boxes built with non-FDIV-bug cpus. + */ + __asm__("fninit\n\t" + "fldl %1\n\t" + "fdivl %2\n\t" + "fmull %2\n\t" + "fldl %1\n\t" + "fsubp %%st,%%st(1)\n\t" + "fistpl %0\n\t" + "fwait\n\t" + "fninit" + : "=m" (*&boot_cpu_data.fdiv_bug) + : "m" (*&x), "m" (*&y)); + printk("mca-pentium specified, avoiding FPU coupling test... "); + if (!boot_cpu_data.fdiv_bug) + printk("??? No FDIV bug? Lucky you...\n"); + else + printk("detected FDIV bug though.\n"); + return; + } /* * check if exception 16 works correctly.. This is truly evil * code: it disables the high 8 interrupts to make sure that @@ -173,10 +204,10 @@ __initfunc(static void check_amd_k6(void)) n = K6_BUG_LOOP; f_vide = vide; - __asm__ ("rdtsc" : "=a" (d)); + rdtscl(d); while (n--) f_vide(); - __asm__ ("rdtsc" : "=a" (d2)); + rdtscl(d2); d = d2-d; /* Knock these two lines out if it debugs out ok */ @@ -246,6 +277,7 @@ __initfunc(static void check_cx686_cpuid(void)) ((Cx86_dir0_msb == 5) || (Cx86_dir0_msb == 3))) { int eax, dummy; unsigned char ccr3, ccr4; + __u32 old_cap; cli(); ccr3 = getCx86(CX86_CCR3); @@ -257,8 +289,11 @@ __initfunc(static void check_cx686_cpuid(void)) /* we have up to level 1 available on the Cx6x86(L|MX) */ boot_cpu_data.cpuid_level = 1; + /* Need to preserve some externally computed capabilities */ + old_cap = boot_cpu_data.x86_capability & X86_FEATURE_MTRR; cpuid(1, &eax, &dummy, &dummy, &boot_cpu_data.x86_capability); + boot_cpu_data.x86_capability |= old_cap; boot_cpu_data.x86 = (eax >> 8) & 15; /* @@ -314,6 +349,24 @@ __initfunc(static void check_cyrix_cpu(void)) } /* + * In setup.c's cyrix_model() we have set the boot_cpu_data.coma_bug + * on certain processors that we know contain this bug and now we + * enable the workaround for it. + */ + +__initfunc(static void check_cyrix_coma(void)) +{ + if (boot_cpu_data.coma_bug) { + unsigned char ccr1; + cli(); + ccr1 = getCx86 (CX86_CCR1); + setCx86 (CX86_CCR1, ccr1 | 0x10); + sti(); + printk("Cyrix processor with \"coma bug\" found, workaround enabled\n"); + } +} + +/* * Check wether we are able to run this kernel safely on SMP. * * - In order to run on a i386, we need to be compiled for i386 @@ -371,5 +424,6 @@ __initfunc(static void check_bugs(void)) check_popad(); check_amd_k6(); check_pentium_f00f(); + check_cyrix_coma(); system_utsname.machine[1] = '0' + boot_cpu_data.x86; } |