📄 ka420.c
字号:
cache_state &= ~(CVAX_SEN2); /* * Set I & D stream for 2nd level * cache operation. */ mtpr (CADR, cache_state); printf("1st Level Cache Completely DISABLED by software on mchk\n"); cache_errcnt.cache_last = 0; time = 0; break; case SET_NONE: recover = 0; /* don't recover */ ka420consprint(2,type,mcf); printf("Got a 1st Level Cache Parity Error with the 1st Level Cache Disabled!\n"); break; default: cache_state = (CVAX_CEND | CVAX_CENI | CVAX_SEN1 | CVAX_SEN2); mtpr (CADR, cache_state); break; } } else { /* * Fewer than 3 errs in 1 time period, * reenable whichever cache sets were on. */ switch (cache_state & CADR_SETMASK) { case SET_BOTH: mtpr (CADR, cache_state); mprintf("1st Level Cache, Re-enabled by software on mchk\n"); break; case SET_ONE: mtpr (CADR, cache_state); mprintf("1st Level Cache, Set 1 Re-enabled, Set 2 left Disabled by software on mchk\n"); break; case SET_TWO: mtpr (CADR, cache_state); mprintf("1st Level Cache, Set 2 Re-enabled, Set 1 left Disabled by software on mchk\n"); break; case SET_NONE: recover = 0; /* don't recover */ ka420consprint(2,type,mcf); printf("Got a 1st Level Cache Parity Error with the 1st Level Cache Disabled!\n"); break; default: cache_state = (CVAX_CEND | CVAX_CENI | CVAX_SEN1 | CVAX_SEN2); mtpr (CADR, cache_state); mprintf("1st Level Cache, Re-enabled by software on mchk\n"); break; } } /* * Since we can recover update the times, */ cache_errcnt.cache_prev = cache_errcnt.cache_last; cache_errcnt.cache_last = time; } else { /* * Undefined Machine check 0x80, 0x81. * Log the mcheck & ESR Packet. * We can't recover so print errors on the console. * todo: if in user-mode only crash the user process. */ logmck((int *)cmcf, ELMCKT_CVAX, cpunum, recover); mprintf("No primary error flag - unspecified error type\n"); ka420logesrpkt(recover); ka420consprint(2,type,mcf); cprintf("No primary error flag - unspecified error type\n"); ka420consprint(3,0,0); } break; case 0x82: case 0x83: /* * Re-enable (after flushing) the 2nd level cache if cache * was enabled before we entered mcheck (to log it in the * state it was in when mcheck occured). */ if (cache2_state) { nb_regs->nb_cacr |= CACR_CPE; for (i=0; i<CVS_CACHE_SIZE; i++) cdp->nb_cvscache[i] = (u_long)0; nb_regs->nb_cacr |= CACR_CEN; } /* * We can't recover so print errors on the console. * Last, clear the error bits. */ logmck((int *)cmcf, ELMCKT_CVAX, cpunum, recover); ka420logesrpkt(recover); ka420consprint(2,type,mcf); ka420consprint(3,0,0); break; default: /* * Re-enable (after flushing) the 2nd level cache if cache * was enabled before we entered mcheck (this is so we * log it in the state it was in when mcheck occured). */ if (cache2_state) { nb_regs->nb_cacr |= CACR_CPE; for (i=0; i<CVS_CACHE_SIZE; i++) cdp->nb_cvscache[i] = (u_long)0; nb_regs->nb_cacr |= CACR_CEN; } /* * Unrecognized mcheck: these are non-recoverable. * Log the mcheck & ESR packet. * Also print to the console. */ logmck((int *)cmcf, ELMCKT_CVAX, cpunum, recover); ka420logesrpkt(recover); type = 0; ka420consprint(2,type,mcf); ka420consprint(3,0,0); break; } if (!recover) panic ("ka420 mchk"); ka420_mchkprog = 0; return(0);}/* * Get the Physical Addr where the memory parity error occured so we can log it. * * For mcheck 0x80, virtual (+4) is given in mcheck frame, convert to physical. * For mcheck 0x81, physical (+4) is given in mcheck frame. * * The macro to determine if an address is in system space may appear in * vmmac.h in a future version of ULTRIX. */#define SYSADDR(v) (v & 0x80000000)ka420getpa(mcf, type) register struct mcCVAXSTARframe *mcf; int type;{ struct pte *pte; /* PTE ptr to obtain physical addr */ int pa; /* the physical address where mem err occured */ if (type == 0x80) { if (SYSADDR (mcf->mc1_vap -4)) { pte = &(Sysmap[btop((int)(mcf->mc1_vap -4) & ~VA_SYS)]); } else { /* * user space address */ pte = vtopte(u.u_procp, btop(mcf->mc1_vap -4)); } /* * Validity check the pte before picking up the page address */ if ((!SYSADDR((int)pte)) || (!pte->pg_v)) pa = -1; else pa = (int)ptob(pte->pg_pfnum); } else pa = mcf->mc1_vap -4; return (pa);}/* * Log 2nd level cache tag parity error. * Log packet 3 (error status registers). * * Traps through SCB vector 54: correctable memory errors. * * These errors are recoverable. */ka420crderr(){ register struct nb_regs *nb_regs = (struct nb_regs *)nexus; register struct nb6_regs *cdp = (struct nb6_regs *)cvscachemem; register int i; int recover; /* set to 1 if we can recover from this error */ u_int time; recover = 0; time = ka420readtodr(); if (nb_regs->nb_cacr & CACR_CPE) { /* * Cache Tag Parity error (Cache automatically disabled): * Will cause a cache miss so a memory read will be done * after we REI from the interrupt. * Action depends on prior 2nd level cache state: * was on: Recover * was off: Panic */ if (cache2_state) { /* * Second Level Cache was on: * Action depends on number of errors: * 3 within 1 time period: Leave Cache disabled * < 3 within 1 time period: Flush Cache & re-enable */ mprintf("Tag parity interrupt: 2nd level cache tag parity\n"); recover = 1; if (time - tag_errcnt.tag_prev <= TIME_THRESH_C2) { /* * Cache was on, 3 errs in 1 time period */ printf("2nd Level Cache DISABLED by software on tag parity\n"); ka420logesrpkt(recover); nb_regs->nb_cacr |= CACR_CPE; cache2_state = 0; tag_errcnt.tag_last = 0; time = 0; } else { /* * Cache was on, < 3 errs in 1 time period * Flush and re-enable cache */ ka420logesrpkt(recover); nb_regs->nb_cacr |= CACR_CPE; for (i=0; i<CVS_CACHE_SIZE; i++) cdp->nb_cvscache[i] = (u_long)0; nb_regs->nb_cacr |= CACR_CEN; mprintf("2nd Level Cache re-enabled by software\n"); } tag_errcnt.tag_prev = tag_errcnt.tag_last; tag_errcnt.tag_last = time; } else { /* * Cache was off: no recover. * NOTE: consprint() sets up display for cprintf here! */ ka420logesrpkt(recover); ka420consprint(3,0,0); printf("2nd Level Cache Tag Parity Error occured with Cache Disabled!\n"); nb_regs->nb_cacr |= CACR_CPE; panic("ka420 Cache Tag Parity error"); } } else { /* * Catch-all: vector 54 interrupt without CACR-CPE bit set. * Dismiss the error and REI. */ mprintf("Tag parity interrupt without tag parity bit\n"); } return(0);}/* * Print error packet to the console. * This is only done when we are about to panic on the error. * * Note: side-effect. * If console is a graphics device, ioctl is done to force kernel printfs * directly to the screen. */ka420consprint(pkt, type, mcf) int pkt; /* error pkt desired: 2 = mcheck frame 3 = error status registers 4 = memory error packet */ int type; /* machine check type */ register struct mcCVAXSTARframe *mcf; /* mcheck frame pointer */{ register struct nb_regs *nb_regs = (struct nb_regs *)nexus; register int i; int ws_disp; /* * If console is a graphics device, * force printf messages directly to screen. */ if (ws_display_type) { ws_disp = ws_display_type << 8; (*cdevsw[ws_display_type].d_ioctl)(ws_disp, QD_KERN_UNLOOP, 0, 0); } switch (pkt) { case 2: cprintf("\nmachine check %x: ", type); /* * Types are disjoint. Have to convert some to linear range. */ if (type >= 0x80) type = type - 0x80 + MCcVAXSTARDISJ; cprintf("%s\n", mcCVAXSTAR[type]); cprintf("\tcode\t= %x\n", mcf->mc1_summary); cprintf("\tmost recent virtual addr\t=%x\n", mcf->mc1_vap); cprintf("\tinternal state 1\t=%x\n", mcf->mc1_internal_state1); cprintf("\tinternal state 2\t=%x\n", mcf->mc1_internal_state2); cprintf("\tpc\t= %x\n", mcf->mc1_pc); cprintf("\tpsl\t= %x\n\n", mcf->mc1_psl); break; case 3: cprintf("\tcacr\t= %x\n", nb_regs->nb_cacr); cprintf("\tcadr\t= %x\n", mfpr(CADR)); cprintf("\tmser\t= %x\n", mfpr(MSER)); break; case 4: cprintf("\tcacr\t= %x\n", nb_regs->nb_cacr); cprintf("\tcadr\t= %x\n", mfpr(CADR)); cprintf("\tmser\t= %x\n", mfpr(MSER)); cprintf("\tphys addr\t= 0x%x\n", ka420getpa(mcf, type)); break; default: cprintf("bogus ka420consprint\n"); break; }}/* * Log Error & Status Registers */ka420logesrpkt(priority) int priority; /* for pkt priority */{ struct el_rec *elrp; register struct nb_regs *nb_regs = (struct nb_regs *)nexus; switch (priority) { case 0: /* non-recoverable mchecks */ priority = EL_PRISEVERE; break; case 1: /* recoverable mchecks */ priority = EL_PRIHIGH; break; case 2: /* recoverable CRDs (cache tag parity errors) */ priority = EL_PRILOW; break; } elrp = ealloc(sizeof(struct el_esr420), priority); if (elrp != NULL) { LSUBID(elrp,ELCT_ESR420,EL_UNDEF,EL_UNDEF,EL_UNDEF,EL_UNDEF,EL_UNDEF); elrp->el_body.elesr420.esr_cacr = nb_regs->nb_cacr; elrp->el_body.elesr420.esr_cadr = mfpr(CADR); elrp->el_body.elesr420.esr_mser = mfpr(MSER); EVALID(elrp); }}/* * Log Error & Status Registers (and physical address where error occured) * as a memory error packet, so uerf can find it as a main memory error. */ka420logmempkt(recover, pa) int recover; /* for pkt priority */ int pa; /* physical addr where memory err occured */{ struct el_rec *elrp; register struct el_mem *mrp; elrp = ealloc(EL_MEMSIZE,recover ? EL_PRIHIGH : EL_PRISEVERE); if (elrp != NULL) { LSUBID(elrp,ELCT_MEM,EL_UNDEF,ELMCNTR_420,EL_UNDEF,EL_UNDEF,EL_UNDEF); mrp = &elrp->el_body.elmem; mrp->elmem_cnt = 1; mrp->elmemerr.cntl = 1; mrp->elmemerr.type = ELMETYP_PAR; mrp->elmemerr.numerr = 1; mrp->elmemerr.regs[0] = ((struct nb_regs *)nexus)->nb_cacr; mrp->elmemerr.regs[1] = mfpr(CADR); mrp->elmemerr.regs[2] = mfpr(MSER) ; mrp->elmemerr.regs[3] = pa; EVALID(elrp); }}ka420readtodr(){ u_int s,todr; struct tm tm; register struct nb_regs *nb_regs = (struct nb_regs *)nexus; /* * All CVAXstar toy clock registers (including NVR) * read/write bits 2 - 9 instead of 0 - 7. */ /* * Copy the toy register contents into tm so that we can * work with. The toy must be completely read in 2.5 millisecs. * * * Wait for update in progress to be done. */ while( nb_regs->nb_toycsra & (QBT_UIP << 2) ) ; s = spl7(); tm.tm_sec = ((nb_regs->nb_toysecs >> 2) & 0xff); tm.tm_min = ((nb_regs->nb_toymins >> 2) & 0xff); tm.tm_hour = ((nb_regs->nb_toyhours >> 2) & 0xff); tm.tm_mday = ((nb_regs->nb_toyday >> 2) & 0xff); tm.tm_mon = ((nb_regs->nb_toymonth >> 2) & 0xff); tm.tm_year = ((nb_regs->nb_toyyear >> 2) & 0xff); splx( s ); todr = toyread_convert(tm); return(todr);}ka420writetodr(yrtime)u_int yrtime;{ struct tm xtime; int s; register struct nb_regs *nb_regs = (struct nb_regs *)nexus; toywrite_convert(&xtime,yrtime); nb_regs->nb_toycsrb = (QBT_SETUP << 2); s = spl7(); nb_regs->nb_toysecs = (xtime.tm_sec << 2); nb_regs->nb_toymins = (xtime.tm_min << 2); nb_regs->nb_toyhours = (xtime.tm_hour << 2); nb_regs->nb_toyday = (xtime.tm_mday << 2); nb_regs->nb_toymonth = (xtime.tm_mon << 2); nb_regs->nb_toyyear = (xtime.tm_year << 2); /* * Start the clock again. */ nb_regs->nb_toycsra = (QBT_SETA << 2); nb_regs->nb_toycsrb = (QBT_SETB << 2); splx( s );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -