📄 mca.c
字号:
* None */voidia64_mca_ucmc_handler(void){ /* Get the MCA processor log */ ia64_log_get(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk); /* Get the MCA platform log */ ia64_log_get(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk); ia64_log_print(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk); /* * Do some error handling - Platform-specific mca handler is called at this point */ mca_handler_platform() ; /* Clear the SAL MCA logs */ ia64_log_clear(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, 1, printk); ia64_log_clear(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM, 1, printk); /* Wakeup all the processors which are spinning in the rendezvous * loop. */ ia64_mca_wakeup_all(); ia64_return_to_sal_check();}/* * ia64_mca_cmc_int_handler * This is correctable machine check interrupt handler. * Right now the logs are extracted and displayed in a well-defined * format. * Inputs * None * Outputs * None */voidia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs){ /* Get the CMC processor log */ ia64_log_get(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk); /* Get the CMC platform log */ ia64_log_get(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk); ia64_log_print(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk); cmci_handler_platform(cmc_irq, arg, ptregs); /* Clear the CMC SAL logs now that they have been saved in the OS buffer */ ia64_sal_clear_state_info(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR); ia64_sal_clear_state_info(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM);}/* * IA64_MCA log support */#define IA64_MAX_LOGS 2 /* Double-buffering for nested MCAs */#define IA64_MAX_LOG_TYPES 3 /* MCA, CMC, INIT */#define IA64_MAX_LOG_SUBTYPES 2 /* Processor, Platform */typedef struct ia64_state_log_s { spinlock_t isl_lock; int isl_index; ia64_psilog_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][IA64_MAX_LOG_SUBTYPES];#define IA64_LOG_LOCK_INIT(it, sit) spin_lock_init(&ia64_state_log[it][sit].isl_lock)#define IA64_LOG_LOCK(it, sit) spin_lock_irqsave(&ia64_state_log[it][sit].isl_lock, s)#define IA64_LOG_UNLOCK(it, sit) spin_unlock_irqrestore(&ia64_state_log[it][sit].isl_lock,\ s)#define IA64_LOG_NEXT_INDEX(it, sit) ia64_state_log[it][sit].isl_index#define IA64_LOG_CURR_INDEX(it, sit) 1 - ia64_state_log[it][sit].isl_index#define IA64_LOG_INDEX_INC(it, sit) \ ia64_state_log[it][sit].isl_index = 1 - ia64_state_log[it][sit].isl_index#define IA64_LOG_INDEX_DEC(it, sit) \ ia64_state_log[it][sit].isl_index = 1 - ia64_state_log[it][sit].isl_index#define IA64_LOG_NEXT_BUFFER(it, sit) (void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_NEXT_INDEX(it,sit)]))#define IA64_LOG_CURR_BUFFER(it, sit) (void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_CURR_INDEX(it,sit)]))/* * 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 retrun to interrupted context using PAL_MC_RESUME * */voidia64_init_handler (struct pt_regs *regs){ sal_log_processor_info_t *proc_ptr; ia64_psilog_t *plog_ptr; printk("Entered OS INIT handler\n"); /* Get the INIT processor log */ ia64_log_get(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk); /* Get the INIT platform log */ ia64_log_get(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk);#ifdef IA64_DUMP_ALL_PROC_INFO ia64_log_print(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);#endif /* * get pointer to min state save area * */ plog_ptr=(ia64_psilog_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR); proc_ptr = &plog_ptr->devlog.proclog; ia64_process_min_state_save(&proc_ptr->slpi_min_state_area,regs); init_handler_platform(regs); /* call platform specific routines */ /* Clear the INIT SAL logs now that they have been saved in the OS buffer */ ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR); ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM);}/* * ia64_log_init * Reset the OS ia64 log buffer * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC}) * sub_info_type (SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM}) * Outputs : None */voidia64_log_init(int sal_info_type, int sal_sub_info_type){ IA64_LOG_LOCK_INIT(sal_info_type, sal_sub_info_type); IA64_LOG_NEXT_INDEX(sal_info_type, sal_sub_info_type) = 0; memset(IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type), 0, sizeof(ia64_psilog_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}) * sub_info_type (SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM}) * Outputs : None * */voidia64_log_get(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc){ sal_log_header_t *log_buffer; int s,total_len=0; IA64_LOG_LOCK(sal_info_type, sal_sub_info_type); /* Get the process state information */ log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type); if (!(total_len=ia64_sal_get_state_info(sal_info_type, sal_sub_info_type ,(u64 *)log_buffer))) prfunc("ia64_mca_log_get : Getting processor log failed\n"); IA64_MCA_DEBUG("ia64_log_get: retrieved %d bytes of error information\n",total_len); IA64_LOG_INDEX_INC(sal_info_type, sal_sub_info_type); IA64_LOG_UNLOCK(sal_info_type, sal_sub_info_type);}/* * ia64_log_clear * Clear the current MCA log from SAL and dpending on the clear_os_buffer flags * clear the OS log buffer also * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC}) * sub_info_type (SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM}) * clear_os_buffer * prfunc (print function) * Outputs : None * */voidia64_log_clear(int sal_info_type, int sal_sub_info_type, int clear_os_buffer, prfunc_t prfunc){ if (ia64_sal_clear_state_info(sal_info_type, sal_sub_info_type)) prfunc("ia64_mca_log_get : Clearing processor log failed\n"); if (clear_os_buffer) { sal_log_header_t *log_buffer; int s; IA64_LOG_LOCK(sal_info_type, sal_sub_info_type); /* Get the process state information */ log_buffer = IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type); memset(log_buffer, 0, sizeof(ia64_psilog_t)); IA64_LOG_INDEX_DEC(sal_info_type, sal_sub_info_type); IA64_LOG_UNLOCK(sal_info_type, sal_sub_info_type); }}/* * ia64_log_processor_regs_print * Print the contents of the saved processor register(s) in the format * <reg_prefix>[<index>] <value> * * Inputs : regs (Register save buffer) * reg_num (# of registers) * reg_class (application/banked/control/bank1_general) * reg_prefix (ar/br/cr/b1_gr) * Outputs : None * */voidia64_log_processor_regs_print(u64 *regs, int reg_num, char *reg_class, char *reg_prefix, prfunc_t prfunc){ int i; prfunc("+%s Registers\n", reg_class); for (i = 0; i < reg_num; i++) prfunc("+ %s[%d] 0x%lx\n", reg_prefix, i, regs[i]);}static char *pal_mesi_state[] = { "Invalid", "Shared", "Exclusive", "Modified", "Reserved1", "Reserved2", "Reserved3", "Reserved4"};static char *pal_cache_op[] = { "Unknown", "Move in", "Cast out", "Coherency check", "Internal", "Instruction fetch", "Implicit Writeback", "Reserved"};/* * ia64_log_cache_check_info_print * Display the machine check information related to cache error(s). * Inputs : i (Multiple errors are logged, i - index of logged error) * info (Machine check info logged by the PAL and later * captured by the SAL) * target_addr (Address which caused the cache error) * Outputs : None */void ia64_log_cache_check_info_print(int i, pal_cache_check_info_t info, u64 target_addr, prfunc_t prfunc){ prfunc("+ Cache check info[%d]\n+", i); prfunc(" Level: L%d",info.level); if (info.mv) prfunc(" ,Mesi: %s",pal_mesi_state[info.mesi]); prfunc(" ,Index: %d,", info.index); if (info.ic) prfunc(" ,Cache: Instruction"); if (info.dc) prfunc(" ,Cache: Data"); if (info.tl) prfunc(" ,Line: Tag"); if (info.dl) prfunc(" ,Line: Data"); prfunc(" ,Operation: %s,", pal_cache_op[info.op]); if (info.wv) prfunc(" ,Way: %d,", info.way); if (info.tv) prfunc(" ,Target Addr: 0x%lx", target_addr); if (info.mc) prfunc(" ,MC: Corrected"); prfunc("\n");}/* * ia64_log_tlb_check_info_print * Display the machine check information related to tlb error(s). * Inputs : i (Multiple errors are logged, i - index of logged error) * info (Machine check info logged by the PAL and later * captured by the SAL) * Outputs : None */voidia64_log_tlb_check_info_print(int i, pal_tlb_check_info_t info, prfunc_t prfunc){ prfunc("+ TLB Check Info [%d]\n+", i); if (info.itc) prfunc(" Failure: Instruction Translation Cache"); if (info.dtc) prfunc(" Failure: Data Translation Cache"); if (info.itr) { prfunc(" Failure: Instruction Translation Register"); prfunc(" ,Slot: %d", info.tr_slot); } if (info.dtr) { prfunc(" Failure: Data Translation Register"); prfunc(" ,Slot: %d", info.tr_slot); } if (info.mc) prfunc(" ,MC: Corrected"); prfunc("\n");}/* * ia64_log_bus_check_info_print * Display the machine check information related to bus error(s). * Inputs : i (Multiple errors are logged, i - index of logged error) * info (Machine check info logged by the PAL and later * captured by the SAL) * req_addr (Address of the requestor of the transaction) * resp_addr (Address of the responder of the transaction) * target_addr (Address where the data was to be delivered to or * obtained from) * Outputs : None */voidia64_log_bus_check_info_print(int i, pal_bus_check_info_t info, u64 req_addr, u64 resp_addr, u64 targ_addr, prfunc_t prfunc){ prfunc("+ BUS Check Info [%d]\n+", i); prfunc(" Status Info: %d", info.bsi); prfunc(" ,Severity: %d", info.sev); prfunc(" ,Transaction Type: %d", info.type); prfunc(" ,Transaction Size: %d", info.size); if (info.cc) prfunc(" ,Cache-cache-transfer"); if (info.ib) prfunc(" ,Error: Internal"); if (info.eb) prfunc(" ,Error: External"); if (info.mc) prfunc(" ,MC: Corrected"); if (info.tv) prfunc(" ,Target Address: 0x%lx", targ_addr); if (info.rq) prfunc(" ,Requestor Address: 0x%lx", req_addr); if (info.tv) prfunc(" ,Responder Address: 0x%lx", resp_addr); prfunc("\n");}/* * ia64_log_processor_info_print * Display the processor-specific information logged by PAL as a part * of MCA or INIT or CMC. * Inputs : lh (Pointer of the sal log header which specifies the format * of SAL state info as specified by the SAL spec). * Outputs : None */voidia64_log_processor_info_print(sal_log_header_t *lh, prfunc_t prfunc){ sal_log_processor_info_t *slpi; int i; if (!lh) return; if (lh->slh_log_type != SAL_SUB_INFO_TYPE_PROCESSOR) return; slpi = (sal_log_processor_info_t *)((char *)lh+sizeof(sal_log_header_t)); /* point to proc info */ if (!slpi) { prfunc("No Processor Error Log found\n"); return; } /* Print branch register contents if valid */ if (slpi->slpi_valid.slpi_br) ia64_log_processor_regs_print(slpi->slpi_br, 8, "Branch", "br", prfunc); /* Print control register contents if valid */ if (slpi->slpi_valid.slpi_cr) ia64_log_processor_regs_print(slpi->slpi_cr, 128, "Control", "cr", prfunc); /* Print application register contents if valid */ if (slpi->slpi_valid.slpi_ar) ia64_log_processor_regs_print(slpi->slpi_br, 128, "Application", "ar", prfunc); /* Print region register contents if valid */ if (slpi->slpi_valid.slpi_rr) ia64_log_processor_regs_print(slpi->slpi_rr, 8, "Region", "rr", prfunc); /* Print floating-point register contents if valid */ if (slpi->slpi_valid.slpi_fr) ia64_log_processor_regs_print(slpi->slpi_fr, 128, "Floating-point", "fr", prfunc); /* Print the cache check information if any*/ for (i = 0 ; i < MAX_CACHE_ERRORS; i++) ia64_log_cache_check_info_print(i, slpi->slpi_cache_check_info[i].slpi_cache_check, slpi->slpi_cache_check_info[i].slpi_target_address, prfunc); /* Print the tlb check information if any*/ for (i = 0 ; i < MAX_TLB_ERRORS; i++) ia64_log_tlb_check_info_print(i,slpi->slpi_tlb_check_info[i], prfunc); /* Print the bus check information if any*/ for (i = 0 ; i < MAX_BUS_ERRORS; i++) ia64_log_bus_check_info_print(i, slpi->slpi_bus_check_info[i].slpi_bus_check, slpi->slpi_bus_check_info[i].slpi_requestor_addr, slpi->slpi_bus_check_info[i].slpi_responder_addr, slpi->slpi_bus_check_info[i].slpi_target_addr, prfunc);}/* * ia64_log_print * Display the contents of the OS error log information * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC}) * sub_info_type (SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM}) * Outputs : None */voidia64_log_print(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc){ char *info_type, *sub_info_type; switch(sal_info_type) { case SAL_INFO_TYPE_MCA: info_type = "MCA"; break; case SAL_INFO_TYPE_INIT: info_type = "INIT"; break; case SAL_INFO_TYPE_CMC: info_type = "CMC"; break; default: info_type = "UNKNOWN"; break; } switch(sal_sub_info_type) { case SAL_SUB_INFO_TYPE_PROCESSOR: sub_info_type = "PROCESSOR"; break; case SAL_SUB_INFO_TYPE_PLATFORM: sub_info_type = "PLATFORM"; break; default: sub_info_type = "UNKNOWN"; break; } prfunc("+BEGIN HARDWARE ERROR STATE [%s %s]\n", info_type, sub_info_type); if (sal_sub_info_type == SAL_SUB_INFO_TYPE_PROCESSOR) ia64_log_processor_info_print( IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type), prfunc); else log_print_platform(IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type),prfunc); prfunc("+END HARDWARE ERROR STATE [%s %s]\n", info_type, sub_info_type);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -