/*
* Machine Check Handler For PII/PIII
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/processor.h>
#include <asm/msr.h>
static int banks;
13 void do_machine_check(struct pt_regs * regs, long error_code)
{
int recover=1;
u32 alow, ahigh, high, low;
u32 mcgstl, mcgsth;
int i;
rdmsr(0x17a, mcgstl, mcgsth);
21 if(mcgstl&(1<<0)) /* Recoverable ? */
recover=0;
printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl);
26 for(i=0;i<banks;i++)
{
rdmsr(0x401+i*4,low, high);
29 if(high&(1<<31))
{
31 if(high&(1<<29))
recover|=1;
33 if(high&(1<<25))
recover|=2;
printk(KERN_EMERG "Bank %d: %08x%08x", i, high, low);
high&=~(1<<31);
37 if(high&(1<<27))
{
rdmsr(0x402+i*4, alow, ahigh);
printk("[%08x%08x]", alow, ahigh);
}
42 if(high&(1<<26))
{
rdmsr(0x402+i*4, alow, ahigh);
printk(" at %08x%08x",
high, low);
}
/* Clear it */
wrmsr(0x401+i*4, 0UL, 0UL);
/* Serialize */
wmb();
}
}
55 if(recover&2)
panic("CPU context corrupt");
57 if(recover&1)
panic("Unable to continue");
printk(KERN_EMERG "Attempting to continue.\n");
mcgstl&=~(1<<2);
wrmsr(0x17a,mcgstl, mcgsth);
}
/*
* This has to be run for each processor
*/
69 void mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
static int done;
75 if( c->x86_vendor != X86_VENDOR_INTEL )
76 return;
78 if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) )
79 return;
81 if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) )
82 return;
/* Ok machine check is available */
86 if(done==0)
printk(KERN_INFO "Intel machine check architecture supported.\n");
rdmsr(0x179, l, h);
89 if(l&(1<<8))
wrmsr(0x17b, 0xffffffff, 0xffffffff);
banks = l&0xff;
92 for(i=1;i<banks;i++)
{
wrmsr(0x400+4*i, 0xffffffff, 0xffffffff);
}
96 for(i=0;i<banks;i++)
{
wrmsr(0x401+4*i, 0x0, 0x0);
}
__asm__ __volatile__ (
"movl %%cr4, %%eax\n\t"
"orl $0x40, %%eax\n\t"
"movl %%eax, %%cr4\n\t" : : : "eax");
printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
done=1;
}