diff options
Diffstat (limited to 'arch/ia64/kernel/mca.c')
-rw-r--r-- | arch/ia64/kernel/mca.c | 251 |
1 files changed, 196 insertions, 55 deletions
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 320c56ebc..150feac03 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -2,21 +2,37 @@ * 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/types.h> #include <linux/init.h> #include <linux/sched.h> +#include <linux/irq.h> +#include <linux/smp_lock.h> +#include <linux/config.h> + #include <asm/page.h> #include <asm/ptrace.h> #include <asm/system.h> #include <asm/sal.h> #include <asm/mca.h> -#include <asm/spinlock.h> + #include <asm/irq.h> #include <asm/machvec.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; @@ -25,6 +41,11 @@ 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))); + +#if defined(SAL_MPINIT_WORKAROUND) && !defined(CONFIG_SMP) +int bootstrap_processor = -1; +#endif static void ia64_mca_cmc_vector_setup(int enable, int_vector_t cmc_vector); @@ -34,7 +55,98 @@ 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_HANDLERS +void +mca_handler_platform (void) +{ + +} + +void +cmci_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. + */ +void +init_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 */ +} + +void +log_print_platform ( void *cur_buff_ptr, prfunc_t prfunc) +{ +} + +void +ia64_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. + * + */ +void +ia64_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 @@ -83,7 +195,7 @@ mca_test(void) #endif /* #if defined(MCA_TEST) */ /* - * mca_init + * ia64_mca_init * Do all the mca specific initialization on a per-processor basis. * * 1. Register spinloop and wakeup request interrupt vectors @@ -93,7 +205,7 @@ mca_test(void) * 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 mca_init. + * processor and hook a handler in the platform-specific ia64_mca_init. * * 5. Initialize MCA/CMC/INIT related log buffers maintained by the OS. * @@ -103,11 +215,20 @@ mca_test(void) * None */ void __init -mca_init(void) +ia64_mca_init(void) { - int i; + 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"); + +#if defined(SAL_MPINIT_WORKAROUND) && !defined(CONFIG_SMP) + /* XXX -- workaround for SAL bug for running on MP system, but UP kernel */ + + bootstrap_processor = hard_smp_processor_id(); +#endif - MCA_DEBUG("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; @@ -134,14 +255,14 @@ mca_init(void) 0)) return; - MCA_DEBUG("mca_init : registered mca rendezvous spinloop and wakeup mech.\n"); + 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); - MCA_DEBUG("mca_init : correctable mca vector setup done\n"); + IA64_MCA_DEBUG("ia64_mca_init : correctable mca vector setup done\n"); ia64_mc_info.imi_mca_handler = __pa(ia64_os_mca_dispatch); ia64_mc_info.imi_mca_handler_size = @@ -155,12 +276,15 @@ mca_init(void) return; - MCA_DEBUG("mca_init : registered os mca handler with SAL\n"); + IA64_MCA_DEBUG("ia64_mca_init : registered os mca handler with SAL\n"); - ia64_mc_info.imi_monarch_init_handler = __pa(ia64_monarch_init_handler); + ia64_mc_info.imi_monarch_init_handler = __pa(mon_init_ptr->fp); ia64_mc_info.imi_monarch_init_handler_size = IA64_INIT_HANDLER_SIZE; - ia64_mc_info.imi_slave_init_handler = __pa(ia64_slave_init_handler); + ia64_mc_info.imi_slave_init_handler = __pa(slave_init_ptr->fp); ia64_mc_info.imi_slave_init_handler_size = IA64_INIT_HANDLER_SIZE; + + 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, @@ -173,7 +297,7 @@ mca_init(void) return; - MCA_DEBUG("mca_init : registered os init handler with SAL\n"); + 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 @@ -186,9 +310,9 @@ mca_init(void) ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR); ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM); - mca_init_platform(); + ia64_mca_init_platform(); - MCA_DEBUG("mca_init : platform-specific mca handling setup done\n"); + IA64_MCA_DEBUG("ia64_mca_init : platform-specific mca handling setup done\n"); #if defined(MCA_TEST) mca_test(); @@ -244,7 +368,7 @@ ia64_mca_wakeup_ipi_wait(void) void ia64_mca_wakeup(int cpu) { - ipi_send(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT); + ipi_send(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT, 0); ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; } @@ -396,25 +520,6 @@ ia64_mca_ucmc_handler(void) ia64_return_to_sal_check(); } -/* - * SAL to OS entry point for INIT on the monarch processor - * This has been defined for registration purposes with SAL - * as a part of mca_init. - */ -void -ia64_monarch_init_handler() -{ -} -/* - * SAL to OS entry point for INIT on the slave processor - * This has been defined for registration purposes with SAL - * as a part of mca_init. - */ - -void -ia64_slave_init_handler() -{ -} /* * ia64_mca_cmc_int_handler * This is correctable machine check interrupt handler. @@ -450,10 +555,9 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs) #define IA64_MAX_LOG_SUBTYPES 2 /* Processor, Platform */ typedef struct ia64_state_log_s { - spinlock_t isl_lock; - int isl_index; - sal_log_header_t isl_log[IA64_MAX_LOGS]; - + 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]; @@ -472,6 +576,53 @@ static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES][IA64_MAX_LOG_SUBTYPES #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 + * + */ + +void +ia64_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}) @@ -484,7 +635,7 @@ ia64_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(sal_log_header_t) * IA64_MAX_LOGS); + sizeof(ia64_psilog_t) * IA64_MAX_LOGS); } /* @@ -499,7 +650,7 @@ void ia64_log_get(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc) { sal_log_header_t *log_buffer; - int s; + int s,total_len=0; IA64_LOG_LOCK(sal_info_type, sal_sub_info_type); @@ -507,9 +658,11 @@ ia64_log_get(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc) /* Get the process state information */ log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type); - if (ia64_sal_get_state_info(sal_info_type, sal_sub_info_type ,(u64 *)log_buffer)) + 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); @@ -542,7 +695,7 @@ ia64_log_clear(int sal_info_type, int sal_sub_info_type, int clear_os_buffer, pr /* Get the process state information */ log_buffer = IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type); - memset(log_buffer, 0, sizeof(sal_log_header_t)); + memset(log_buffer, 0, sizeof(ia64_psilog_t)); IA64_LOG_INDEX_DEC(sal_info_type, sal_sub_info_type); @@ -731,11 +884,7 @@ ia64_log_processor_info_print(sal_log_header_t *lh, prfunc_t prfunc) if (lh->slh_log_type != SAL_SUB_INFO_TYPE_PROCESSOR) return; -#if defined(MCA_TEST) - slpi = &slpi_buf; -#else - slpi = (sal_log_processor_info_t *)lh->slh_log_dev_spec_info; -#endif /#if defined(MCA_TEST) */ + 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"); @@ -763,14 +912,6 @@ ia64_log_processor_info_print(sal_log_header_t *lh, prfunc_t prfunc) ia64_log_processor_regs_print(slpi->slpi_fr, 128, "Floating-point", "fr", prfunc); - /* Print bank1-gr NAT register contents if valid */ - ia64_log_processor_regs_print(&slpi->slpi_bank1_nat_bits, 1, "NAT", "nat", prfunc); - - /* Print bank 1 register contents if valid */ - if (slpi->slpi_valid.slpi_bank1_gr) - ia64_log_processor_regs_print(slpi->slpi_bank1_gr, 16, "Bank1-General", "gr", - prfunc); - /* Print the cache check information if any*/ for (i = 0 ; i < MAX_CACHE_ERRORS; i++) ia64_log_cache_check_info_print(i, |