linux/arch/x86/kernel/cpu/bugs.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 1994  Linus Torvalds
   3 *
   4 *  Cyrix stuff, June 1998 by:
   5 *      - Rafael R. Reilova (moved everything from head.S),
   6 *        <rreilova@ececs.uc.edu>
   7 *      - Channing Corn (tests & fixes),
   8 *      - Andrew D. Balsa (code cleanup).
   9 */
  10#include <linux/init.h>
  11#include <linux/utsname.h>
  12#include <asm/bugs.h>
  13#include <asm/processor.h>
  14#include <asm/processor-flags.h>
  15#include <asm/i387.h>
  16#include <asm/msr.h>
  17#include <asm/paravirt.h>
  18#include <asm/alternative.h>
  19
  20static double __initdata x = 4195835.0;
  21static double __initdata y = 3145727.0;
  22
  23/*
  24 * This used to check for exceptions..
  25 * However, it turns out that to support that,
  26 * the XMM trap handlers basically had to
  27 * be buggy. So let's have a correct XMM trap
  28 * handler, and forget about printing out
  29 * some status at boot.
  30 *
  31 * We should really only care about bugs here
  32 * anyway. Not features.
  33 */
  34static void __init check_fpu(void)
  35{
  36        s32 fdiv_bug;
  37
  38        kernel_fpu_begin();
  39
  40        /*
  41         * trap_init() enabled FXSR and company _before_ testing for FP
  42         * problems here.
  43         *
  44         * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug
  45         */
  46        __asm__("fninit\n\t"
  47                "fldl %1\n\t"
  48                "fdivl %2\n\t"
  49                "fmull %2\n\t"
  50                "fldl %1\n\t"
  51                "fsubp %%st,%%st(1)\n\t"
  52                "fistpl %0\n\t"
  53                "fwait\n\t"
  54                "fninit"
  55                : "=m" (*&fdiv_bug)
  56                : "m" (*&x), "m" (*&y));
  57
  58        kernel_fpu_end();
  59
  60        if (fdiv_bug) {
  61                set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
  62                pr_warn("Hmm, FPU with FDIV bug\n");
  63        }
  64}
  65
  66void __init check_bugs(void)
  67{
  68        identify_boot_cpu();
  69#ifndef CONFIG_SMP
  70        pr_info("CPU: ");
  71        print_cpu_info(&boot_cpu_data);
  72#endif
  73
  74        /*
  75         * Check whether we are able to run this kernel safely on SMP.
  76         *
  77         * - i386 is no longer supported.
  78         * - In order to run on anything without a TSC, we need to be
  79         *   compiled for a i486.
  80         */
  81        if (boot_cpu_data.x86 < 4)
  82                panic("Kernel requires i486+ for 'invlpg' and other features");
  83
  84        init_utsname()->machine[1] =
  85                '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
  86        alternative_instructions();
  87
  88        /*
  89         * kernel_fpu_begin/end() in check_fpu() relies on the patched
  90         * alternative instructions.
  91         */
  92        if (cpu_has_fpu)
  93                check_fpu();
  94}
  95