home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-i386 / bugs.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  4.8 KB  |  195 lines

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