1/* 2 * Athlon/Hammer specific Machine Check Exception Reporting 3 * (C) Copyright 2002 Dave Jones <davej@codemonkey.org.uk> 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 AMD Athlon/Duron */ 19static fastcall void k7_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=1; 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 /* Clear it */ 52 wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL); 53 /* Serialize */ 54 wmb(); 55 add_taint(TAINT_MACHINE_CHECK); 56 } 57 } 58 59 if (recover&2) 60 panic ("CPU context corrupt"); 61 if (recover&1) 62 panic ("Unable to continue"); 63 printk (KERN_EMERG "Attempting to continue.\n"); 64 mcgstl &= ~(1<<2); 65 wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth); 66} 67 68 69/* AMD K7 machine check is Intel like */ 70void amd_mcheck_init(struct cpuinfo_x86 *c) 71{ 72 u32 l, h; 73 int i; 74 75 if (!cpu_has(c, X86_FEATURE_MCE)) 76 return; 77 78 machine_check_vector = k7_machine_check; 79 wmb(); 80 81 printk (KERN_INFO "Intel machine check architecture supported.\n"); 82 rdmsr (MSR_IA32_MCG_CAP, l, h); 83 if (l & (1<<8)) /* Control register present ? */ 84 wrmsr (MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); 85 nr_mce_banks = l & 0xff; 86 87 /* Clear status for MC index 0 separately, we don't touch CTL, 88 * as some K7 Athlons cause spurious MCEs when its enabled. */ 89 if (boot_cpu_data.x86 == 6) { 90 wrmsr (MSR_IA32_MC0_STATUS, 0x0, 0x0); 91 i = 1; 92 } else 93 i = 0; 94 for (; i<nr_mce_banks; i++) { 95 wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff); 96 wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0); 97 } 98 99 set_in_cr4 (X86_CR4_MCE); 100 printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", 101 smp_processor_id()); 102} 103