linux/arch/x86/kernel/fpu/bugs.c
<<
>>
Prefs
   1/*
   2 * x86 FPU bug checks:
   3 */
   4#include <asm/fpu/internal.h>
   5
   6/*
   7 * Boot time CPU/FPU FDIV bug detection code:
   8 */
   9
  10static double __initdata x = 4195835.0;
  11static double __initdata y = 3145727.0;
  12
  13/*
  14 * This used to check for exceptions..
  15 * However, it turns out that to support that,
  16 * the XMM trap handlers basically had to
  17 * be buggy. So let's have a correct XMM trap
  18 * handler, and forget about printing out
  19 * some status at boot.
  20 *
  21 * We should really only care about bugs here
  22 * anyway. Not features.
  23 */
  24static void __init check_fpu(void)
  25{
  26        u32 cr0_saved;
  27        s32 fdiv_bug;
  28
  29        /* We might have CR0::TS set already, clear it: */
  30        cr0_saved = read_cr0();
  31        write_cr0(cr0_saved & ~X86_CR0_TS);
  32
  33        kernel_fpu_begin();
  34
  35        /*
  36         * trap_init() enabled FXSR and company _before_ testing for FP
  37         * problems here.
  38         *
  39         * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug
  40         */
  41        __asm__("fninit\n\t"
  42                "fldl %1\n\t"
  43                "fdivl %2\n\t"
  44                "fmull %2\n\t"
  45                "fldl %1\n\t"
  46                "fsubp %%st,%%st(1)\n\t"
  47                "fistpl %0\n\t"
  48                "fwait\n\t"
  49                "fninit"
  50                : "=m" (*&fdiv_bug)
  51                : "m" (*&x), "m" (*&y));
  52
  53        kernel_fpu_end();
  54
  55        write_cr0(cr0_saved);
  56
  57        if (fdiv_bug) {
  58                set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
  59                pr_warn("Hmm, FPU with FDIV bug\n");
  60        }
  61}
  62
  63void __init fpu__init_check_bugs(void)
  64{
  65        /*
  66         * kernel_fpu_begin/end() in check_fpu() relies on the patched
  67         * alternative instructions.
  68         */
  69        if (cpu_has_fpu)
  70                check_fpu();
  71}
  72