linux/arch/x86/kernel/fpu/bugs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * x86 FPU bug checks:
   4 */
   5#include <asm/fpu/internal.h>
   6
   7/*
   8 * Boot time CPU/FPU FDIV bug detection code:
   9 */
  10
  11static double __initdata x = 4195835.0;
  12static double __initdata y = 3145727.0;
  13
  14/*
  15 * This used to check for exceptions..
  16 * However, it turns out that to support that,
  17 * the XMM trap handlers basically had to
  18 * be buggy. So let's have a correct XMM trap
  19 * handler, and forget about printing out
  20 * some status at boot.
  21 *
  22 * We should really only care about bugs here
  23 * anyway. Not features.
  24 */
  25void __init fpu__init_check_bugs(void)
  26{
  27        s32 fdiv_bug;
  28
  29        /* kernel_fpu_begin/end() relies on patched alternative instructions. */
  30        if (!boot_cpu_has(X86_FEATURE_FPU))
  31                return;
  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        if (fdiv_bug) {
  56                set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
  57                pr_warn("Hmm, FPU with FDIV bug\n");
  58        }
  59}
  60