linux-old/arch/i386/kernel/bluesmoke.c
<<
>>
Prefs
   1
   2#include <linux/init.h>
   3#include <linux/types.h>
   4#include <linux/kernel.h>
   5#include <linux/sched.h>
   6#include <linux/config.h>
   7#include <asm/processor.h> 
   8#include <asm/msr.h>
   9
  10#ifdef CONFIG_X86_MCE
  11
  12static int mce_disabled __initdata = 0;
  13
  14/*
  15 *      Machine Check Handler For PII/PIII
  16 */
  17
  18static int banks;
  19
  20static void intel_machine_check(struct pt_regs * regs, long error_code)
  21{
  22        int recover=1;
  23        u32 alow, ahigh, high, low;
  24        u32 mcgstl, mcgsth;
  25        int i;
  26        
  27        rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
  28        if(mcgstl&(1<<0))       /* Recoverable ? */
  29                recover=0;
  30
  31        printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl);
  32        
  33        for(i=0;i<banks;i++)
  34        {
  35                rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);
  36                if(high&(1<<31))
  37                {
  38                        if(high&(1<<29))
  39                                recover|=1;
  40                        if(high&(1<<25))
  41                                recover|=2;
  42                        printk(KERN_EMERG "Bank %d: %08x%08x", i, high, low);
  43                        high&=~(1<<31);
  44                        if(high&(1<<27))
  45                        {
  46                                rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
  47                                printk("[%08x%08x]", ahigh, alow);
  48                        }
  49                        if(high&(1<<26))
  50                        {
  51                                rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
  52                                printk(" at %08x%08x", ahigh, alow);
  53                        }
  54                        printk("\n");
  55                        /* Clear it */
  56                        wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
  57                        /* Serialize */
  58                        wmb();
  59                }
  60        }
  61        
  62        if(recover&2)
  63                panic("CPU context corrupt");
  64        if(recover&1)
  65                panic("Unable to continue");
  66        printk(KERN_EMERG "Attempting to continue.\n");
  67        mcgstl&=~(1<<2);
  68        wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
  69}
  70
  71/*
  72 *      Machine check handler for Pentium class Intel
  73 */
  74 
  75static void pentium_machine_check(struct pt_regs * regs, long error_code)
  76{
  77        u32 loaddr, hi, lotype;
  78        rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
  79        rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
  80        printk(KERN_EMERG "CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
  81        if(lotype&(1<<5))
  82                printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
  83}
  84
  85/*
  86 *      Machine check handler for WinChip C6
  87 */
  88 
  89static void winchip_machine_check(struct pt_regs * regs, long error_code)
  90{
  91        printk(KERN_EMERG "CPU#%d: Machine Check Exception.\n", smp_processor_id());
  92}
  93
  94/*
  95 *      Handle unconfigured int18 (should never happen)
  96 */
  97
  98static void unexpected_machine_check(struct pt_regs * regs, long error_code)
  99{       
 100        printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
 101}
 102
 103/*
 104 *      Call the installed machine check handler for this CPU setup.
 105 */
 106
 107static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
 108
 109asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
 110{
 111        machine_check_vector(regs, error_code);
 112}
 113
 114/*
 115 *      Set up machine check reporting for Intel processors
 116 */
 117
 118static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
 119{
 120        u32 l, h;
 121        int i;
 122        static int done;
 123        
 124        /*
 125         *      Check for MCE support
 126         */
 127
 128        if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) )
 129                return; 
 130        
 131        /*
 132         *      Pentium machine check
 133         */
 134        
 135        if(c->x86 == 5)
 136        {
 137                /* Default P5 to off as its often misconnected */
 138                if(mce_disabled != -1)
 139                        return;
 140                machine_check_vector = pentium_machine_check;
 141                wmb();
 142                /* Read registers before enabling */
 143                rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
 144                rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
 145                if(done==0)
 146                        printk(KERN_INFO "Intel old style machine check architecture supported.\n");
 147                /* Enable MCE */
 148                set_in_cr4(X86_CR4_MCE);
 149                printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
 150                return;
 151        }
 152        
 153
 154        /*
 155         *      Check for PPro style MCA
 156         */
 157                        
 158        if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) )
 159                return;
 160                
 161        /* Ok machine check is available */
 162        
 163        machine_check_vector = intel_machine_check;
 164        wmb();
 165        
 166        if(done==0)
 167                printk(KERN_INFO "Intel machine check architecture supported.\n");
 168        rdmsr(MSR_IA32_MCG_CAP, l, h);
 169        if(l&(1<<8))
 170                wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 171        banks = l&0xff;
 172        for(i=1;i<banks;i++)
 173        {
 174                wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
 175        }
 176        for(i=0;i<banks;i++)
 177        {
 178                wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
 179        }
 180        set_in_cr4(X86_CR4_MCE);
 181        printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
 182        done=1;
 183}
 184
 185/*
 186 *      Set up machine check reporting on the Winchip C6 series
 187 */
 188 
 189static void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
 190{
 191        u32 lo, hi;
 192        /* Not supported on C3 */
 193        if(c->x86 != 5)
 194                return;
 195        /* Winchip C6 */
 196        machine_check_vector = winchip_machine_check;
 197        wmb();
 198        rdmsr(MSR_IDT_FCR1, lo, hi);
 199        lo|= (1<<2);    /* Enable EIERRINT (int 18 MCE) */
 200        lo&= ~(1<<4);   /* Enable MCE */
 201        wrmsr(MSR_IDT_FCR1, lo, hi);
 202        set_in_cr4(X86_CR4_MCE);
 203        printk(KERN_INFO "Winchip machine check reporting enabled on CPU#%d.\n", smp_processor_id());
 204}
 205
 206
 207/*
 208 *      This has to be run for each processor
 209 */
 210
 211
 212
 213void __init mcheck_init(struct cpuinfo_x86 *c)
 214{
 215        if(mce_disabled==1)
 216                return;
 217                
 218        switch(c->x86_vendor)
 219        {
 220                case X86_VENDOR_AMD:
 221                        /*
 222                         *      AMD K7 machine check is Intel like
 223                         */
 224                        if(c->x86 == 6 || c->x86 == 15)
 225                                intel_mcheck_init(c);
 226                        break;
 227                case X86_VENDOR_INTEL:
 228                        intel_mcheck_init(c);
 229                        break;
 230                case X86_VENDOR_CENTAUR:
 231                        winchip_mcheck_init(c);
 232                        break;
 233                default:
 234                        break;
 235        }
 236}
 237
 238static int __init mcheck_disable(char *str)
 239{
 240        mce_disabled = 1;
 241        return 0;
 242}
 243
 244static int __init mcheck_enable(char *str)
 245{
 246        mce_disabled = -1;
 247        return 0;
 248}
 249
 250__setup("nomce", mcheck_disable);
 251__setup("mce", mcheck_enable);
 252
 253#else
 254asmlinkage void do_machine_check(struct pt_regs * regs, long error_code) {}
 255void __init mcheck_init(struct cpuinfo_x86 *c) {}
 256#endif
 257
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.