bugs.c 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * x86 FPU bug checks:
  4. */
  5. #include <linux/printk.h>
  6. #include <asm/cpufeature.h>
  7. #include <asm/fpu/api.h>
  8. /*
  9. * Boot time CPU/FPU FDIV bug detection code:
  10. */
  11. static double __initdata x = 4195835.0;
  12. static double __initdata y = 3145727.0;
  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. */
  24. void __init fpu__init_check_bugs(void)
  25. {
  26. s32 fdiv_bug;
  27. /* kernel_fpu_begin/end() relies on patched alternative instructions. */
  28. if (!boot_cpu_has(X86_FEATURE_FPU))
  29. return;
  30. kernel_fpu_begin();
  31. /*
  32. * trap_init() enabled FXSR and company _before_ testing for FP
  33. * problems here.
  34. *
  35. * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug
  36. */
  37. __asm__("fninit\n\t"
  38. "fldl %1\n\t"
  39. "fdivl %2\n\t"
  40. "fmull %2\n\t"
  41. "fldl %1\n\t"
  42. "fsubp %%st,%%st(1)\n\t"
  43. "fistpl %0\n\t"
  44. "fwait\n\t"
  45. "fninit"
  46. : "=m" (*&fdiv_bug)
  47. : "m" (*&x), "m" (*&y));
  48. kernel_fpu_end();
  49. if (fdiv_bug) {
  50. set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
  51. pr_warn("Hmm, FPU with FDIV bug\n");
  52. }
  53. }