📄 kn210.c
字号:
*/kn210harderrintr(ep)int *ep;{int isr; /* Content of ISR */u_long pa; /* Physical address */u_long dser; isr = *(int *)ISR; /* Read content of ISR */ /* * Log DMA system error register, error address register, ..etc. */ esr[0].esr_wear = * (u_long *)KN210WEAR; esr[0].esr_dser = * (u_long *)KN210DSER; esr[0].esr_qbear = * (u_long *)KN210QBEAR; esr[0].esr_dear = * (u_long *)KN210DEAR; esr[0].esr_cbtcr = * (u_long *)KN210CBTCR; esr[0].esr_isr = isr; /* Clear the error bits */ *(u_long *)KN210DSER = 0xc0bd; *(u_long *)KN210CBTCR = 0xc0000000 | esr[0].esr_cbtcr; *(int *)ISR = 0; /* Acknowledge all error interrupts */ if (isr & ISR_WEAR) { /* Write error interrupt */ /* physical address is in WEAR */ pa = esr[0].esr_wear; if (btop((int)pa) < physmem) { /* was writing to main memory */ kn210logmempkt(EL_PRISEVERE, ep, pa); kn210consprint(MEMPKT, ep, pa, 0); panic("Memory write error"); } else { kn210logesrpkt(ep, esr, EL_PRISEVERE); kn210consprint(ESRPKT, ep, pa, 0); panic("Bus write error"); } } if (isr & ISR_CERR) { /* CQBIC or CMCTL error interrupt */ /* compute physical address */ dser = esr[0].esr_dser; if (dser & 0xa0) { /* * Q22 bus write cycle timeout after 10uS, * or Q22 bus parity error. * QBEAR contains Qbus physical address. */ pa = esr[0].esr_qbear << 9; kn210logesrpkt(ep, esr, EL_PRISEVERE); kn210consprint(ESRPKT, ep, pa, 1); panic("Q22 bus error"); } else if (dser & 0x11) { /* * DMA transfer to non-existent main memory location, * or main memory error. * DEAR contains physical address. */ pa = esr[0].esr_dear << 9; /* was writing to main memory */ kn210logmempkt(EL_PRISEVERE, ep, pa); kn210consprint(MEMPKT, ep, pa, 0); panic("Memory error"); } } if (isr & ISR_PWF) { /* Powerfail interrupt */ powerfail_intr(ep); }}/* * Pending powerfail, currently ULTRIX has no handling * strategy on VAX and MIPS. Further, there is no restart * parameter block on MIPS. * */powerfail_intr(ep)int *ep;{ printf("Power fail..\n"); DELAY(1000000); /* Delay 1 second, if we are still alive, continue */}/* * Interrupts from Qbus level 7 or 10mS clock. Level 7 is reserved for * Qbus real-time devices. Currently not used in ULTRIX. */kn210hardintr2(ep)int *ep;{extern int (*(scb[]))();register int vrr; vrr = read_nofault(VRR3); /* Read interrupt vector */ /* 0 = passive release */ vrr &= 0xffff; (*(scb[vrr/4]))(ep,vrr); /* Call the interrupt handler */}/* * Interrupts from NI, DSSI, or Qbus level 6. */kn210hardintr1(ep)int *ep;{extern int (*(scb[]))();register int vrr; vrr = read_nofault(VRR2); /* Read interrupt vector */ /* 0 = passive release */ vrr &= 0xffff; (*(scb[vrr/4]))(ep,vrr); /* Call the interrupt handler */}/* * Interrupts from the Qbus level 5 and 4, * and from the SSC chip (programmable timers, console). * * VRR0 contains vector for Qbus level 4 & 5, don't read VRR1 for * reason I don't understand. */kn210hardintr0(ep)int *ep;{extern int (*(scb[]))();register int vrr; vrr = read_nofault(VRR0); /* Read interrupt vector */ /* 0 = passive release */ vrr &= 0xffff; (*(scb[vrr/4]))(ep,vrr); /* Call the interrupt handler */}/* * Routine to handle trap errors: user-mode ibe & dbe, & all kernel mode traps. * We try to recover from user-mode errors and panic on kernel mode errors. */kn210trap_error(ep, code, sr, cause, signo)register u_int *ep; /* exception frame ptr */register u_int code; /* trap code (trap type) */u_int sr, cause; /* status and cause regs */int *signo; /* set if we want to kill process */{ caddr_t pa; /* the physical addr of the error */ int epc; /* the EPC of the error */ int pagetype; /* type of page */ int vaddr; /* virt addr of error */ register struct proc *p; /* ptr to current proc struct */ /* * Log DMA system error register, error address register, ..etc. */ esr[0].esr_wear = * (u_long *)KN210WEAR; esr[0].esr_dser = * (u_long *)KN210DSER; esr[0].esr_qbear = * (u_long *)KN210QBEAR; esr[0].esr_dear = * (u_long *)KN210DEAR; esr[0].esr_cbtcr = * (u_long *)KN210CBTCR; /* Clear the error bits */ *(u_long *)KN210DSER = 0xc0bd; *(u_long *)KN210CBTCR = 0xc0000000 | esr[0].esr_cbtcr; p = u.u_procp; if (USERMODE(sr)) { /* * It is a memory read error: * a) on a private process page, terminate the process * (by setting signo = SIGBUS) * b) on a shared page, crash the system. * TBD: on a non-modified page, re-read the page (page fault), * and continue the process. * TBD: on a shared page terminate all proc's sharing the page, * instead of crash system. * TBD: on hard errors map out the page. */ pa = (caddr_t)vatophys(ep[EF_BADVADDR]); if ( (int)pa != -1 && (btop((int)pa) < physmem) ) { pagetype = cmap[pgtocm(btop(pa))].c_type; if (SHAREDPG(pagetype)) { kn210logmempkt(EL_PRISEVERE, ep,pa); kn210consprint(MEMPKT, ep, pa, 0); panic("memory read error in shared page"); } else { kn210logmempkt(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: case EXC_IBE: /* * Figure out if its a memory parity error * or a read bus timeout error */ pa = (caddr_t)vatophys(ep[EF_BADVADDR]); if ( (int)pa != -1 && (btop((int)pa) < physmem) ) { kn210logmempkt(EL_PRISEVERE, ep, pa); kn210consprint(MEMPKT, ep, pa, 0); panic("memory read error in kernel mode"); } else { kn210logesrpkt(ep, esr, EL_PRISEVERE); kn210consprint(ESRPKT, ep, 0, 0); panic("read bus timeout"); } break; case EXC_CPU: kn210logesrpkt(ep, esr, EL_PRISEVERE); kn210consprint(ESRPKT, ep, 0, 0); panic("coprocessor unusable"); break; case EXC_RADE: case EXC_WADE: kn210logesrpkt(ep, esr, EL_PRISEVERE); kn210consprint(ESRPKT, ep, 0, 0); panic("unaligned access"); break; default: kn210logesrpkt(ep, esr, EL_PRISEVERE); kn210consprint(ESRPKT, ep, 0, 0); panic("trap"); break; } } /* * Default user-mode action is to terminate the process */ *signo = SIGBUS; return(0);}/* * Log Error & Status Registers to the error log buffer. */kn210logesrpkt(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_5400,EL_UNDEF,EL_UNDEF,EL_UNDEF,EL_UNDEF); elrp->el_body.elesr.elesr.el_esr5400.esr_cause = ep[EF_CAUSE]; elrp->el_body.elesr.elesr.el_esr5400.esr_epc = ep[EF_EPC]; elrp->el_body.elesr.elesr.el_esr5400.esr_status = ep[EF_SR]; elrp->el_body.elesr.elesr.el_esr5400.esr_badva = ep[EF_BADVADDR]; elrp->el_body.elesr.elesr.el_esr5400.esr_sp = ep[EF_SP]; elrp->el_body.elesr.elesr.el_esr5400.esr_wear = ptr->esr_wear; elrp->el_body.elesr.elesr.el_esr5400.esr_dser = ptr->esr_dser; elrp->el_body.elesr.elesr.el_esr5400.esr_qbear = ptr->esr_qbear; elrp->el_body.elesr.elesr.el_esr5400.esr_dear = ptr->esr_dear; elrp->el_body.elesr.elesr.el_esr5400.esr_cbtcr = ptr->esr_cbtcr; elrp->el_body.elesr.elesr.el_esr5400.esr_isr = ptr->esr_isr; EVALID(elrp); }}/* * 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. */kn210logmempkt(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; struct memcsr *memcsrptr = (struct memcsr *)MEMCSR;/* Pointer to memory csr */ elrp = ealloc(EL_MEMSIZE, priority); if (elrp != NULL) { LSUBID(elrp,ELCT_MEM,EL_UNDEF,ELMCNTR_5400,EL_UNDEF,EL_UNDEF,EL_UNDEF); mrp = &elrp->el_body.elmem; mrp->elmem_cnt = 1; mrp->elmemerr.cntl = 1; mrp->elmemerr.numerr = 1; mrp->elmemerr.regs[0] = memcsrptr->memcsr16; if (mrp->elmemerr.regs[0] & 0xc0000000) mrp->elmemerr.type = ELMETYP_RDS; else if (mrp->elmemerr.regs[0] & 0x20000000) mrp->elmemerr.type = ELMETYP_CRD; else if (mrp->elmemerr.regs[0] & 0x100) mrp->elmemerr.type = ELMETYP_CNTL; else mrp->elmemerr.type = 0; memcsrptr->memcsr16 = mrp->elmemerr.regs[0]; /* Clear errors*/ mrp->elmemerr.regs[1] = pa; mrp->elmemerr.regs[2] = ep[EF_EPC];; mrp->elmemerr.regs[3] = ep[EF_BADVADDR];; EVALID(elrp); }}/* * 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, printstate is changed to force * kernel printfs directly to the screen. */kn210consprint(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 */{ /* * If console is a graphics device, * force printf messages directly to screen. * Note: DS_5400 currently does not support qdss, * but just in case... */ printstate |= PANICPRINT; switch (pkt) { case ESRPKT: cprintf("\nException condition\n"); break; case MEMPKT: cprintf("\nMemory Error\n"); break; default: cprintf("bad consprint\n"); break; } cprintf("\tCause reg\t= 0x%x\n", ep[EF_CAUSE]); cprintf("\tException PC\t= 0x%x\n", ep[EF_EPC]); cprintf("\tStatus reg\t= 0x%x\n", ep[EF_SR]); cprintf("\tBad virt addr\t= 0x%x\n", ep[EF_BADVADDR]); if (pa) { if (qbus) { cprintf("\tQ22 Bus physical address of error: 0x%x\n", pa); } else { cprintf("\tPhysical address of error: 0x%x\n",pa); } } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -