bluesmoke.c

来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 654 行 · 第 1/2 页

C
654
字号
/*  * Machine check handler. * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs. * Additional K8 decoding and simplification Copyright 2003 Eric Morton, Newisys Inc * Rest from unknown author(s). */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/ctype.h>#include <linux/pci.h>#include <linux/timer.h>#include <linux/notifier.h>#include <asm/bluesmoke.h>#include <asm/processor.h> #include <asm/msr.h>#include <asm/kdebug.h>#include <asm/smp.h>static int mce_disabled __initdata;static unsigned long mce_cpus; /* *	Machine Check Handler For PII/PIII/K7 */static int banks;static unsigned long ignored_banks, disabled_banks;struct notifier_block *mc_notifier_list = NULL;EXPORT_SYMBOL(mc_notifier_list);static void generic_machine_check(struct pt_regs * regs, long error_code){	int recover=1;	u32 alow, ahigh, high, low;	u32 mcgstl, mcgsth;	int i;	struct notifier_mc_err mc_err;	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);	if(mcgstl&(1<<0))	/* Recoverable ? */		recover=0;	/* Make sure unrecoverable MCEs reach the console */	if(recover & 3)		oops_in_progress++;	printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", 				smp_processor_id(), mcgsth, mcgstl);		if (regs && (mcgstl & 2))		printk(KERN_EMERG "RIP <%02lx>:%016lx RSP %016lx\n", 		       regs->cs, regs->rip, regs->rsp); 	for(i=0;i<banks;i++)	{		if ((1UL<<i) & ignored_banks) 			continue; 		rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);		if(high&(1<<31))		{			memset(&mc_err, 0x00, sizeof(mc_err));			mc_err.cpunum = safe_smp_processor_id();			mc_err.banknum = i;			mc_err.mci_status = ((u64)high << 32) | low;			if(high&(1<<29))				recover|=1;			if(high&(1<<25))				recover|=2;			printk(KERN_EMERG "Bank %d: %08x%08x", i, high, low);			high&=~(1<<31);			if(high&(1<<27))			{				rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);				mc_err.mci_misc = ((u64)ahigh << 32) | alow;				printk("[%08x%08x]", alow, ahigh);			}			if(high&(1<<26))			{				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);				mc_err.mci_addr = ((u64)ahigh << 32) | alow;				printk(" at %08x%08x",					ahigh, alow);			}			rdmsr(MSR_IA32_MC0_CTL+i*4, alow, ahigh);			mc_err.mci_ctl = ((u64)ahigh << 32) | alow;			printk("\n");			/* Clear it */			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);			/* Serialize */			wmb();			notifier_call_chain(&mc_notifier_list, X86_VENDOR_INTEL, &mc_err);		}	}	if(recover&2)		panic("CPU context corrupt");	if(recover&1)		panic("Unable to continue");	printk(KERN_EMERG "Attempting to continue.\n");	mcgstl&=~(1<<2);	wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);}static void unexpected_machine_check(struct pt_regs *regs, long error_code){ 	printk("unexpected machine check %lx\n", error_code); } /* *	Call the installed machine check handler for this CPU setup. */  static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;void do_machine_check(struct pt_regs * regs, long error_code){	notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL);	machine_check_vector(regs, error_code);}/*  *	K8 machine check. */static char *k8bank[] = {	"data cache",	"instruction cache",	"bus unit",	"load/store unit",	"northbridge"};static char *transaction[] = { 	"instruction", "data", "generic", "reserved"}; static char *cachelevel[] = { 	"0", "1", "2", "generic"};static char *memtrans[] = { 	"generic error", "generic read", "generic write", "data read",	"data write", "instruction fetch", "prefetch", "evict", "snoop",	"?", "?", "?", "?", "?", "?", "?"};static char *partproc[] = { 	"local node origin", "local node response", 	"local node observed", "generic participation"};static char *timeout[] = { 	"request didn't time out",	"request timed out"};static char *memoryio[] = { 	"memory", "res.", "i/o", "generic"};static char *nbextendederr[] = { 	"ECC error", 	"CRC error",	"Sync error",	"Master abort",	"Target abort",	"GART error",	"RMW error",	"Watchdog error",	"Chipkill ECC error", 	"<9>","<10>","<11>","<12>",	"<13>","<14>","<15>"};static char *highbits[32] = { 	[31] = "valid",	[30] = "error overflow (multiple errors)",	[29] = "error uncorrected",	[28] = "error enable",	[27] = "misc error valid",	[26] = "error address valid", 	[25] = "processor context corrupt", 	[24] = "res24",	[23] = "res23",	/* 22-15 ecc syndrome bits */	[14] = "corrected ecc error",	[13] = "uncorrected ecc error",	[12] = "res12",	[11] = "res11",	[10] = "res10",	[9] = "res9",	[8] = "error found by scrub", 	[7] = "res7",	/* 6-4 ht link number of error */ 	[3] = "res3",	[2] = "res2",	[1] = "err cpu1",	[0] = "err cpu0",};static void decode_k8_generic_errcode(unsigned int cpunum, u64 status){	unsigned short errcode = status & 0xffff;	int i;	for (i=0; i<32; i++) {		if (i==31 || i==28 || i==26)			continue;		if (highbits[i] && (status & (1UL<<(i+32)))) {			printk(KERN_ERR "CPU%d:   bit%d = %s\n", cpunum, i+32, highbits[i]);		}	}	if ((errcode & 0xFFF0) == 0x0010) {		printk(KERN_ERR "CPU%d: TLB error '%s transaction, level %s'\n",		       cpunum,		       transaction[(errcode >> 2) & 3],		       cachelevel[errcode & 3]);	}	else if ((errcode & 0xFF00) == 0x0100) {		printk(KERN_ERR "CPU%d: memory/cache error '%s mem transaction, %s transaction, level %s'\n",		       cpunum,		       memtrans[(errcode >> 4) & 0xf],		       transaction[(errcode >> 2) & 3],		       cachelevel[errcode & 3]);	}	else if ((errcode & 0xF800) == 0x0800) {		printk(KERN_ERR "CPU%d: bus error '%s, %s\n      %s mem transaction\n      %s access, level %s'\n",		       cpunum,		       partproc[(errcode >> 9) & 0x3],		       timeout[(errcode >> 8) & 1],		       memtrans[(errcode >> 4) & 0xf],		       memoryio[(errcode >> 2) & 0x3],		       cachelevel[(errcode & 0x3)]);	}}static void decode_k8_dc_mc(unsigned int cpunum, u64 status){	unsigned short exterrcode = (status >> 16) & 0x0f;	unsigned short errcode = status & 0xffff;	if(status&(3UL<<45)) {		printk(KERN_ERR "CPU%d: Data cache ECC error (syndrome %x)",		       cpunum,		       (u32) (status >> 47) & 0xff);		if(status&(1UL<<40)) {			printk(" found by scrubber");		}		printk("\n");	}	if ((errcode & 0xFFF0) == 0x0010) {		printk(KERN_ERR "CPU%d: TLB parity error in %s array\n",		       cpunum,		       (exterrcode == 0) ? "physical" : "virtual");	}	decode_k8_generic_errcode(cpunum, status);}static void decode_k8_ic_mc(unsigned int cpunum, u64 status){	unsigned short exterrcode = (status >> 16) & 0x0f;	unsigned short errcode = status & 0xffff;	if(status&(3UL<<45)) {		printk(KERN_ERR "CPU%d: Instruction cache ECC error\n",		       cpunum);	}	if ((errcode & 0xFFF0) == 0x0010) {		printk(KERN_ERR "CPU%d: TLB parity error in %s array\n",		       cpunum,		       (exterrcode == 0) ? "physical" : "virtual");	}	decode_k8_generic_errcode(cpunum, status);}static void decode_k8_bu_mc(unsigned int cpunum, u64 status){	unsigned short exterrcode = (status >> 16) & 0x0f;	if(status&(3UL<<45)) {		printk(KERN_ERR "CPU%d: L2 cache ECC error\n",		       cpunum);	}	printk(KERN_ERR "CPU%d: %s array error\n",	       cpunum,	       (exterrcode == 0) ? "Bus or cache" : "Cache tag");	decode_k8_generic_errcode(cpunum, status);}static void decode_k8_ls_mc(unsigned int cpunum, u64 status){	decode_k8_generic_errcode(cpunum, status);}static void decode_k8_nb_mc(unsigned int cpunum, u64 status){	unsigned short exterrcode = (status >> 16) & 0x0f;	printk(KERN_ERR "CPU%d: Northbridge %s\n", cpunum, nbextendederr[exterrcode]);	switch (exterrcode) { 	case 0:		printk(KERN_ERR "CPU%d: ECC syndrome = %x\n",		       cpunum,		       (u32) (status >> 47) & 0xff);		break;	case 8:			printk(KERN_ERR "CPU%d: Chipkill ECC syndrome = %x\n",		       cpunum,	    	   (u32) ((((status >> 24) & 0xff) << 8) | ((status >> 47) & 0xff)));		break;	case 1: 	case 2:	case 3:	case 4:	case 6:		printk(KERN_ERR "CPU%d: link number = %x\n",		       cpunum,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?