⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mca.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * File:	mca.c * Purpose:	Generic MCA handling layer * * Updated for latest kernel * Copyright (C) 2001 Intel * Copyright (C) Fred Lewis (frederick.v.lewis@intel.com) * * Copyright (C) 2000 Intel * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com) * * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) * * 01/01/03 F. Lewis    Added setup of CMCI and CPEI IRQs, logging of corrected *                      platform errors, completed code for logging of *                      corrected & uncorrected machine check errors, and *                      updated for conformance with Nov. 2000 revision of the *                      SAL 3.0 spec. * 00/03/29 C. Fleckenstein  Fixed PAL/SAL update issues, began MCA bug fixes, logging issues, *                           added min save state dump, added INIT handler. */#include <linux/config.h>#include <linux/types.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/smp_lock.h>#include <asm/machvec.h>#include <asm/page.h>#include <asm/ptrace.h>#include <asm/system.h>#include <asm/sal.h>#include <asm/mca.h>#include <asm/irq.h>#include <asm/hw_irq.h>#include <asm/acpi-ext.h>#undef MCA_PRT_XTRA_DATAtypedef struct ia64_fptr {	unsigned long fp;	unsigned long gp;} ia64_fptr_t;ia64_mc_info_t			ia64_mc_info;ia64_mca_sal_to_os_state_t	ia64_sal_to_os_handoff_state;ia64_mca_os_to_sal_state_t	ia64_os_to_sal_handoff_state;u64				ia64_mca_proc_state_dump[512];u64				ia64_mca_stack[1024];u64				ia64_mca_stackframe[32];u64				ia64_mca_bspstore[1024];u64				ia64_init_stack[INIT_TASK_SIZE] __attribute__((aligned(16)));static void			ia64_mca_wakeup_ipi_wait(void);static void			ia64_mca_wakeup(int cpu);static void			ia64_mca_wakeup_all(void);static void			ia64_log_init(int);extern void		        ia64_monarch_init_handler (void);extern void		        ia64_slave_init_handler (void);extern struct hw_interrupt_type irq_type_iosapic_level;static struct irqaction cmci_irqaction = {	handler:    ia64_mca_cmc_int_handler,	flags:      SA_INTERRUPT,	name:       "cmc_hndlr"};static struct irqaction mca_rdzv_irqaction = {	handler:    ia64_mca_rendez_int_handler,	flags:      SA_INTERRUPT,	name:       "mca_rdzv"};static struct irqaction mca_wkup_irqaction = {	handler:    ia64_mca_wakeup_int_handler,	flags:      SA_INTERRUPT,	name:       "mca_wkup"};static struct irqaction mca_cpe_irqaction = {	handler:    ia64_mca_cpe_int_handler,	flags:      SA_INTERRUPT,	name:       "cpe_hndlr"};/* *  ia64_mca_log_sal_error_record * *  This function retrieves a specified error record type from SAL, sends it to *  the system log, and notifies SALs to clear the record from its non-volatile *  memory. * *  Inputs  :   sal_info_type   (Type of error record MCA/CMC/CPE/INIT) *  Outputs :   None */voidia64_mca_log_sal_error_record(int sal_info_type){	/* Get the MCA error record */	if (!ia64_log_get(sal_info_type, (prfunc_t)printk))		return;                 // no record retrieved	/* Log the error record */	ia64_log_print(sal_info_type, (prfunc_t)printk);	/* Clear the CMC SAL logs now that they have been logged */	ia64_sal_clear_state_info(sal_info_type);}/* * hack for now, add platform dependent handlers * here */#ifndef PLATFORM_MCA_HANDLERSvoidmca_handler_platform (void){}voidia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs){	IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. vector = %#x\n", cpe_irq);	/* Get the CMC error record and log it */	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);}/* * This routine will be used to deal with platform specific handling * of the init, i.e. drop into the kernel debugger on server machine, * or if the processor is part of some parallel machine without a * console, then we would call the appropriate debug hooks here. */voidinit_handler_platform (struct pt_regs *regs){	/* if a kernel debugger is available call it here else just dump the registers */	show_regs(regs);		/* dump the state info */	while (1);			/* hang city if no debugger */}/* * ia64_mca_init_platform * *  External entry for platform specific MCA initialization. * *  Inputs *      None * *  Outputs *      None */voidia64_mca_init_platform (void){}/* *  ia64_mca_check_errors * *  External entry to check for error records which may have been posted by SAL *  for a prior failure which resulted in a machine shutdown before an the *  error could be logged.  This function must be called after the filesystem *  is initialized. * *  Inputs  :   None * *  Outputs :   None */voidia64_mca_check_errors (void){	/*	 *  If there is an MCA error record pending, get it and log it.	 */	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);}/* * ia64_mca_register_cpev * *  Register the corrected platform error vector with SAL. * *  Inputs *      cpev        Corrected Platform Error Vector number * *  Outputs *      None */static voidia64_mca_register_cpev (int cpev){	/* Register the CPE interrupt vector with SAL */	if (ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0)) {		printk("ia64_mca_platform_init: failed to register Corrected "		       "Platform Error interrupt vector with SAL.\n");		return;	}	IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error "		       "vector %#x setup and enabled\n", cpev);}#endif /* PLATFORM_MCA_HANDLERS */static char *min_state_labels[] = {	"nat",	"r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",	"r9", "r10","r11", "r12","r13","r14", "r15",	"b0r16","b0r17", "b0r18", "b0r19", "b0r20",	"b0r21", "b0r22","b0r23", "b0r24", "b0r25",	"b0r26", "b0r27", "b0r28","b0r29", "b0r30", "b0r31",	"r16", "r17", "r18","r19", "r20", "r21","r22",	"r23", "r24","r25", "r26", "r27","r28", "r29", "r30","r31",	"preds", "br0", "rsc",	"iip", "ipsr", "ifs",	"xip", "xpsr", "xfs"};int ia64_pmss_dump_bank0=0;  /* dump bank 0 ? *//* * routine to process and prepare to dump min_state_save * information for debugging purposes. * */voidia64_process_min_state_save (pal_min_state_area_t *pmss, struct pt_regs *ptregs){	int i, max=57;	u64 *tpmss_ptr=(u64 *)pmss;	/* dump out the min_state_area information */	for (i=0;i<max;i++) {		if(!ia64_pmss_dump_bank0) {			if(strncmp("B0",min_state_labels[i],2)==0) {				tpmss_ptr++;  /* skip to next entry */				continue;			}		}		printk("%5s=0x%16.16lx ",min_state_labels[i],*tpmss_ptr++);		if (((i+1)%3)==0 || ((!strcmp("GR16",min_state_labels[i]))				     && !ia64_pmss_dump_bank0))			printk("\n");	}}/* * ia64_mca_cmc_vector_setup * *  Setup the corrected machine check vector register in the processor and *  unmask interrupt.  This function is invoked on a per-processor basis. * * Inputs *      None * * Outputs *	None */voidia64_mca_cmc_vector_setup (void){	cmcv_reg_t	cmcv;	cmcv.cmcv_regval	= 0;	cmcv.cmcv_mask      = 0;        /* Unmask/enable interrupt */	cmcv.cmcv_vector    = IA64_CMC_VECTOR;	ia64_set_cmcv(cmcv.cmcv_regval);	IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d corrected "		       "machine check vector %#x setup and enabled.\n",		       smp_processor_id(), IA64_CMC_VECTOR);	IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d CMCV = %#016lx\n",		       smp_processor_id(), ia64_get_cmcv());}#if defined(MCA_TEST)sal_log_processor_info_t	slpi_buf;voidmca_test(void){	slpi_buf.valid.psi_static_struct = 1;	slpi_buf.valid.num_cache_check = 1;	slpi_buf.valid.num_tlb_check = 1;	slpi_buf.valid.num_bus_check = 1;	slpi_buf.valid.processor_static_info.minstate = 1;	slpi_buf.valid.processor_static_info.br = 1;	slpi_buf.valid.processor_static_info.cr = 1;	slpi_buf.valid.processor_static_info.ar = 1;	slpi_buf.valid.processor_static_info.rr = 1;	slpi_buf.valid.processor_static_info.fr = 1;	ia64_os_mca_dispatch();}#endif /* #if defined(MCA_TEST) *//* *  verify_guid * *  Compares a test guid to a target guid and returns result. * *  Inputs *      test_guid *     (ptr to guid to be verified) *      target_guid *   (ptr to standard guid to be verified against) * *  Outputs *      0               (test verifies against target) *      non-zero        (test guid does not verify) */static intverify_guid (efi_guid_t *test, efi_guid_t *target){	int     rc;	if ((rc = memcmp((void *)test, (void *)target, sizeof(efi_guid_t)))) {		IA64_MCA_DEBUG("ia64_mca_print: invalid guid = "			       "{ %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "			       "%#02x, %#02x, %#02x, %#02x, } } \n ",			       test->data1, test->data2, test->data3, test->data4[0],			       test->data4[1], test->data4[2], test->data4[3],			       test->data4[4], test->data4[5], test->data4[6],			       test->data4[7]);	}	return rc;}/* * ia64_mca_init * *  Do all the system level mca specific initialization. * *	1. Register spinloop and wakeup request interrupt vectors * *	2. Register OS_MCA handler entry point * *	3. Register OS_INIT handler entry point * *  4. Initialize MCA/CMC/INIT related log buffers maintained by the OS. * *  Note that this initialization is done very early before some kernel *  services are available. * *  Inputs  :   None * *  Outputs :   None */void __initia64_mca_init(void){	ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;	ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;	ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;	int i;	s64 rc;	IA64_MCA_DEBUG("ia64_mca_init: begin\n");	/* Clear the Rendez checkin flag for all cpus */	for(i = 0 ; i < NR_CPUS; i++)		ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;	/*	 * Register the rendezvous spinloop and wakeup mechanism with SAL	 */	/* Register the rendezvous interrupt vector with SAL */	if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,					 SAL_MC_PARAM_MECHANISM_INT,					 IA64_MCA_RENDEZ_VECTOR,					 IA64_MCA_RENDEZ_TIMEOUT,					 0)))	{		printk("ia64_mca_init: Failed to register rendezvous interrupt "		       "with SAL.  rc = %ld\n", rc);		return;	}	/* Register the wakeup interrupt vector with SAL */	if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,					 SAL_MC_PARAM_MECHANISM_INT,					 IA64_MCA_WAKEUP_VECTOR,					 0, 0)))	{		printk("ia64_mca_init: Failed to register wakeup interrupt with SAL.  rc = %ld\n",		       rc);		return;	}	IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.\n");	ia64_mc_info.imi_mca_handler        = __pa(mca_hldlr_ptr->fp);	/*	 * XXX - disable SAL checksum by setting size to 0; should be	 *	__pa(ia64_os_mca_dispatch_end) - __pa(ia64_os_mca_dispatch);	 */	ia64_mc_info.imi_mca_handler_size	= 0;	/* Register the os mca handler with SAL */	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,				       ia64_mc_info.imi_mca_handler,				       mca_hldlr_ptr->gp,				       ia64_mc_info.imi_mca_handler_size,				       0, 0, 0)))	{		printk("ia64_mca_init: Failed to register os mca handler with SAL.  rc = %ld\n",		       rc);		return;	}	IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n",		       ia64_mc_info.imi_mca_handler, mca_hldlr_ptr->gp);	/*	 * XXX - disable SAL checksum by setting size to 0, should be	 * IA64_INIT_HANDLER_SIZE	 */	ia64_mc_info.imi_monarch_init_handler		= __pa(mon_init_ptr->fp);	ia64_mc_info.imi_monarch_init_handler_size	= 0;	ia64_mc_info.imi_slave_init_handler		= __pa(slave_init_ptr->fp);	ia64_mc_info.imi_slave_init_handler_size	= 0;	IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lx\n",		       ia64_mc_info.imi_monarch_init_handler);	/* Register the os init handler with SAL */	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,				       ia64_mc_info.imi_monarch_init_handler,				       __pa(ia64_get_gp()),				       ia64_mc_info.imi_monarch_init_handler_size,				       ia64_mc_info.imi_slave_init_handler,				       __pa(ia64_get_gp()),				       ia64_mc_info.imi_slave_init_handler_size)))	{		printk("ia64_mca_init: Failed to register m/s init handlers with SAL. rc = %ld\n",		       rc);		return;	}	IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SAL\n");	/*	 *  Configure the CMCI vector and handler. Interrupts for CMC are	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smp.c).	 */	register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);	ia64_mca_cmc_vector_setup();       /* Setup vector on BSP & enable */	/* Setup the MCA rendezvous interrupt vector */	register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);	/* Setup the MCA wakeup interrupt vector */	register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);

⌨️ 快捷键说明

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