bugs.c 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * x86 FPU bug checks:
  4. */
  5. #include <asm/fpu/api.h>
  6. /*
  7. * Boot time CPU/FPU FDIV bug detection code:
  8. */
  9. static double __initdata x = 4195835.0;
  10. static double __initdata y = 3145727.0;
  11. /*
  12. * This used to check for exceptions..
  13. * However, it turns out that to support that,
  14. * the XMM trap handlers basically had to
  15. * be buggy. So let's have a correct XMM trap
  16. * handler, and forget about printing out
  17. * some status at boot.
  18. *
  19. * We should really only care about bugs here
  20. * anyway. Not features.
  21. */
  22. void __init fpu__init_check_bugs(void)
  23. {
  24. s32 fdiv_bug;
  25. /* kernel_fpu_begin/end() relies on patched alternative instructions. */
  26. if (!boot_cpu_has(X86_FEATURE_FPU))
  27. return;
  28. kernel_fpu_begin();
  29. /*
  30. * trap_init() enabled FXSR and company _before_ testing for FP
  31. * problems here.
  32. *
  33. * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug
  34. */
  35. __asm__("fninit\n\t"
  36. "fldl %1\n\t"
  37. "fdivl %2\n\t"
  38. "fmull %2\n\t"
  39. "fldl %1\n\t"
  40. "fsubp %%st,%%st(1)\n\t"
  41. "fistpl %0\n\t"
  42. "fwait\n\t"
  43. "fninit"
  44. : "=m" (*&fdiv_bug)
  45. : "m" (*&x), "m" (*&y));
  46. kernel_fpu_end();
  47. if (fdiv_bug) {
  48. set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
  49. pr_warn("Hmm, FPU with FDIV bug\n");
  50. }
  51. }