bugs.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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. void __init fpu__init_check_bugs(void)
  22. {
  23. u32 cr0_saved;
  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. /* We might have CR0::TS set already, clear it: */
  29. cr0_saved = read_cr0();
  30. write_cr0(cr0_saved & ~X86_CR0_TS);
  31. kernel_fpu_begin();
  32. /*
  33. * trap_init() enabled FXSR and company _before_ testing for FP
  34. * problems here.
  35. *
  36. * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug
  37. */
  38. __asm__("fninit\n\t"
  39. "fldl %1\n\t"
  40. "fdivl %2\n\t"
  41. "fmull %2\n\t"
  42. "fldl %1\n\t"
  43. "fsubp %%st,%%st(1)\n\t"
  44. "fistpl %0\n\t"
  45. "fwait\n\t"
  46. "fninit"
  47. : "=m" (*&fdiv_bug)
  48. : "m" (*&x), "m" (*&y));
  49. kernel_fpu_end();
  50. write_cr0(cr0_saved);
  51. if (fdiv_bug) {
  52. set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
  53. pr_warn("Hmm, FPU with FDIV bug\n");
  54. }
  55. }