bugs.c 1.2 KB

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