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>
12 static int mce_disabled __initdata = 0;
15 * Machine Check Handler For PII/PIII
20 static void intel_machine_check(struct pt_regs * regs, long error_code)
23 u32 alow, ahigh, high, low;
27 rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
28 if(mcgstl&(1<<0)) /* Recoverable ? */
31 printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl);
35 rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);
42 printk(KERN_EMERG "Bank %d: %08x%08x", i, high, low);
46 rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
47 printk("[%08x%08x]", ahigh, alow);
51 rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
52 printk(" at %08x%08x", ahigh, alow);
56 wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
63 panic("CPU context corrupt");
65 panic("Unable to continue");
66 printk(KERN_EMERG "Attempting to continue.\n");
68 wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
72 * Machine check handler for Pentium class Intel
75 static void pentium_machine_check(struct pt_regs * regs, long error_code)
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);
82 printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
86 * Machine check handler for WinChip C6
89 static void winchip_machine_check(struct pt_regs * regs, long error_code)
91 printk(KERN_EMERG "CPU#%d: Machine Check Exception.\n", smp_processor_id());
95 * Handle unconfigured int18 (should never happen)
98 static void unexpected_machine_check(struct pt_regs * regs, long error_code)
100 printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
104 * Call the installed machine check handler for this CPU setup.
107 static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
109 asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
111 machine_check_vector(regs, error_code);
115 * Set up machine check reporting for Intel processors
118 static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
125 * Check for MCE support
128 if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) )
132 * Pentium machine check
137 /* Default P5 to off as its often misconnected */
138 if(mce_disabled != -1)
140 machine_check_vector = pentium_machine_check;
142 /* Read registers before enabling */
143 rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
144 rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
146 printk(KERN_INFO "Intel old style machine check architecture supported.\n");
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());
155 * Check for PPro style MCA
158 if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) )
161 /* Ok machine check is available */
163 machine_check_vector = intel_machine_check;
167 printk(KERN_INFO "Intel machine check architecture supported.\n");
168 rdmsr(MSR_IA32_MCG_CAP, l, h);
170 wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
174 wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
178 wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
180 set_in_cr4(X86_CR4_MCE);
181 printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
186 * Set up machine check reporting on the Winchip C6 series
189 static void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
192 /* Not supported on C3 */
196 machine_check_vector = winchip_machine_check;
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());
208 * This has to be run for each processor
213 void __init mcheck_init(struct cpuinfo_x86 *c)
218 switch(c->x86_vendor)
222 * AMD K7 machine check is Intel like
224 if(c->x86 == 6 || c->x86 == 15)
225 intel_mcheck_init(c);
227 case X86_VENDOR_INTEL:
228 intel_mcheck_init(c);
230 case X86_VENDOR_CENTAUR:
231 winchip_mcheck_init(c);
238 static int __init mcheck_disable(char *str)
244 static int __init mcheck_enable(char *str)
250 __setup("nomce", mcheck_disable);
251 __setup("mce", mcheck_enable);
254 asmlinkage void do_machine_check(struct pt_regs * regs, long error_code) {}
255 void __init mcheck_init(struct cpuinfo_x86 *c) {}