bugs.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * include/asm-i386/bugs.h
  3. *
  4. * Copyright (C) 1994 Linus Torvalds
  5. *
  6. * Cyrix stuff, June 1998 by:
  7. * - Rafael R. Reilova (moved everything from head.S),
  8. * <rreilova@ececs.uc.edu>
  9. * - Channing Corn (tests & fixes),
  10. * - Andrew D. Balsa (code cleanup).
  11. *
  12. * Pentium III FXSR, SSE support
  13. * Gareth Hughes <gareth@valinux.com>, May 2000
  14. */
  15. /*
  16. * This is included by init/main.c to check for architecture-dependent bugs.
  17. *
  18. * Needs:
  19. * void check_bugs(void);
  20. */
  21. #include <linux/config.h>
  22. #include <linux/init.h>
  23. #include <asm/processor.h>
  24. #include <asm/i387.h>
  25. #include <asm/msr.h>
  26. static int __init no_halt(char *s)
  27. {
  28. boot_cpu_data.hlt_works_ok = 0;
  29. return 1;
  30. }
  31. __setup("no-hlt", no_halt);
  32. static int __init mca_pentium(char *s)
  33. {
  34. mca_pentium_flag = 1;
  35. return 1;
  36. }
  37. __setup("mca-pentium", mca_pentium);
  38. static int __init no_387(char *s)
  39. {
  40. boot_cpu_data.hard_math = 0;
  41. write_cr0(0xE | read_cr0());
  42. return 1;
  43. }
  44. __setup("no387", no_387);
  45. static double __initdata x = 4195835.0;
  46. static double __initdata y = 3145727.0;
  47. /*
  48. * This used to check for exceptions..
  49. * However, it turns out that to support that,
  50. * the XMM trap handlers basically had to
  51. * be buggy. So let's have a correct XMM trap
  52. * handler, and forget about printing out
  53. * some status at boot.
  54. *
  55. * We should really only care about bugs here
  56. * anyway. Not features.
  57. */
  58. static void __init check_fpu(void)
  59. {
  60. if (!boot_cpu_data.hard_math) {
  61. #ifndef CONFIG_MATH_EMULATION
  62. printk(KERN_EMERG "No coprocessor found and no math emulation present.\n");
  63. printk(KERN_EMERG "Giving up.\n");
  64. for (;;) ;
  65. #endif
  66. return;
  67. }
  68. /* Enable FXSR and company _before_ testing for FP problems. */
  69. /*
  70. * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
  71. */
  72. if (offsetof(struct task_struct, thread.i387.fxsave) & 15) {
  73. extern void __buggy_fxsr_alignment(void);
  74. __buggy_fxsr_alignment();
  75. }
  76. if (cpu_has_fxsr) {
  77. printk(KERN_INFO "Enabling fast FPU save and restore... ");
  78. set_in_cr4(X86_CR4_OSFXSR);
  79. printk("done.\n");
  80. }
  81. if (cpu_has_xmm) {
  82. printk(KERN_INFO "Enabling unmasked SIMD FPU exception support... ");
  83. set_in_cr4(X86_CR4_OSXMMEXCPT);
  84. printk("done.\n");
  85. }
  86. /* Test for the divl bug.. */
  87. __asm__("fninit\n\t"
  88. "fldl %1\n\t"
  89. "fdivl %2\n\t"
  90. "fmull %2\n\t"
  91. "fldl %1\n\t"
  92. "fsubp %%st,%%st(1)\n\t"
  93. "fistpl %0\n\t"
  94. "fwait\n\t"
  95. "fninit"
  96. : "=m" (*&boot_cpu_data.fdiv_bug)
  97. : "m" (*&x), "m" (*&y));
  98. if (boot_cpu_data.fdiv_bug)
  99. printk("Hmm, FPU with FDIV bug.\n");
  100. }
  101. static void __init check_hlt(void)
  102. {
  103. printk(KERN_INFO "Checking 'hlt' instruction... ");
  104. if (!boot_cpu_data.hlt_works_ok) {
  105. printk("disabled\n");
  106. return;
  107. }
  108. __asm__ __volatile__("hlt ; hlt ; hlt ; hlt");
  109. printk("OK.\n");
  110. }
  111. /*
  112. * Most 386 processors have a bug where a POPAD can lock the
  113. * machine even from user space.
  114. */
  115. static void __init check_popad(void)
  116. {
  117. #ifndef CONFIG_X86_POPAD_OK
  118. int res, inp = (int) &res;
  119. printk(KERN_INFO "Checking for popad bug... ");
  120. __asm__ __volatile__(
  121. "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
  122. : "=&a" (res)
  123. : "d" (inp)
  124. : "ecx", "edi" );
  125. /* If this fails, it means that any user program may lock the CPU hard. Too bad. */
  126. if (res != 12345678) printk( "Buggy.\n" );
  127. else printk( "OK.\n" );
  128. #endif
  129. }
  130. /*
  131. * Check whether we are able to run this kernel safely on SMP.
  132. *
  133. * - In order to run on a i386, we need to be compiled for i386
  134. * (for due to lack of "invlpg" and working WP on a i386)
  135. * - In order to run on anything without a TSC, we need to be
  136. * compiled for a i486.
  137. * - In order to support the local APIC on a buggy Pentium machine,
  138. * we need to be compiled with CONFIG_X86_GOOD_APIC disabled,
  139. * which happens implicitly if compiled for a Pentium or lower
  140. * (unless an advanced selection of CPU features is used) as an
  141. * otherwise config implies a properly working local APIC without
  142. * the need to do extra reads from the APIC.
  143. */
  144. static void __init check_config(void)
  145. {
  146. /*
  147. * We'd better not be a i386 if we're configured to use some
  148. * i486+ only features! (WP works in supervisor mode and the
  149. * new "invlpg" and "bswap" instructions)
  150. */
  151. #if defined(CONFIG_X86_WP_WORKS_OK) || defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_BSWAP)
  152. if (boot_cpu_data.x86 == 3)
  153. panic("Kernel requires i486+ for 'invlpg' and other features");
  154. #endif
  155. /*
  156. * If we configured ourselves for a TSC, we'd better have one!
  157. */
  158. #ifdef CONFIG_X86_TSC
  159. if (!cpu_has_tsc)
  160. panic("Kernel compiled for Pentium+, requires TSC feature!");
  161. #endif
  162. /*
  163. * If we were told we had a good local APIC, check for buggy Pentia,
  164. * i.e. all B steppings and the C2 stepping of P54C when using their
  165. * integrated APIC (see 11AP erratum in "Pentium Processor
  166. * Specification Update").
  167. */
  168. #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC)
  169. if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
  170. && cpu_has_apic
  171. && boot_cpu_data.x86 == 5
  172. && boot_cpu_data.x86_model == 2
  173. && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
  174. panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!");
  175. #endif
  176. }
  177. extern void alternative_instructions(void);
  178. static void __init check_bugs(void)
  179. {
  180. identify_cpu(&boot_cpu_data);
  181. #ifndef CONFIG_SMP
  182. printk("CPU: ");
  183. print_cpu_info(&boot_cpu_data);
  184. #endif
  185. check_config();
  186. check_fpu();
  187. check_hlt();
  188. check_popad();
  189. system_utsname.machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
  190. alternative_instructions();
  191. }