root/include/asm-i386/bugs.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. no_halt
  2. no_387
  3. copro_timeout
  4. check_fpu
  5. check_hlt
  6. check_tlb
  7. check_bugs

   1 /*
   2  *  include/asm-i386/bugs.h
   3  *
   4  *  Copyright (C) 1994  Linus Torvalds
   5  */
   6 
   7 /*
   8  * This is included by init/main.c to check for architecture-dependent bugs.
   9  *
  10  * Needs:
  11  *      void check_bugs(void);
  12  */
  13 
  14 #include <linux/config.h>
  15 
  16 #define CONFIG_BUGi386
  17 
  18 static void no_halt(char *s, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
  19 {
  20         hlt_works_ok = 0;
  21 }
  22 
  23 static void no_387(char *s, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
  24 {
  25         hard_math = 0;
  26         __asm__("movl %%cr0,%%eax\n\t"
  27                 "orl $0xE,%%eax\n\t"
  28                 "movl %%eax,%%cr0\n\t" : : : "ax");
  29 }
  30 
  31 static char fpu_error = 0;
  32 
  33 static void copro_timeout(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35         fpu_error = 1;
  36         timer_table[COPRO_TIMER].expires = jiffies+100;
  37         timer_active |= 1<<COPRO_TIMER;
  38         printk("387 failed: trying to reset\n");
  39         send_sig(SIGFPE, last_task_used_math, 1);
  40         outb_p(0,0xf1);
  41         outb_p(0,0xf0);
  42 }
  43 
  44 static void check_fpu(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46         static double x = 4195835.0;
  47         static double y = 3145727.0;
  48         unsigned short control_word;
  49 
  50         if (!hard_math) {
  51 #ifndef CONFIG_MATH_EMULATION
  52                 printk("No coprocessor found and no math emulation present.\n");
  53                 printk("Giving up.\n");
  54                 for (;;) ;
  55 #endif
  56                 return;
  57         }
  58         /*
  59          * check if exception 16 works correctly.. This is truly evil
  60          * code: it disables the high 8 interrupts to make sure that
  61          * the irq13 doesn't happen. But as this will lead to a lockup
  62          * if no exception16 arrives, it depends on the fact that the
  63          * high 8 interrupts will be re-enabled by the next timer tick.
  64          * So the irq13 will happen eventually, but the exception 16
  65          * should get there first..
  66          */
  67         printk("Checking 386/387 coupling... ");
  68         timer_table[COPRO_TIMER].expires = jiffies+50;
  69         timer_table[COPRO_TIMER].fn = copro_timeout;
  70         timer_active |= 1<<COPRO_TIMER;
  71         __asm__("clts ; fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
  72         control_word &= 0xffc0;
  73         __asm__("fldcw %0 ; fwait": :"m" (*&control_word));
  74         outb_p(inb_p(0x21) | (1 << 2), 0x21);
  75         __asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait");
  76         timer_active &= ~(1<<COPRO_TIMER);
  77         if (fpu_error)
  78                 return;
  79         if (!ignore_irq13) {
  80                 printk("Ok, fpu using old IRQ13 error reporting\n");
  81                 return;
  82         }
  83         __asm__("fninit\n\t"
  84                 "fldl %1\n\t"
  85                 "fdivl %2\n\t"
  86                 "fmull %2\n\t"
  87                 "fldl %1\n\t"
  88                 "fsubp %%st,%%st(1)\n\t"
  89                 "fistpl %0\n\t"
  90                 "fwait\n\t"
  91                 "fninit"
  92                 : "=m" (*&fdiv_bug)
  93                 : "m" (*&x), "m" (*&y));
  94         if (!fdiv_bug) {
  95                 printk("Ok, fpu using exception 16 error reporting.\n");
  96                 return;
  97 
  98         }
  99         printk("Hmm, FDIV bug i%c86 system\n", '0'+x86);
 100 }
 101 
 102 static void check_hlt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 103 {
 104         printk("Checking 'hlt' instruction... ");
 105         if (!hlt_works_ok) {
 106                 printk("disabled\n");
 107                 return;
 108         }
 109         __asm__ __volatile__("hlt ; hlt ; hlt ; hlt");
 110         printk("Ok.\n");
 111 }
 112 
 113 static void check_tlb(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115 #ifndef CONFIG_M386
 116         /*
 117          * The 386 chips don't support TLB finegrained invalidation.
 118          * They will fault when they hit a invlpg instruction.
 119          */
 120         if (x86 == 3) {
 121                 printk("CPU is a 386 and this kernel was compiled for 486 or better.\n");
 122                 printk("Giving up.\n");
 123                 for (;;) ;
 124         }
 125 #endif
 126 }
 127 
 128 static void check_bugs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130         check_tlb();
 131         check_fpu();
 132         check_hlt();
 133         system_utsname.machine[1] = '0' + x86;
 134 }

/* [previous][next][first][last][top][bottom][index][help] */