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

📄 mca.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * File: 	mca.c * Purpose: 	Generic MCA handling layer * * Updated for latest kernel * 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) * * 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/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> typedef 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[256];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_cmc_vector_setup(int 		enable, 							  int_vector_t 	cmc_vector);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,int);static void			ia64_log_get(int,int, prfunc_t);static void			ia64_log_clear(int,int,int, prfunc_t);extern void		        ia64_monarch_init_handler (void);extern void		        ia64_slave_init_handler (void);/* * hack for now, add platform dependent handlers * here */#ifndef PLATFORM_MCA_HANDLERSvoidmca_handler_platform (void){}voidcmci_handler_platform (int cmc_irq, void *arg, struct pt_regs *ptregs){}/* * 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 */}voidlog_print_platform ( void *cur_buff_ptr, prfunc_t prfunc){}	voidia64_mca_init_platform (void){}#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");	}	/* hang city for now, until we include debugger or copy to ptregs to show: */	while (1);} /* * ia64_mca_cmc_vector_setup *	Setup the correctable machine check vector register in the processor * Inputs *	Enable (1 - enable cmc interrupt , 0 - disable) *	CMC handler entry point (if enabled) * * Outputs *	None */static voidia64_mca_cmc_vector_setup(int 		enable, 			  int_vector_t 	cmc_vector){	cmcv_reg_t	cmcv;	cmcv.cmcv_regval 	= 0;	cmcv.cmcv_mask  	= enable;	cmcv.cmcv_vector 	= cmc_vector;	ia64_set_cmcv(cmcv.cmcv_regval);}#if defined(MCA_TEST)sal_log_processor_info_t	slpi_buf;voidmca_test(void){	slpi_buf.slpi_valid.slpi_psi = 1;	slpi_buf.slpi_valid.slpi_cache_check = 1;	slpi_buf.slpi_valid.slpi_tlb_check = 1;	slpi_buf.slpi_valid.slpi_bus_check = 1;	slpi_buf.slpi_valid.slpi_minstate = 1;	slpi_buf.slpi_valid.slpi_bank1_gr = 1;	slpi_buf.slpi_valid.slpi_br = 1;	slpi_buf.slpi_valid.slpi_cr = 1;	slpi_buf.slpi_valid.slpi_ar = 1;	slpi_buf.slpi_valid.slpi_rr = 1;	slpi_buf.slpi_valid.slpi_fr = 1;	ia64_os_mca_dispatch();}#endif /* #if defined(MCA_TEST) *//* * ia64_mca_init *	Do all the mca specific initialization on a per-processor basis. * *	1. Register spinloop and wakeup request interrupt vectors * *	2. Register OS_MCA handler entry point * *	3. Register OS_INIT handler entry point * *	4. Initialize CMCV register to enable/disable CMC interrupt on the *	   processor and hook a handler in the platform-specific ia64_mca_init. * *	5. Initialize MCA/CMC/INIT related log buffers maintained by the OS. * * 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;	int i;	IA64_MCA_DEBUG("ia64_mca_init : begin\n");	/* Clear the Rendez checkin flag for all cpus */	for(i = 0 ; i < IA64_MAXCPUS; i++)		ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;	/* NOTE : The actual irqs for the rendez, wakeup and 	 * cmc interrupts are requested in the platform-specific	 * mca initialization code.	 */	/* 	 * Register the rendezvous spinloop and wakeup mechanism with SAL	 */	/* Register the rendezvous interrupt vector with SAL */	if (ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,				   SAL_MC_PARAM_MECHANISM_INT,				   IA64_MCA_RENDEZ_INT_VECTOR,				   IA64_MCA_RENDEZ_TIMEOUT))		return;	/* Register the wakeup interrupt vector with SAL */	if (ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,				   SAL_MC_PARAM_MECHANISM_INT,				   IA64_MCA_WAKEUP_INT_VECTOR,				   0))		return;	IA64_MCA_DEBUG("ia64_mca_init : registered mca rendezvous spinloop and wakeup mech.\n");	/*	 * Setup the correctable machine check vector	 */	ia64_mca_cmc_vector_setup(IA64_CMC_INT_ENABLE, 				  IA64_MCA_CMC_INT_VECTOR);	IA64_MCA_DEBUG("ia64_mca_init : correctable mca vector setup done\n");	ia64_mc_info.imi_mca_handler 		= __pa(ia64_os_mca_dispatch);	/*	 * 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 (ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,				 ia64_mc_info.imi_mca_handler,				 __pa(ia64_get_gp()),				 ia64_mc_info.imi_mca_handler_size,				 0,0,0))		return;	IA64_MCA_DEBUG("ia64_mca_init : registered os mca handler with SAL\n");	/* 	 * 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 (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))		return;	IA64_MCA_DEBUG("ia64_mca_init : registered os init handler with SAL\n");	/* Initialize the areas set aside by the OS to buffer the 	 * platform/processor error states for MCA/INIT/CMC	 * handling.	 */	ia64_log_init(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR);	ia64_log_init(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM);	ia64_log_init(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR);	ia64_log_init(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM);	ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR);	ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM);	ia64_mca_init_platform();		IA64_MCA_DEBUG("ia64_mca_init : platform-specific mca handling setup done\n");#if defined(MCA_TEST)	mca_test();#endif /* #if defined(MCA_TEST) */	printk("Mca related initialization done\n");}/* * ia64_mca_wakeup_ipi_wait *	Wait for the inter-cpu interrupt to be sent by the * 	monarch processor once it is done with handling the *	MCA. * Inputs  *	None * Outputs *	None */voidia64_mca_wakeup_ipi_wait(void){	int	irr_num = (IA64_MCA_WAKEUP_INT_VECTOR >> 6);	int	irr_bit = (IA64_MCA_WAKEUP_INT_VECTOR & 0x3f);	u64	irr = 0;	do {		switch(irr_num) {		case 0:			irr = ia64_get_irr0();			break;		case 1:			irr = ia64_get_irr1();			break;		case 2:			irr = ia64_get_irr2();			break;		case 3:			irr = ia64_get_irr3();			break;		}	} while (!(irr & (1 << irr_bit))) ;}/* * ia64_mca_wakeup *	Send an inter-cpu interrupt to wake-up a particular cpu * 	and mark that cpu to be out of rendez. * Inputs *	cpuid * Outputs *	None */voidia64_mca_wakeup(int cpu){	platform_send_ipi(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT, 0);	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;	}/* * ia64_mca_wakeup_all *	Wakeup all the cpus which have rendez'ed previously. * Inputs *	None * Outputs *	None */voidia64_mca_wakeup_all(void){	int cpu;	/* Clear the Rendez checkin flag for all cpus */	for(cpu = 0 ; cpu < smp_num_cpus; cpu++)		if (ia64_mc_info.imi_rendez_checkin[cpu] == IA64_MCA_RENDEZ_CHECKIN_DONE)			ia64_mca_wakeup(cpu);}/* * ia64_mca_rendez_interrupt_handler *	This is handler used to put slave processors into spinloop  *	while the monarch processor does the mca handling and later *	wake each slave up once the monarch is done. * Inputs  *	None * Outputs *	None */voidia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs){	int flags, cpu = 0;	/* Mask all interrupts */        save_and_cli(flags);#ifdef CONFIG_SMP	cpu = cpu_logical_id(hard_smp_processor_id());#endif	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;	/* Register with the SAL monarch that the slave has	 * reached SAL	 */	ia64_sal_mc_rendez();	/* Wait for the wakeup IPI from the monarch 	 * This waiting is done by polling on the wakeup-interrupt	 * vector bit in the processor's IRRs	 */	ia64_mca_wakeup_ipi_wait();	/* Enable all interrupts */	restore_flags(flags);}/* * ia64_mca_wakeup_int_handler *	The interrupt handler for processing the inter-cpu interrupt to the * 	slave cpu which was spinning in the rendez loop. *	Since this spinning is done by turning off the interrupts and *	polling on the wakeup-interrupt bit in the IRR, there is  *	nothing useful to be done in the handler. *  Inputs *	wakeup_irq	(Wakeup-interrupt bit) *	arg		(Interrupt handler specific argument) *	ptregs		(Exception frame at the time of the interrupt) *  Outputs *	 */voidia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs){	}/* * ia64_return_to_sal_check *	This is function called before going back from the OS_MCA handler * 	to the OS_MCA dispatch code which finally takes the control back * 	to the SAL. *	The main purpose of this routine is to setup the OS_MCA to SAL *	return state which can be used by the OS_MCA dispatch code  *	just before going back to SAL. * Inputs *	None * Outputs *	None */voidia64_return_to_sal_check(void){	/* Copy over some relevant stuff from the sal_to_os_mca_handoff	 * so that it can be used at the time of os_mca_to_sal_handoff	 */	ia64_os_to_sal_handoff_state.imots_sal_gp = 		ia64_sal_to_os_handoff_state.imsto_sal_gp;	ia64_os_to_sal_handoff_state.imots_sal_check_ra = 		ia64_sal_to_os_handoff_state.imsto_sal_check_ra;	/* For now ignore the MCA */	ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;}/*  * ia64_mca_ucmc_handler *	This is uncorrectable machine check handler called from OS_MCA *	dispatch code which is in turn called from SAL_CHECK(). *	This is the place where the core of OS MCA handling is done. *	Right now the logs are extracted and displayed in a well-defined *	format. This handler code is supposed to be run only on the *	monarch processor. Once the  monarch is done with MCA handling *	further MCA logging is enabled by clearing logs. *	Monarch also has the duty of sending wakeup-IPIs to pull the *	slave processors out of rendez. spinloop. * Inputs *	None * Outputs

⌨️ 快捷键说明

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