📄 ka420.c
字号:
continue; } printf("vec 0x%x, ipl 0x%x\n", cvec, br); ui->ui_hd = &uba_hd[numuba]; for (ivec=ui->ui_intr; *ivec; ivec++) { ui->ui_hd->uh_vec[cvec/4] = scbentry(*ivec, SCB_ISTACK); cvec += 4; } ui->ui_alive = 1; ui->ui_addr = (caddr_t)addr; ui->ui_physaddr = 0; ui->ui_dk = -1; udp->ud_dinfo[ui->ui_unit] = ui; (*udp->ud_attach)(ui); } /* * Configure remaining CVAXstar/PVAX devices, no others. */ config_set_alive("ibus", 0); for (ui=ubdinit; udp=ui->ui_driver; ui++) { if (udp == &lndriver && ui->ui_unit==0) addr = (caddr_t) 0x200e0000; else continue; /* * Following should never happen on a CVAXstar. */ if (ui->ui_ubanum != -1 || ui->ui_alive || ui->ui_slave != -1) continue; cvec = 0x200; i = (*udp->ud_probe)(addr); if(i == 0) continue; ui->ui_adpt = 0; config_fillin(ui); printf(" csr 0x%x ", addr); if (cvec == 0) { printf("zero vector\n"); continue; } if (cvec == 0x200) { printf("didn't interrupt\n"); continue; } printf("vec 0x%x, ipl 0x%x\n", cvec, br); ui->ui_hd = &uba_hd[numuba]; for (ivec=ui->ui_intr; *ivec; ivec++) { ui->ui_hd->uh_vec[cvec/4] = scbentry(*ivec, SCB_ISTACK); cvec += 4; } ui->ui_alive = 1; ui->ui_addr = (caddr_t)addr; ui->ui_physaddr = 0; ui->ui_dk = -1; udp->ud_dinfo[ui->ui_unit] = ui; (*udp->ud_attach)(ui); } /* * Set parity control register DPEN and CPEN bits * and clear DMA bit. This enables CPU and DMA parity * checking and selects the lo address (0 - 16MB) for * LANCE chip DMA transfers. */ ((struct nb_regs *)nexus)->nb_par_ctl = PAR_CTL_CPEN | PAR_CTL_DPEN; /* * Tell the console program that we've booted and * that we would like to restart if the machine panics. */ ((struct nb_regs *)nexus)->nb_cpmbx=RB_VS_RESTART; return(0);}/* * Bits in CACR: Cache Control Register (2nd level cache) (cvqcb->cvq2_cacr) */#define CACR_CEN 0x00000010 /* <4> Cache enable */#define CACR_CPE 0x00000020 /* <5> Cache Parity Error */ /* NOTE: VS3100 spec calls this TPE *//* * Bits in MSER: Memory System Error Register (IPR 39 or 0x27) */#define MSER_DAL 0x00000040 /* <6> DAL or 2nd level cache data store parity */#define MSER_MCD 0x00000020 /* <5> mcheck due to DAL parity error */#define MSER_MCC 0x00000010 /* <4> mcheck due to 1st lev cache parity */#define MSER_DAT 0x00000002 /* <1> data parity in 1st level cache */#define MSER_TAG 0x00000001 /* <0> tag parity in 1st level cache *//* * Bits in CADR: Cache Disable Register (IPR 37) */#define CADR_STMASK 0xF0 /* 1st level cache state mask */#define CVAX_SEN2 0x00000080 /* <7> 1st level cache set 2 enabled */#define CVAX_SEN1 0x00000040 /* <6> 1st level cache set 1 enabled */#define CVAX_CENI 0x00000020 /* <5> 1st level I-stream caching enabled */#define CVAX_CEND 0x00000010 /* <4> 1st level D-stream caching enabled *//* * Bits in PSL: Processor Status Longword (for mcheck recovery) */#define PSL_FPD 0x08000000 /* <27> First Part Done flag *//* * Bits in Internal Status Info 2: (for mcheck recovery) */#define IS2_VCR 0x00008000 /* <15> VAX Can't Restart flag *//* * This routine sets the cache to the state passed: enabled/disabled. * The CVAX chip has a first level cache enabled through IPR CADR. * The KA420 processor has a second level cache enabled through * local register CACR. * Also set state flags in the error count structures. *//* * This variable defines the state of the * 1st and 2nd level caches, i.e., bit 0 is set * if 1st level cache is on and bit 1 is set if * 2nd level cache is on. The normal state is * both caches on (cvs_cache_on = 3). */extern int cvs_cache_on;ka420setcache(state)int state;{ register int i; register struct nb6_regs *cdp = (struct nb6_regs *)cvscachemem; /* * Enable 1st level cache. * Write to CADR flushes 1st level cache (if DIA bit = 0). */ mtpr (CADR, state); if (cvs_cache_on & 2) { /* * Flush 2nd level cache before enabling. */ ((struct nb_regs *)nexus)->nb_cacr = CACR_CPE; for (i=0; i<CVS_CACHE_SIZE; i++) cdp->nb_cvscache[i] = (u_long)0; ((struct nb_regs *)nexus)->nb_cacr |= CACR_CEN; cache2_state = 1; } return(0);}/* * Enable cache. Both D_stream & I-stream, both Set-1 and Set-2. * These bits are in the IPR CADR for the CVAX chip. * * The variable cvs_cache_on defines the state of the * 1st and 2nd level caches, i.e., bit 0 is set * if 1st level cache is on and bit 1 is set if * 2nd level cache is on. The normal state is * both caches on (cvs_cache_on = 3). */extern int cache_state;ka420cachenbl(){ if (cvs_cache_on & 1) cache_state = (CVAX_CEND | CVAX_CENI | CVAX_SEN1 | CVAX_SEN2); else cache_state = (CVAX_CEND | CVAX_CENI); return(0);}/* * CVAXstar has no console register to write to, * but routine is called from machdep and locore, * and the system will panic if no tocons routine. */ka420tocons(c) register int c;{ return(0);}short *ka420nexaddr(ioadpt,nexnum) int nexnum,ioadpt;{ return(NEXUVII);}char *ka420umaddr(ioadpt,nexnum) int ioadpt,nexnum;{ return(QMEMVAXSTAR);}/* * Machine check handler. * Called from locore thru the cpu switch in response to a trap at SCB 4 * We recover from any that we can if hardware "retry" is possible. */ka420machcheck (cmcf)caddr_t cmcf;{ register struct nb_regs *nb_regs; register struct nb6_regs *cdp; /* ptr to 2nd level cache diag space */ register int i; /* counter for cache clearing code */ register struct mcCVAXSTARframe *mcf; register int recover; /* set to 1 if error is recoverable */ register u_int time; /* from TODR */ u_int type; /* machine check type */ int cpunum; /* 0 for uniprocessor */ int retry; /* set to 1 if hardware can retry the instr */ int ws_disp; /* type of work station display for ioctl */ /* * Disable 2nd level cache to protect execution of machine check code. * NOTE: Do NOT put any executable code in this routine before * disabling the cache, the cache may be what caused the mcheck. */ nb_regs = (struct nb_regs *)nexus; nb_regs->nb_cacr &= ~CACR_CEN; /* * Set up pointer needed to clear 2nd level cache data storage. */ cdp = (struct nb6_regs *)cvscachemem; /* * Do not allow recursive machine check. * Halt the processor, then a restart should get a dump. */ if (ka420_mchkprog == 0) ka420_mchkprog = 1; else asm("halt"); type = ((struct mcframe *) cmcf)->mc_summary; mcf = (struct mcCVAXSTARframe *) cmcf; recover = 0; cpunum = 0; retry = 0; /* * First note the time; then switch on machine check type. */ time = ka420readtodr(); switch (type) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: if (((mcf->mc1_psl & PSL_FPD) == 0) && ((mcf->mc1_internal_state2 & IS2_VCR) == 0)) retry = 1; /* * CFPA errors (1-4) and memory management errors (5-8). * Re-enable 2nd level cache to log in correct state. * If fewer than 3 errors in 1 time period, try to recover * else we will crash. * todo: if in user-mode only crash the user process. */ 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; } if (time - cfpa_errcnt.cfpa_prev > TIME_THRESH) { if (retry) recover = 1; } logmck((int *)cmcf, ELMCKT_CVAX, cpunum, recover); if (recover) { cfpa_errcnt.cfpa_prev = cfpa_errcnt.cfpa_last; cfpa_errcnt.cfpa_last = time; } else { ka420consprint(2,type,mcf); } break; case 9: case 10: /* * These are non-recoverable: * Re-enable 2nd level cache to log in correct state. * Log the mcheck & print mcheck frame to console. * todo: if in user-mode only crash the process. */ 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; } logmck((int *)cmcf, ELMCKT_CVAX, cpunum, recover); ka420consprint(2,type,mcf); break; case 0x80: case 0x81: if (((mcf->mc1_psl & PSL_FPD) != 0) || (((mcf->mc1_psl & PSL_FPD) == 0) && ((mcf->mc1_internal_state2 & IS2_VCR) == 0))) retry = 1; /* * There are several possible causes for this mcheck. * First re-enable the 2nd level cache if its not * a cache error and the cache was enabled before * we entered mcheck (for recovery and so we log it * in the state it was in when mcheck occured). * Check for which error caused the mcheck and take * appropriate action. */ if (((mfpr(MSER) & MSER_MCD) == 0) && 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; } if ((mfpr(MSER) & MSER_MCD) != 0) { /* * DAL Bus Parity Err/2nd Level Cache Data Parity Err. * Determine if its main memory or 2nd level cache * by counting the frequency of errors. If we get 3 * in the time-out period (even after flushing the * cache) then we assume its main memory. */ if (time - dal_errcnt.dal_prev <= TIME_THRESH_C2) { /* * Got 3 errors within 1 time period. * This must be a real parity memory error (not * cache), so crash the process or the system. * todo: if in user-mode only crash the user process. * todo: map out the bad page. */ dal_errcnt.dal_last = 0; time = 0; recover = 0; } else { /* * Got fewer than 3 errors within 1 time period. * This may be a second level cache error, so * flush/re-enable the cache & count the errors. * todo: if we can't retry the instruction * if in usermode only crash user process. */ 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 on mcheck\n"); if (retry) recover = 1; } /* * Log the machine check, and the error status regs. * If we can recover update the times, * else print errors on the console. * Note: if we can't recover log it as a memory error. * Last, clear the error bits. */ logmck((int *)cmcf, ELMCKT_CVAX, cpunum, recover); if (recover) { ka420logesrpkt(recover); dal_errcnt.dal_prev = dal_errcnt.dal_last; dal_errcnt.dal_last = time; } else { ka420logmempkt(recover, ka420getpa(mcf, type)); ka420consprint(2,type,mcf); ka420consprint(4,type,mcf); } mtpr(MSER,1); } else if ((mfpr(MSER) & MSER_MCC) != 0) { /* * 1st Level Cache Parity Err (CPU disables & flushes). * If recovery is possible, do so, else log and quit. */ if (retry) { recover = 1; logmck((int *)cmcf, ELMCKT_CVAX, cpunum, recover); mtpr(MSER,1); } else { /* todo: if in user-mode only crash the user process. */ logmck((int *)cmcf, ELMCKT_CVAX, cpunum, recover); ka420consprint(2,type,mcf); mtpr(MSER,1); break; /* out of switch */ } /* * Recovery procedures: */ if (time - cache_errcnt.cache_prev <= TIME_THRESH_C1) { /* * Got 3 errors within 1 time period. * Action depends on prior state of 1st level cache: * Reenable whichever cache sets were NOT on. * And reset the timers to require 3 * errs/time period with the new cache setting. */ switch (cache_state & CADR_SETMASK) { case SET_BOTH: cache_state &= ~(CVAX_SEN2); mtpr (CADR, cache_state); printf("1st Level Cache, Set 2 DISABLED, Set 1 Enabled by software on mchk\n"); cache_errcnt.cache_last = 0; time = 0; break; case SET_ONE: cache_state |= (CVAX_SEN2); cache_state &= ~(CVAX_SEN1); mtpr (CADR, cache_state); printf("1st Level Cache, Set 1 DISABLED, Set 2 Enabled by software on mchk\n"); cache_errcnt.cache_last = 0; time = 0; break; case SET_TWO:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -