📄 trap.c
字号:
(*(tc_slot_info[2].intr)) (tc_slot_info[2].unit); if ((intr & KN03_INTR_SCSI) && tc_slot_info[KN03_SCSI_SLOT].intr) (*(tc_slot_info[KN03_SCSI_SLOT].intr)) (tc_slot_info[KN03_SCSI_SLOT].unit); if ((intr & KN03_INTR_LANCE) && tc_slot_info[KN03_LANCE_SLOT].intr) (*(tc_slot_info[KN03_LANCE_SLOT].intr)) (tc_slot_info[KN03_LANCE_SLOT].unit); if (user_warned && ((intr & KN03_INTR_PSWARN) == 0)) { printf("%s\n", "Power supply ok now."); user_warned = 0; } if ((intr & KN03_INTR_PSWARN) && (user_warned < 3)) { user_warned++; printf("%s\n", "Power supply overheating"); } } if (mask & MACH_INT_MASK_3) kn03_errintr(); return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);}#endif /* DS5000_240 *//* * This is called from MachUserIntr() if astpending is set. * This is very similar to the tail of trap(). */softintr(statusReg, pc) unsigned statusReg; /* status register at time of the exception */ unsigned pc; /* program counter where to continue */{ register struct proc *p = curproc; int sig; cnt.v_soft++; /* take pending signals */ while ((sig = CURSIG(p)) != 0) postsig(sig); p->p_priority = p->p_usrpri; astpending = 0; if (p->p_flag & P_OWEUPC) { p->p_flag &= ~P_OWEUPC; ADDUPROF(p); } if (want_resched) { int s; /* * Since we are curproc, clock will normally just change * our priority without moving us from one queue to another * (since the running process is not on a queue.) * If that happened after we put ourselves on the run queue * but before we switched, we might not be on the queue * indicated by our priority. */ s = splstatclock(); setrunqueue(p); p->p_stats->p_ru.ru_nivcsw++; mi_switch(); splx(s); while ((sig = CURSIG(p)) != 0) postsig(sig); } curpriority = p->p_priority;}#ifdef DEBUGtrapDump(msg) char *msg;{ register int i; int s; s = splhigh(); printf("trapDump(%s)\n", msg); for (i = 0; i < TRAPSIZE; i++) { if (trp == trapdebug) trp = &trapdebug[TRAPSIZE - 1]; else trp--; if (trp->cause == 0) break; printf("%s: ADR %x PC %x CR %x SR %x\n", trap_type[(trp->cause & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT], trp->vadr, trp->pc, trp->cause, trp->status); printf(" RA %x code %d\n", trp-> ra, trp->code); } bzero(trapdebug, sizeof(trapdebug)); trp = trapdebug; splx(s);}#endif/* *---------------------------------------------------------------------- * * MemErrorInterrupts -- * pmax_errintr - for the DS2100/DS3100 * kn02_errintr - for the DS5000/200 * kn02ba_errintr - for the DS5000/1xx and DS5000/xx * * Handler an interrupt for the control register. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidpmax_errintr(){ volatile u_short *sysCSRPtr = (u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR); u_short csr; csr = *sysCSRPtr; if (csr & KN01_CSR_MERR) { printf("Memory error at 0x%x\n", *(unsigned *)MACH_PHYS_TO_UNCACHED(KN01_SYS_ERRADR)); panic("Mem error interrupt"); } *sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;}static voidkn02_errintr(){ u_int erradr, chksyn, physadr; int i; erradr = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR); chksyn = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN); *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0; MachEmptyWriteBuffer(); if (!(erradr & KN02_ERR_VALID)) return; /* extract the physical word address and compensate for pipelining */ physadr = erradr & KN02_ERR_ADDRESS; if (!(erradr & KN02_ERR_WRITE)) physadr = (physadr & ~0xfff) | ((physadr & 0xfff) - 5); physadr <<= 2; printf("%s memory %s %s error at 0x%x\n", (erradr & KN02_ERR_CPU) ? "CPU" : "DMA", (erradr & KN02_ERR_WRITE) ? "write" : "read", (erradr & KN02_ERR_ECCERR) ? "ECC" : "timeout", physadr); if (erradr & KN02_ERR_ECCERR) { *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN) = 0; MachEmptyWriteBuffer(); printf("ECC 0x%x\n", chksyn); /* check for a corrected, single bit, read error */ if (!(erradr & KN02_ERR_WRITE)) { if (physadr & 0x4) { /* check high word */ if (chksyn & KN02_ECC_SNGHI) return; } else { /* check low word */ if (chksyn & KN02_ECC_SNGLO) return; } } } panic("Mem error interrupt");}#ifdef DS5000_240static voidkn03_errintr(){ printf("erradr %x\n", *(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR)); *(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0; MachEmptyWriteBuffer();}#endif /* DS5000_240 */static voidkn02ba_errintr(){ register int mer, adr, siz; static int errintr_cnt = 0; siz = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MSR); mer = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MER); adr = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_AER); /* clear interrupt bit */ *(unsigned int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0; errintr_cnt++; printf("(%d)%s%x [%x %x %x]\n", errintr_cnt, "Bad memory chip at phys ", kn02ba_recover_erradr(adr, mer), mer, siz, adr);}static unsignedkn02ba_recover_erradr(phys, mer) register unsigned phys, mer;{ /* phys holds bits 28:2, mer knows which byte */ switch (mer & KMIN_MER_LASTBYTE) { case KMIN_LASTB31: mer = 3; break; case KMIN_LASTB23: mer = 2; break; case KMIN_LASTB15: mer = 1; break; case KMIN_LASTB07: mer = 0; break; } return ((phys & KMIN_AER_ADDR_MASK) | mer);}/* * Return the resulting PC as if the branch was executed. */unsignedMachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch) unsigned *regsPtr; unsigned instPC; unsigned fpcCSR; int allowNonBranch;{ InstFmt inst; unsigned retAddr; int condition; extern unsigned GetBranchDest(); inst = *(InstFmt *)instPC;#if 0 printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC, inst.word, fpcCSR); /* XXX */#endif switch ((int)inst.JType.op) { case OP_SPECIAL: switch ((int)inst.RType.func) { case OP_JR: case OP_JALR: retAddr = regsPtr[inst.RType.rs]; break; default: if (!allowNonBranch) panic("MachEmulateBranch: Non-branch"); retAddr = instPC + 4; break; } break; case OP_BCOND: switch ((int)inst.IType.rt) { case OP_BLTZ: case OP_BLTZAL: if ((int)(regsPtr[inst.RType.rs]) < 0) retAddr = GetBranchDest((InstFmt *)instPC); else retAddr = instPC + 8; break; case OP_BGEZAL: case OP_BGEZ: if ((int)(regsPtr[inst.RType.rs]) >= 0) retAddr = GetBranchDest((InstFmt *)instPC); else retAddr = instPC + 8; break; default: panic("MachEmulateBranch: Bad branch cond"); } break; case OP_J: case OP_JAL: retAddr = (inst.JType.target << 2) | ((unsigned)instPC & 0xF0000000); break; case OP_BEQ: if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt]) retAddr = GetBranchDest((InstFmt *)instPC); else retAddr = instPC + 8; break; case OP_BNE: if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt]) retAddr = GetBranchDest((InstFmt *)instPC); else retAddr = instPC + 8; break; case OP_BLEZ: if ((int)(regsPtr[inst.RType.rs]) <= 0) retAddr = GetBranchDest((InstFmt *)instPC); else retAddr = instPC + 8; break; case OP_BGTZ: if ((int)(regsPtr[inst.RType.rs]) > 0) retAddr = GetBranchDest((InstFmt *)instPC); else retAddr = instPC + 8; break; case OP_COP1: switch (inst.RType.rs) { case OP_BCx: case OP_BCy: if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE) condition = fpcCSR & MACH_FPC_COND_BIT; else condition = !(fpcCSR & MACH_FPC_COND_BIT); if (condition) retAddr = GetBranchDest((InstFmt *)instPC); else retAddr = instPC + 8; break; default: if (!allowNonBranch) panic("MachEmulateBranch: Bad coproc branch instruction"); retAddr = instPC + 4; } break; default: if (!allowNonBranch) panic("MachEmulateBranch: Non-branch instruction"); retAddr = instPC + 4; }#if 0 printf("Target addr=%x\n", retAddr); /* XXX */#endif return (retAddr);}unsignedGetBranchDest(InstPtr) InstFmt *InstPtr;{ return ((unsigned)InstPtr + 4 + ((short)InstPtr->IType.imm << 2));}/* * This routine is called by procxmt() to single step one instruction. * We do this by storing a break instruction after the current instruction, * resuming execution, and then restoring the old instruction. */cpu_singlestep(p) register struct proc *p;{ register unsigned va; register int *locr0 = p->p_md.md_regs; int i; /* compute next address after current location */ va = MachEmulateBranch(locr0, locr0[PC], locr0[FSR], 1); if (p->p_md.md_ss_addr || p->p_md.md_ss_addr == va || !useracc((caddr_t)va, 4, B_READ)) { printf("SS %s (%d): breakpoint already set at %x (va %x)\n", p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */ return (EFAULT); } p->p_md.md_ss_addr = va; p->p_md.md_ss_instr = fuiword((caddr_t)va); i = suiword((caddr_t)va, MACH_BREAK_SSTEP); if (i < 0) { vm_offset_t sa, ea; int rv; sa = trunc_page((vm_offset_t)va); ea = round_page((vm_offset_t)va+sizeof(int)-1); rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_DEFAULT, FALSE); if (rv == KERN_SUCCESS) { i = suiword((caddr_t)va, MACH_BREAK_SSTEP); (void) vm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE); } } if (i < 0) return (EFAULT);#if 0 printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n", p->p_comm, p->p_pid, p->p_md.md_ss_addr, p->p_md.md_ss_instr, locr0[PC], fuword((caddr_t)va)); /* XXX */#endif return (0);}#ifdef DEBUGkdbpeek(addr){ if (addr & 3) { printf("kdbpeek: unaligned address %x\n", addr); return (-1); } return (*(int *)addr);}#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra *//* * Print a stack backtrace. */voidstacktrace(a0, a1, a2, a3) int a0, a1, a2, a3;{ unsigned pc, sp, fp, ra, va, subr; unsigned instr, mask; InstFmt i; int more, stksize; int regs[3]; extern setsoftclock(); extern char start[], edata[]; cpu_getregs(regs); /* get initial values from the exception frame */ sp = regs[0]; pc = regs[1]; ra = 0; fp = regs[2];loop: /* check for current PC in the kernel interrupt handler code */ if (pc >= (unsigned)MachKernIntr && pc < (unsigned)MachUserIntr) { /* NOTE: the offsets depend on the code in locore.s */ printf("interrupt\n"); a0 = kdbpeek(sp + 36); a1 = kdbpeek(sp + 40); a2 = kdbpeek(sp + 44); a3 = kdbpeek(sp + 48); pc = kdbpeek(sp + 20); ra = kdbpeek(sp + 92); sp = kdbpeek(sp + 100); fp = kdbpeek(sp + 104); } /* check for current PC in the exception handler code */ if (pc >= 0x80000000 && pc < (unsigned)setsoftclock) { ra = 0; subr = 0; goto done; } /* check for bad PC */ if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) { printf("PC 0x%x: not in kernel\n", pc); ra = 0; subr = 0; goto done; } /* * Find the beginning of the current subroutine by scanning backwards * from the current PC for the end of the previous subroutine. */ va = pc - sizeof(int); while ((instr = kdbpeek(va)) != MIPS_JR_RA) va -= sizeof(int); va += 2 * sizeof(int); /* skip back over branch & delay slot */ /* skip over nulls which might separate .o files */ while ((instr = kdbpeek(va)) == 0) va += sizeof(int); subr = va; /* scan forwards to find stack size and any saved registers */ stksize = 0; more = 3; mask = 0; for (; more; va += sizeof(int), more = (more == 3) ? 3 : more - 1) { /* stop if hit our current position */ if (va >= pc) break; instr = kdbpeek(va); i.word = instr; switch (i.JType.op) { case OP_SPECIAL: switch (i.RType.func) { case OP_JR: case OP_JALR: more = 2; /* stop after next instruction */ break; case OP_SYSCALL: case OP_BREAK: more = 1; /* stop now */ }; break; case OP_BCOND: case OP_J: case OP_JAL: case OP_BEQ: case OP_BNE: case OP_BLEZ: case OP_BGTZ: more = 2; /* stop after next instruction */ break; case OP_COP0: case OP_COP1: case OP_COP2: case OP_COP3: switch (i.RType.rs) { case OP_BCx: case OP_BCy: more = 2; /* stop after next instruction */ }; break; case OP_SW: /* look for saved registers on the stack */ if (i.IType.rs != 29) break; /* only restore the first one */ if (mask & (1 << i.IType.rt)) break; mask |= 1 << i.IType.rt; switch (i.IType.rt) { case 4: /* a0 */ a0 = kdbpeek(sp + (short)i.IType.imm); break; case 5: /* a1 */ a1 = kdbpeek(sp + (short)i.IType.imm); break; case 6: /* a2 */ a2 = kdbpeek(sp + (short)i.IType.imm); break; case 7: /* a3 */ a3 = kdbpeek(sp + (short)i.IType.imm); break; case 30: /* fp */ fp = kdbpeek(sp + (short)i.IType.imm); break; case 31: /* ra */ ra = kdbpeek(sp + (short)i.IType.imm); } break; case OP_ADDI: case OP_ADDIU: /* look for stack pointer adjustment */ if (i.IType.rs != 29 || i.IType.rt != 29) break; stksize = (short)i.IType.imm; } }done: printf("%x+%x (%x,%x,%x,%x) ra %x sz %d\n", subr, pc - subr, a0, a1, a2, a3, ra, stksize); if (ra) { if (pc == ra && stksize == 0) printf("stacktrace: loop!\n"); else { pc = ra; sp -= stksize; goto loop; } }}#endif /* DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -