/* * 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; }