📄 kn220.c
字号:
if (SHAREDPG(pa)) { kn220logmempkt(EL_PRISEVERE, ep,pa); kn220consprint(MEMPKT, ep, pa, 0); panic("memory read error in shared page"); } else { kn220logmempkt(EL_PRIHIGH, ep, pa); printf("pid %d (%s) was killed on memory read error\n", p->p_pid, u.u_comm); uprintf("pid %d (%s) was killed on memory read error\n", p->p_pid, u.u_comm); } } else { uprintf("pid %d (%s) was killed on bus read error\n", p->p_pid, u.u_comm); } } else { /* * Kernel mode errors. * They all panic, its just a matter of what we log * and what panic message we issue. */ switch (code) { case EXC_DBE: /* Data Bus Error */ case EXC_IBE: /* Instruction Bus Error */ /* * Figure out if its a memory parity error * or a read bus timeout error */ /* If the bits in the dser are set its a CQBIC * reported problem. */ if (isr & ISR_CERR) { kn220_qbus_memerr(ep); } else { /* A memory controller reported * problem. Trap is caused on multi bit errors * on read or bus timeouts. * Look for Multi bit ECC errors. If it is a multi bit error * bits (HME or LME) will be zero in the memory error syndrome * reister. */ if( (( esr[0].esr_mesr & KN220_LME ) == 0) || (( esr[0].esr_mesr & KN220_HME) == 0)) { /* Multi bit ECC error */ kn220logmempkt(EL_PRISEVERE, ep, pa); kn220consprint(MEMPKT, ep, pa, 0); panic("memory read error in kernel mode"); } /* To get here it was not a parity error * so it must have been a memory timeout. */ kn220logesrpkt(ep, esr, EL_PRISEVERE); kn220consprint(ESRPKT, ep, pa, 0); panic("read bus timeout"); } break; case EXC_CPU: /* CoProcessor Unusable */ kn220logesrpkt(ep, esr, EL_PRISEVERE); kn220consprint(ESRPKT, ep, 0, 0); panic("coprocessor unusable"); break; case EXC_RADE: /* Read Address Error */ case EXC_WADE: /* Write Address Error */ kn220logesrpkt(ep, esr, EL_PRISEVERE); kn220consprint(ESRPKT, ep, 0, 0); panic("unaligned access"); break; case SEXC_SEGV: /* This can be because we were in TLBMIS code * and to a SEGV. That causes us to get to this * routine with a SEXC_SEGV and I want a better * panic message than "trap". */ kn220logesrpkt(ep, esr, EL_PRISEVERE); kn220consprint(ESRPKT, ep, 0, 0); panic("segmentation violation"); break; default: kn220logesrpkt(ep, esr, EL_PRISEVERE); kn220consprint(ESRPKT, ep, 0, 0); panic("trap"); break; } } /* * Default user-mode action is to terminate the process */ *signo = SIGBUS; return(0);}#define KN220_LOG_ESRPKT(elrp, cause, epc, sr, badva, sp) \ elrp->el_body.elesr.elesr.el_esr5500.esr_cause = cause; \ elrp->el_body.elesr.elesr.el_esr5500.esr_epc = epc; \ elrp->el_body.elesr.elesr.el_esr5500.esr_status = sr; \ elrp->el_body.elesr.elesr.el_esr5500.esr_badva = badva; \ elrp->el_body.elesr.elesr.el_esr5500.esr_sp = sp; \/* * Copy the information from the error registers to the * the error log buffer area. */kn220copy_esrinfo(elrp, esrp)struct el_rec *elrp;struct esr *esrp; /* pointer to esrs */{ elrp->el_body.elesr.elesr.el_esr5500.esr_dser = esrp->esr_dser; elrp->el_body.elesr.elesr.el_esr5500.esr_qbear = esrp->esr_qbear; elrp->el_body.elesr.elesr.el_esr5500.esr_dear = esrp->esr_dear; elrp->el_body.elesr.elesr.el_esr5500.esr_cbtcr = esrp->esr_cbtcr; elrp->el_body.elesr.elesr.el_esr5500.esr_isr = esrp->esr_isr; elrp->el_body.elesr.elesr.el_esr5500.esr_mser = esrp->esr_mesr; elrp->el_body.elesr.elesr.el_esr5500.esr_mear = esrp->esr_mear; elrp->el_body.elesr.elesr.el_esr5500.esr_ipcr = esrp->esr_ipcr;}/* * Log Error & Status Registers to the error log buffer. */kn220logesrpkt(ep, ptr, priority)register u_int *ep; /* exception frame ptr */struct esr *ptr; /* pointer to esr */int priority; /* for pkt priority */{ struct el_rec *elrp; elrp = ealloc(sizeof(struct el_esr), priority); if (elrp != NULL) { LSUBID(elrp,ELCT_ESR,ELESR_5500,EL_UNDEF,EL_UNDEF,EL_UNDEF,EL_UNDEF); KN220_LOG_ESRPKT(elrp, ep[EF_CAUSE], ep[EF_EPC], ep[EF_SR], ep[EF_BADVADDR], ep[EF_SP]); kn220copy_esrinfo(elrp, ptr); EVALID(elrp); }}/* * kn220_log_errinfo: * Exported through the cpusw and used to log error information to * the error log buffer. */kn220_log_errinfo(p)struct kn220log_errinfo_t *p;{ struct el_rec *elrp; switch (p->pkt_type) { case ESRPKT: elrp = ealloc(sizeof(struct el_esr), EL_PRISEVERE); if (elrp != NULL) { LSUBID(elrp,ELCT_ESR,ELESR_5500,EL_UNDEF,EL_UNDEF,EL_UNDEF,EL_UNDEF); KN220_LOG_ESRPKT(elrp, p->cause, p->epc, p->sr, p->badvaddr, p->sp); kn220copy_esrinfo(elrp, (struct esr *) &(p->logesr)); EVALID(elrp); } break; default: cprintf("bad pkt type"); return; }} /* * Log a memory error packet, so uerf can find it as a main memory error. * Determine the type of memory error by reading MEMCSR16. * * Side effect: clear error bits in MEMCSR16. */kn220logmempkt(priority, ep, pa)int priority; /* pkt priority: panic: severe; else: high */register u_int *ep; /* exception frame ptr */int pa; /* physical addr where memory err occured */{ struct el_rec *elrp; register struct el_mem *mrp; int slot, sum_addr; /* compute which memory board the pa is on. * Walk through each of the four slots and find which slot the PA * is on. Memory_slot[slot] has the size of the memory board so * we loop through each until the pa boundry is found. */ slot=0; for(; slot < 4; slot++) { if(memory_slot[slot] != 0) { if((sum_addr + memory_slot[slot]) < pa) sum_addr = sum_addr + memory_slot[slot]; else { /* the sum of the address exceeds the pa so * we have found the board! */ break; } } else /* An empty slot so we have reached the end of memory * and can stop now. */ break; } slot++; /* because we want to start counting from 1 when we log it */ /* Allocate an error log packet. */ elrp = ealloc(EL_MEMSIZE, priority); if (elrp != NULL) { LSUBID(elrp,ELCT_MEM,EL_UNDEF,ELMCNTR_5500,EL_UNDEF,EL_UNDEF,EL_UNDEF); mrp = &elrp->el_body.elmem; mrp->elmem_cnt = 1; mrp->elmemerr.cntl = 1; mrp->elmemerr.numerr = 1; /* Check for MULTI bit errors in both the * High and Low ECC checks. Bits are zero * if an error was detected. * Address of location in error is in esr_mear */ if( ((esr[0].esr_mesr & KN220_HME) == 0) || ((esr[0].esr_mesr & KN220_LME) == 0)) mrp->elmemerr.type = ELMETYP_RDS; else /* Check for SINGLE bit errors in both the * High and Low ECC checks. Bits are zero * if an error was detected. * Address of location in error is in esr_mear */ if( ((esr[0].esr_mesr & KN220_HER) == 0) || ((esr[0].esr_mesr & KN220_LER) == 0)) mrp->elmemerr.type = ELMETYP_CRD; else /* Check for PARITY error */ if (esr[0].esr_dser & DSER_PARITY){ mrp->elmemerr.type = ELMETYP_PAR; } else /* Check if its a Non-existant memory access. */ if (esr[0].esr_dser & DSER_NXM){ mrp->elmemerr.type = ELMETYP_NXM; } else mrp->elmemerr.type = 0; mrp->elmemerr.regs[0] = esr[0].esr_mesr; mrp->elmemerr.regs[1] = pa; mrp->elmemerr.regs[2] = ep[EF_EPC]; mrp->elmemerr.regs[3] = ep[EF_BADVADDR]; mrp->elmemerr.regs[4] = slot; /* We are done...validate the error log packet. This puts * it back on the available list and closes the error log * task. */ EVALID(elrp); }}/* * Print error packet to the console. * This is only done when we are about to panic on the error. * Uses kn220_print_consinfo to do the actual printing. * */kn220consprint(pkt, ep, pa, qbus)int pkt; /* error pkt: Error & Stat Regs / memory pkt */register u_int *ep; /* exception frame ptr */unsigned pa; /* For MEMPKT: physical addr of error */ int qbus; /* 1 if pa is a qbus address, 0 otherwise */{ struct kn220consinfo_t p; p.pkt_type = pkt; p.pkt.cause = ep[EF_CAUSE]; p.pkt.epc = ep[EF_EPC]; p.pkt.sr = ep[EF_SR]; p.pkt.badvaddr = ep[EF_BADVADDR]; p.pkt.pa = pa; p.qbus = qbus; kn220_print_consinfo(&p);}/* * This routine is similar to kn220consprint(). * This is exported through the cpusw structure. * * N.B.: side-effect. * If console is a graphics device, printstate is changed * to force kernel printfs directly to the screen. */kn220_print_consinfo(p)struct kn220consinfo_t *p;{ /* * If console is a graphics device, * force printf messages directly to screen. * Note: DS_5500 currently does not support qdss, * but just in case... */ printstate |= PANICPRINT; switch (p->pkt_type) { case ESRPKT: cprintf("\nException condition\n"); break; case MEMPKT: cprintf("\nMemory Error\n"); break; default: cprintf("bad consprint\n"); return; } cprintf("\tCause reg\t= 0x%x\n", p->pkt.cause); cprintf("\tException PC\t= 0x%x\n", p->pkt.epc); cprintf("\tStatus reg\t= 0x%x\n", p->pkt.sr); cprintf("\tBad virt addr\t= 0x%x\n", p->pkt.badvaddr); if (p->pkt.pa) { if (p->qbus) { cprintf("\tQ22 Bus physical address of error: 0x%x\n", p->pkt.pa); } else { cprintf("\tPhysical address of error: 0x%x\n",p->pkt.pa); } } return;}/* * Log memory errors in kernel buffer * We get memory interupts for ECC errors on writes * but single bit errors; data is fixed which makes single bit errors * generated informational only. */kn220memerr(ep)register u_int *ep; /* exception frame ptr */{ register struct proc *p; /* ptr to current proc struct */ u_long dser; u_long pa; /* Physical address */ int isr; /* Content of ISR */ int i; /* counter for Single bit array scan */ struct kn220consinfo_t *pcons; /* pointer to console info */ struct kn220log_errinfo_t *plog; /* pointer to log info */ /* Read content of Interrupt Status Register */ isr = *(int *)ISR; /* * Log DMA system error register, error address register, ..etc. */ esr[0].esr_dser = * (u_long *)KN220DSER; /* DMA Sys error register*/ esr[0].esr_qbear = * (u_long *)KN220QBEAR; /* Qbus error addr reg. */ esr[0].esr_dear = * (u_long *)KN220DEAR; /* DMA error addr reg. */ esr[0].esr_cbtcr = * (u_long *)KN220CBTCR; /* CDAL Bus Timeout */ esr[0].esr_mesr = * (u_long *)KN220MESR; /* Memory Error Syndrom Reg.*/ esr[0].esr_mear = * (u_long *)KN220MEAR; /* Memory Error Address Reg.*/ esr[0].esr_isr = isr; /* Interupt Status Reg. */ /* Clear the error bits */ /* Compute the physical address. * pa that is load by the R3000 in the execption frame will * be the default address to use. */ pa = vatophys(ep[EF_BADVADDR]); /* If the problem was a memeory error problem the address will be * found in the MEAR register. * * Check the high two bit of the MEAR; if one and only one * of them is set the DESR is invalid but the MESR is valid. * Set the mesr to a valid value to stop us from processing * bad data. * * bit 28 & 29 value meanings * 00 memory space * 11 memory space * 01 I/O space * 10 I/O space * * Also, if bit 1 is set, the address in MEAR is valid. This bit is * needed by the hardware to indicate what kind of cycle it was * processing ... if the contents of the reg. is OK or not. */ if ((esr[0].esr_mear & GOOD_ADDR) == 0) /* DMA Cycle */ { pa = esr[0].esr_mear; if((esr[0].esr_mear & KN220_NXM) == 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -