📄 trap.c
字号:
args.i[3] = locr0[A3]; if (i > 4) { i = copyin((caddr_t)(locr0[SP] + 4 * sizeof(int)), (caddr_t)&args.i[4], (u_int)(i - 4) * sizeof(int)); if (i) { locr0[V0] = i; locr0[A3] = 1;#ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);#endif goto done; } } }#ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);#endif rval[0] = 0; rval[1] = locr0[V1];#ifdef DEBUG if (trp == trapdebug) trapdebug[TRAPSIZE - 1].code = code; else trp[-1].code = code;#endif i = (*callp->sy_call)(p, &args, rval); /* * Reinitialize proc pointer `p' as it may be different * if this is a child returning from fork syscall. */ p = curproc; locr0 = p->p_md.md_regs;#ifdef DEBUG { int s; s = splhigh(); trp->status = statusReg; trp->cause = causeReg; trp->vadr = locr0[SP]; trp->pc = locr0[PC]; trp->ra = locr0[RA]; trp->code = -code; if (++trp == &trapdebug[TRAPSIZE]) trp = trapdebug; splx(s); }#endif switch (i) { case 0: locr0[V0] = rval[0]; locr0[V1] = rval[1]; locr0[A3] = 0; break; case ERESTART: locr0[PC] = pc; break; case EJUSTRETURN: break; /* nothing to do */ default: locr0[V0] = i; locr0[A3] = 1; } done:#ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p->p_tracep, code, i, rval[0]);#endif goto out; } case T_BREAK+T_USER: { register unsigned va, instr; /* compute address of break instruction */ va = pc; if ((int)causeReg < 0) va += 4; /* read break instruction */ instr = fuiword((caddr_t)va);#ifdef KADB if (instr == MACH_BREAK_BRKPT || instr == MACH_BREAK_SSTEP) goto err;#endif if (p->p_md.md_ss_addr != va || instr != MACH_BREAK_SSTEP) { i = SIGTRAP; break; } /* restore original instruction and clear BP */ i = suiword((caddr_t)va, p->p_md.md_ss_instr); 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, p->p_md.md_ss_instr); (void) vm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE); } } if (i < 0) { i = SIGTRAP; break; } p->p_md.md_ss_addr = 0; goto out; } case T_RES_INST+T_USER: i = SIGILL; break; case T_COP_UNUSABLE+T_USER: if ((causeReg & MACH_CR_COP_ERR) != 0x10000000) { i = SIGILL; /* only FPU instructions allowed */ break; } MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs); machFPCurProcPtr = p; p->p_md.md_regs[PS] |= MACH_SR_COP_1_BIT; p->p_md.md_flags |= MDP_FPUSED; goto out; case T_OVFLOW+T_USER: i = SIGFPE; break; case T_ADDR_ERR_LD: /* misaligned access */ case T_ADDR_ERR_ST: /* misaligned access */ case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ if (i = ((struct pcb *)UADDR)->pcb_onfault) { ((struct pcb *)UADDR)->pcb_onfault = 0; return (onfault_table[i]); } /* FALLTHROUGH */ default: err:#ifdef KADB { extern struct pcb kdbpcb; if (USERMODE(statusReg)) kdbpcb = p->p_addr->u_pcb; else { kdbpcb.pcb_regs[ZERO] = 0; kdbpcb.pcb_regs[AST] = ((int *)&args)[2]; kdbpcb.pcb_regs[V0] = ((int *)&args)[3]; kdbpcb.pcb_regs[V1] = ((int *)&args)[4]; kdbpcb.pcb_regs[A0] = ((int *)&args)[5]; kdbpcb.pcb_regs[A1] = ((int *)&args)[6]; kdbpcb.pcb_regs[A2] = ((int *)&args)[7]; kdbpcb.pcb_regs[A3] = ((int *)&args)[8]; kdbpcb.pcb_regs[T0] = ((int *)&args)[9]; kdbpcb.pcb_regs[T1] = ((int *)&args)[10]; kdbpcb.pcb_regs[T2] = ((int *)&args)[11]; kdbpcb.pcb_regs[T3] = ((int *)&args)[12]; kdbpcb.pcb_regs[T4] = ((int *)&args)[13]; kdbpcb.pcb_regs[T5] = ((int *)&args)[14]; kdbpcb.pcb_regs[T6] = ((int *)&args)[15]; kdbpcb.pcb_regs[T7] = ((int *)&args)[16]; kdbpcb.pcb_regs[T8] = ((int *)&args)[17]; kdbpcb.pcb_regs[T9] = ((int *)&args)[18]; kdbpcb.pcb_regs[RA] = ((int *)&args)[19]; kdbpcb.pcb_regs[MULLO] = ((int *)&args)[21]; kdbpcb.pcb_regs[MULHI] = ((int *)&args)[22]; kdbpcb.pcb_regs[PC] = pc; kdbpcb.pcb_regs[SR] = statusReg; bzero((caddr_t)&kdbpcb.pcb_regs[F0], 33 * sizeof(int)); } if (kdb(causeReg, vadr, p, !USERMODE(statusReg))) return (kdbpcb.pcb_regs[PC]); }#else#ifdef DEBUG printf("trap: pid %d %s sig %d adr %x pc %x ra %x\n", p->p_pid, p->p_comm, i, vadr, pc, p->p_md.md_regs[RA]); /* XXX */ trapDump("trap");#endif#endif panic("trap"); } trapsignal(p, i, ucode);out: /* * Note: we should only get here if returning to user mode. */ /* take pending signals */ while ((i = CURSIG(p)) != 0) postsig(i); p->p_priority = p->p_usrpri; astpending = 0; 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 switch()'ed, 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 ((i = CURSIG(p)) != 0) postsig(i); } /* * If profiling, charge system time to the trapped pc. */ if (p->p_flag & P_PROFIL) { extern int psratio; addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio); } curpriority = p->p_priority; return (pc);}int badaddr_flag;/* * Handle an interrupt. * Called from MachKernIntr() or MachUserIntr() * Note: curproc might be NULL. */interrupt(statusReg, causeReg, pc) unsigned statusReg; /* status register at time of the exception */ unsigned causeReg; /* cause register at time of exception */ unsigned pc; /* program counter where to continue */{ register unsigned mask; struct clockframe cf; int oonfault = ((struct pcb *)UADDR)->pcb_onfault;#ifdef DEBUG trp->status = statusReg; trp->cause = causeReg; trp->vadr = 0; trp->pc = pc; trp->ra = 0; trp->code = 0; if (++trp == &trapdebug[TRAPSIZE]) trp = trapdebug;#endif mask = causeReg & statusReg; /* pending interrupts & enable mask */ if (mask & MACH_INT_MASK_5) { /* level 5 interrupt */ splx((MACH_SPL_MASK_8 & ~causeReg) | MACH_SR_INT_ENA_CUR); printf("level 5 interrupt: PC %x CR %x SR %x\n", pc, causeReg, statusReg); causeReg &= ~MACH_INT_MASK_5; } if (mask & MACH_INT_MASK_4) { /* level 4 interrupt */ /* * asynchronous bus error */ splx((MACH_SPL_MASK_7 & ~causeReg) | MACH_SR_INT_ENA_CUR); *(char *)INTCLR0 = INTCLR0_BERR; causeReg &= ~MACH_INT_MASK_4;#define BADADDR 1 if (oonfault == BADADDR) { /* XXX */ badaddr_flag = 1; } else { printf("level 4 interrupt: PC %x CR %x SR %x\n", pc, causeReg, statusReg); } } if (mask & MACH_INT_MASK_3) { /* level 3 interrupt */ /* * fp error */ splx((MACH_SPL_MASK_6 & ~causeReg) | MACH_SR_INT_ENA_CUR); if (!USERMODE(statusReg)) {#ifdef DEBUG trapDump("fpintr");#else printf("FPU interrupt: PC %x CR %x SR %x\n", pc, causeReg, statusReg);#endif } else MachFPInterrupt(statusReg, causeReg, pc); causeReg &= ~MACH_INT_MASK_3; } if (mask & MACH_INT_MASK_2) { /* level 2 interrupt */ register int stat; splx((MACH_SPL_MASK_5 & ~causeReg) | MACH_SR_INT_ENA_CUR); stat = *(volatile u_char *)INTST0; if (stat & INTST0_TIMINT) { /* timer */ static int led_count = 0; *(volatile u_char *)INTCLR0 = INTCLR0_TIMINT; cf.pc = pc; cf.sr = statusReg; hardclock(&cf); if (++led_count > hz) { led_count = 0; *(volatile u_char *)DEBUG_PORT ^= DP_LED1; } }#if NBM > 0 if (stat & INTST0_KBDINT) /* keyboard */ kbm_rint(SCC_KEYBOARD);#endif#if NMS > 0 if (stat & INTST0_MSINT) /* mouse */ kbm_rint(SCC_MOUSE);#endif causeReg &= ~MACH_INT_MASK_2; } if (mask & MACH_INT_MASK_1) { /* level 1 interrupt */ splx((MACH_SPL_MASK_4 & ~causeReg) | MACH_SR_INT_ENA_CUR); level1_intr(); causeReg &= ~MACH_INT_MASK_1; } if (mask & MACH_INT_MASK_0) { /* level 0 interrupt */ splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR); level0_intr(); causeReg &= ~MACH_INT_MASK_0; } splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR); if (mask & MACH_SOFT_INT_MASK_0) { struct clockframe cf; clearsoftclock(); cnt.v_soft++; cf.pc = pc; cf.sr = statusReg; softclock(); } /* process network interrupt if we trapped or will very soon */ if ((mask & MACH_SOFT_INT_MASK_1) || netisr && (statusReg & MACH_SOFT_INT_MASK_1)) { clearsoftnet(); cnt.v_soft++;#ifdef INET if (netisr & (1 << NETISR_ARP)) { netisr &= ~(1 << NETISR_ARP); arpintr(); } if (netisr & (1 << NETISR_IP)) { netisr &= ~(1 << NETISR_IP); ipintr(); }#endif#ifdef NS if (netisr & (1 << NETISR_NS)) { netisr &= ~(1 << NETISR_NS); nsintr(); }#endif#ifdef ISO if (netisr & (1 << NETISR_ISO)) { netisr &= ~(1 << NETISR_ISO); clnlintr(); }#endif } /* restore onfault flag */ ((struct pcb *)UADDR)->pcb_onfault = oonfault;}/* * 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 switch()'ed, 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/* * 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();#if 0 printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC, *(unsigned *)instPC, fpcCSR);#endif inst = *(InstFmt *)instPC; switch ((int)inst.JType.op) { case OP_SPECIAL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -