/* * machine check handler. */ void s390_do_machine_check(void) { struct mci *mci; mci = (struct mci *) &S390_lowcore.mcck_interruption_code; if (mci->sd) /* system damage */ s390_handle_damage("received system damage machine check\n"); if (mci->pd) /* instruction processing damage */ s390_handle_damage("received instruction processing " "damage machine check\n"); if (mci->se) /* storage error uncorrected */ s390_handle_damage("received storage error uncorrected " "machine check\n"); if (mci->sc) /* storage error corrected */ printk(KERN_WARNING "received storage error corrected machine check\n"); if (mci->ke) /* storage key-error uncorrected */ s390_handle_damage("received storage key-error uncorrected " "machine check\n"); if (mci->ds && mci->fa) /* storage degradation */ s390_handle_damage("received storage degradation machine " "check\n"); if (mci->cp) /* channel report word pending */ up(&m_sem); #ifdef CONFIG_MACHCHK_WARNING /* * The warning may remain for a prolonged period on the bare iron. * (actually till the machine is powered off, or until the problem is gone) * So we just stop listening for the WARNING MCH and prevent continuously * being interrupted. One caveat is however, that we must do this per * processor and cannot use the smp version of ctl_clear_bit(). * On VM we only get one interrupt per virtally presented machinecheck. * Though one suffices, we may get one interrupt per (virtual) processor. */ if (mci->w) { /* WARNING pending ? */ static int mchchk_wng_posted = 0; /* * Use single machine clear, as we cannot handle smp right now */ __ctl_clear_bit(14, 24); /* Disable WARNING MCH */ if (xchg(&mchchk_wng_posted, 1) == 0) kill_proc(1, SIGPWR, 1); } #endif }
/* * s390_do_machine_check * * mchine check pre-processor, collecting the machine check info, * queueing it and posting the machine check handler for processing. */ void s390_do_machine_check( void ) { int crw_count; mcic_t mcic; trapid_t ltt_interruption_code; uint32_t ltt_old_psw; #ifdef S390_MACHCHK_DEBUG printk( KERN_INFO "s390_do_machine_check : starting ...\n"); #endif memcpy( &mcic, &S390_lowcore.mcck_interruption_code, sizeof(__u64)); memcpy( <t_interruption_code, &S390_lowcore.mcck_interruption_code, sizeof(__u64)); memcpy( <t_old_psw, &S390_lowcore.mcck_old_psw, sizeof(uint32_t)); ltt_old_psw &= PSW_ADDR_MASK; TRACE_TRAP_ENTRY(ltt_interruption_code,ltt_old_psw); if (mcic.mcc.mcd.sd) /* system damage */ s390_handle_damage("received system damage machine check\n"); if (mcic.mcc.mcd.pd) /* instruction processing damage */ s390_handle_damage("received instruction processing damage machine check\n"); if (mcic.mcc.mcd.se) /* storage error uncorrected */ s390_handle_damage("received storage error uncorrected machine check\n"); if (mcic.mcc.mcd.sc) /* storage error corrected */ printk(KERN_WARNING "received storage error corrected machine check\n"); if (mcic.mcc.mcd.ke) /* storage key-error uncorrected */ s390_handle_damage("received storage key-error uncorrected machine check\n"); if (mcic.mcc.mcd.ds && mcic.mcc.mcd.fa) /* storage degradation */ s390_handle_damage("received storage degradation machine check\n"); if ( mcic.mcc.mcd.cp ) // CRW pending ? { crw_count = s390_collect_crw_info(); if ( crw_count ) { up( &s_sem ); } /* endif */ } /* endif */ #ifdef CONFIG_MACHCHK_WARNING /* * The warning may remain for a prolonged period on the bare iron. * (actually till the machine is powered off, or until the problem is gone) * So we just stop listening for the WARNING MCH and prevent continuously * being interrupted. One caveat is however, that we must do this per * processor and cannot use the smp version of ctl_clear_bit(). * On VM we only get one interrupt per virtally presented machinecheck. * Though one suffices, we may get one interrupt per (virtual) processor. */ if ( mcic.mcc.mcd.w ) // WARNING pending ? { // Use single machine clear, as we cannot handle smp right now __ctl_clear_bit( 14, 24 ); // Disable WARNING MCH if ( ! mchchk_wng_posted ) { mchchk_wng_posted = s390_post_warning(); if ( mchchk_wng_posted ) { up( &s_sem ); } /* endif */ } /* endif */ } /* endif */ #endif #ifdef S390_MACHCHK_DEBUG printk( KERN_INFO "s390_do_machine_check : done \n"); #endif return; }