1/* 2 * P6 specific Machine Check Exception Reporting 3 * (C) Copyright 2002 Alan Cox <alan@redhat.com> 4 */ 5 6#include <linux/init.h> 7#include <linux/types.h> 8#include <linux/kernel.h> 9#include <linux/interrupt.h> 10#include <linux/smp.h> 11 12#include <asm/processor.h> 13#include <asm/system.h> 14#include <asm/msr.h> 15 16#include "mce.h" 17 18/* Machine Check Handler For PII/PIII */ 19static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) 20{ 21 int recover=1; 22 u32 alow, ahigh, high, low; 23 u32 mcgstl, mcgsth; 24 int i; 25 26 rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth); 27 if (mcgstl & (1<<0)) /* Recoverable ? */ 28 recover=0; 29 30 printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", 31 smp_processor_id(), mcgsth, mcgstl); 32 33 for (i=0; i<nr_mce_banks; i++) { 34 rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high); 35 if (high & (1<<31)) { 36 if (high & (1<<29)) 37 recover |= 1; 38 if (high & (1<<25)) 39 recover |= 2; 40 printk (KERN_EMERG "Bank %d: %08x%08x", i, high, low); 41 high &= ~(1<<31); 42 if (high & (1<<27)) { 43 rdmsr (MSR_IA32_MC0_MISC+i*4, alow, ahigh); 44 printk ("[%08x%08x]", ahigh, alow); 45 } 46 if (high & (1<<26)) { 47 rdmsr (MSR_IA32_MC0_ADDR+i*4, alow, ahigh); 48 printk (" at %08x%08x", ahigh, alow); 49 } 50 printk ("\n"); 51 } 52 } 53 54 if (recover & 2) 55 panic ("CPU context corrupt"); 56 if (recover & 1) 57 panic ("Unable to continue"); 58 59 printk (KERN_EMERG "Attempting to continue.\n"); 60 /* 61 * Do not clear the MSR_IA32_MCi_STATUS if the error is not 62 * recoverable/continuable.This will allow BIOS to look at the MSRs 63 * for errors if the OS could not log the error. 64 */ 65 for (i=0; i<nr_mce_banks; i++) { 66 unsigned int msr; 67 msr = MSR_IA32_MC0_STATUS+i*4; 68 rdmsr (msr,low, high); 69 if (high & (1<<31)) { 70 /* Clear it */ 71 wrmsr (msr, 0UL, 0UL); 72 /* Serialize */ 73 wmb(); 74 add_taint(TAINT_MACHINE_CHECK); 75 } 76 } 77 mcgstl &= ~(1<<2); 78 wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth); 79} 80 81/* Set up machine check reporting for processors with Intel style MCE */ 82void intel_p6_mcheck_init(struct cpuinfo_x86 *c) 83{ 84 u32 l, h; 85 int i; 86 87 /* Check for MCE support */ 88 if (!cpu_has(c, X86_FEATURE_MCE)) 89 return; 90 91 /* Check for PPro style MCA */ 92 if (!cpu_has(c, X86_FEATURE_MCA)) 93 return; 94 95 /* Ok machine check is available */ 96 machine_check_vector = intel_machine_check; 97 wmb(); 98 99 printk (KERN_INFO "Intel machine check architecture supported.\n"); 100 rdmsr (MSR_IA32_MCG_CAP, l, h); 101 if (l & (1<<8)) /* Control register present ? */ 102 wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); 103 nr_mce_banks = l & 0xff; 104 105 /* 106 * Following the example in IA-32 SDM Vol 3: 107 * - MC0_CTL should not be written 108 * - Status registers on all banks should be cleared on reset 109 */ 110 for (i=1; i<nr_mce_banks; i++) 111 wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff); 112 113 for (i=0; i<nr_mce_banks; i++) 114 wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0); 115 116 set_in_cr4 (X86_CR4_MCE); 117 printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", 118 smp_processor_id()); 119} 120