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

📄 mca.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Setup the CPE interrupt vector */	{		irq_desc_t *desc;		unsigned int irq;		int cpev = acpi_request_vector(ACPI20_ENTRY_PIS_CPEI);		if (cpev >= 0) {			for (irq = 0; irq < NR_IRQS; ++irq)				if (irq_to_vector(irq) == cpev) {					desc = irq_desc(irq);					desc->status |= IRQ_PER_CPU;					desc->handler = &irq_type_iosapic_level;					setup_irq(irq, &mca_cpe_irqaction);				}			ia64_mca_register_cpev(cpev);		} else			printk("ia64_mca_init: Failed to get routed CPEI vector from ACPI.\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);	ia64_log_init(SAL_INFO_TYPE_INIT);	ia64_log_init(SAL_INFO_TYPE_CMC);	ia64_log_init(SAL_INFO_TYPE_CPE);#if defined(MCA_TEST)	mca_test();#endif /* #if defined(MCA_TEST) */	printk("Mca related initialization done\n");#if 0   // Too early in initialization -- error log is lost	/* Do post-failure MCA error logging */	ia64_mca_check_errors();#endif  // Too early in initialization -- error log is lost}/* * 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_VECTOR >> 6);	int	irr_bit = (IA64_MCA_WAKEUP_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_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 :   None * */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;	/* Cold Boot for uncorrectable MCA */	ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;}/* * 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 rendezvous spinloop. * *  Inputs  :   None *  Outputs :   None */voidia64_mca_ucmc_handler(void){#if 0   /* stubbed out @FVL */	/*	 *  Attempting to log a DBE error Causes "reserved register/field panic"	 *  in printk.	 */	/* Get the MCA error record and log it */	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);#endif  /* stubbed out @FVL */	/*	 *  Do Platform-specific mca error handling if required.	 */	mca_handler_platform() ;	/*	 *  Wakeup all the processors which are spinning in the rendezvous	 *  loop.	 */	ia64_mca_wakeup_all();	/* Return to SAL */	ia64_return_to_sal_check();}/* * ia64_mca_cmc_int_handler * *  This is corrected machine check interrupt handler. *	Right now the logs are extracted and displayed in a well-defined *	format. * * Inputs *      interrupt number *      client data arg ptr *      saved registers ptr * * Outputs *	None */voidia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs){	IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %d\n",		       cmc_irq, smp_processor_id());	/* Get the CMC error record and log it */	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);}/* * IA64_MCA log support */#define IA64_MAX_LOGS		2	/* Double-buffering for nested MCAs */#define IA64_MAX_LOG_TYPES      4   /* MCA, INIT, CMC, CPE */typedef struct ia64_state_log_s{	spinlock_t	isl_lock;	int		isl_index;	ia64_err_rec_t  isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */} ia64_state_log_t;static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];/* Note:  Some of these macros assume IA64_MAX_LOGS is always 2.  Should be *//* fixed. @FVL                                                              */#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)#define IA64_LOG_LOCK(it)      spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)#define IA64_LOG_UNLOCK(it)    spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)#define IA64_LOG_NEXT_INDEX(it)    ia64_state_log[it].isl_index#define IA64_LOG_CURR_INDEX(it)    1 - ia64_state_log[it].isl_index#define IA64_LOG_INDEX_INC(it) \    ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index#define IA64_LOG_INDEX_DEC(it) \    ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index#define IA64_LOG_NEXT_BUFFER(it)   (void *)(&(ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]))#define IA64_LOG_CURR_BUFFER(it)   (void *)(&(ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))/* * C portion of the OS INIT handler * * Called from ia64_<monarch/slave>_init_handler * * Inputs: pointer to pt_regs where processor info was saved. * * Returns: *   0 if SAL must warm boot the System *   1 if SAL must return to interrupted context using PAL_MC_RESUME * */voidia64_init_handler (struct pt_regs *regs){	sal_log_processor_info_t *proc_ptr;	ia64_err_rec_t *plog_ptr;	printk("Entered OS INIT handler\n");	/* Get the INIT processor log */	if (!ia64_log_get(SAL_INFO_TYPE_INIT, (prfunc_t)printk))		return;                 // no record retrieved#ifdef IA64_DUMP_ALL_PROC_INFO	ia64_log_print(SAL_INFO_TYPE_INIT, (prfunc_t)printk);#endif	/*	 * get pointer to min state save area	 *	 */	plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT);	proc_ptr = &plog_ptr->proc_err;	ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area,				    regs);	/* Clear the INIT SAL logs now that they have been saved in the OS buffer */	ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);	init_handler_platform(regs);              /* call platform specific routines */}/* *  ia64_log_prt_guid * *  Print a formatted GUID. * * Inputs   :   p_guid      (ptr to the GUID) *              prfunc      (print function) * Outputs  :   None * */voidia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc){	printk("GUID = { %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "	       "%#02x, %#02x, %#02x, %#02x, } } \n ", p_guid->data1,	       p_guid->data2, p_guid->data3, p_guid->data4[0], p_guid->data4[1],	       p_guid->data4[2], p_guid->data4[3], p_guid->data4[4],	       p_guid->data4[5], p_guid->data4[6], p_guid->data4[7]);}static voidia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc){	int i, j;	if (!p)		return;	for (i = 0; i < n_ch;) {		prfunc("%p ", (void *)p);		for (j = 0; (j < 16) && (i < n_ch); i++, j++, p++) {			prfunc("%02x ", *p);		}		prfunc("\n");	}}#ifdef MCA_PRT_XTRA_DATA    // for test only @FVLstatic voidia64_log_prt_record_header (sal_log_record_header_t *rh, prfunc_t prfunc){	prfunc("SAL RECORD HEADER:  Record buffer = %p,  header size = %ld\n",	       (void *)rh, sizeof(sal_log_record_header_t));	ia64_log_hexdump((unsigned char *)rh, sizeof(sal_log_record_header_t),			 (prfunc_t)prfunc);	prfunc("Total record length = %d\n", rh->len);	ia64_log_prt_guid(&rh->platform_guid, prfunc);	prfunc("End of SAL RECORD HEADER\n");}static voidia64_log_prt_section_header (sal_log_section_hdr_t *sh, prfunc_t prfunc){	prfunc("SAL SECTION HEADER:  Record buffer = %p,  header size = %ld\n",	       (void *)sh, sizeof(sal_log_section_hdr_t));	ia64_log_hexdump((unsigned char *)sh, sizeof(sal_log_section_hdr_t),			 (prfunc_t)prfunc);	prfunc("Length of section & header = %d\n", sh->len);	ia64_log_prt_guid(&sh->guid, prfunc);	prfunc("End of SAL SECTION HEADER\n");}#endif  // MCA_PRT_XTRA_DATA for test only @FVL/* * ia64_log_init *	Reset the OS ia64 log buffer * Inputs   :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) * Outputs	:	None */voidia64_log_init(int sal_info_type){	IA64_LOG_LOCK_INIT(sal_info_type);	IA64_LOG_NEXT_INDEX(sal_info_type) = 0;	memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0,	       sizeof(ia64_err_rec_t) * IA64_MAX_LOGS);}/* * ia64_log_get * *	Get the current MCA log from SAL and copy it into the OS log buffer. * *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) *              prfunc      (fn ptr of log output function) *  Outputs :   size        (total record length) * */u64ia64_log_get(int sal_info_type, prfunc_t prfunc){	sal_log_record_header_t     *log_buffer;	u64                         total_len = 0;	int                         s;	IA64_LOG_LOCK(sal_info_type);	/* Get the process state information */	log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type);	total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer);	if (total_len) {		IA64_LOG_INDEX_INC(sal_info_type);		IA64_LOG_UNLOCK(sal_info_type);		IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. "			       "Record length = %ld\n", sal_info_type, total_len);		return total_len;	} else {		IA64_LOG_UNLOCK(sal_info_type);		prfunc("ia64_log_get: Failed to retrieve SAL error record type %d\n",		       sal_info_type);		return 0;	}}/* *  ia64_log_prt_oem_data * *  Print OEM specific data if included. * * Inputs   :   header_len  (length passed in section header) *              sect_len    (default length of section type) *              p_data      (ptr to data) *			prfunc		(print function) * Outputs	:	None *

⌨️ 快捷键说明

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