📄 trap.c
字号:
/* 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) printf("Warning: can't restore instruction at %x: %x\n", p->p_md.md_ss_addr, p->p_md.md_ss_instr); p->p_md.md_ss_addr = 0; i = SIGTRAP; break; } 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 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 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 ((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);}/* * 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;#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 cnt.v_intr++; mask = causeReg & statusReg; /* pending interrupts & enable mask */ if (pmax_hardware_intr) splx((*pmax_hardware_intr)(mask, pc, statusReg, causeReg)); if (mask & MACH_INT_MASK_5) { 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); } if (mask & MACH_SOFT_INT_MASK_0) { clearsoftclock(); cnt.v_soft++; 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 }}/* * Handle pmax (DECstation 2100/3100) interrupts. */pmax_intr(mask, pc, statusReg, causeReg) unsigned mask; unsigned pc; unsigned statusReg; unsigned causeReg;{ register volatile struct chiptime *c = Mach_clock_addr; struct clockframe cf; int temp; /* handle clock interrupts ASAP */ if (mask & MACH_INT_MASK_3) { temp = c->regc; /* XXX clear interrupt bits */ cf.pc = pc; cf.sr = statusReg; hardclock(&cf); /* keep clock interrupts enabled */ causeReg &= ~MACH_INT_MASK_3; } /* Re-enable clock interrupts */ splx(MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR);#if NSII > 0 if (mask & MACH_INT_MASK_0) siiintr(0);#endif#if NLE > 0 if (mask & MACH_INT_MASK_1) leintr(0);#endif#if NDC > 0 if (mask & MACH_INT_MASK_2) dcintr(0);#endif if (mask & MACH_INT_MASK_4) pmax_errintr(); return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);}/* * Handle hardware interrupts for the KN02. (DECstation 5000/200) * Returns spl value. */kn02_intr(mask, pc, statusReg, causeReg) unsigned mask; unsigned pc; unsigned statusReg; unsigned causeReg;{ register unsigned i, m; register volatile struct chiptime *c = Mach_clock_addr; register unsigned csr; int temp; struct clockframe cf; static int warned = 0; /* handle clock interrupts ASAP */ if (mask & MACH_INT_MASK_1) { csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR); if ((csr & KN02_CSR_PSWARN) && !warned) { warned = 1; printf("WARNING: power supply is overheating!\n"); } else if (warned && !(csr & KN02_CSR_PSWARN)) { warned = 0; printf("WARNING: power supply is OK again\n"); } temp = c->regc; /* XXX clear interrupt bits */ cf.pc = pc; cf.sr = statusReg; hardclock(&cf); /* keep clock interrupts enabled */ causeReg &= ~MACH_INT_MASK_1; } /* Re-enable clock interrupts */ splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR); if (mask & MACH_INT_MASK_0) { csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR); m = csr & (csr >> KN02_CSR_IOINTEN_SHIFT) & KN02_CSR_IOINT;#if 0 *(unsigned *)MACHPHYS_TO_UNCACHED(KN02_SYS_CSR) = (csr & ~(KN02_CSR_WRESERVED | 0xFF)) | (m << KN02_CSR_IOINTEN_SHIFT);#endif for (i = 0; m; i++, m >>= 1) { if (!(m & 1)) continue; if (tc_slot_info[i].intr) (*tc_slot_info[i].intr)(tc_slot_info[i].unit); else printf("spurious interrupt %d\n", i); }#if 0 *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR) = csr & ~(KN02_CSR_WRESERVED | 0xFF);#endif } if (mask & MACH_INT_MASK_3) kn02_errintr(); return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);}/* * 3min hardware interrupts. (DECstation 5000/1xx) */kmin_intr(mask, pc, statusReg, causeReg) unsigned mask; unsigned pc; unsigned statusReg; unsigned causeReg;{ register u_int intr; register volatile struct chiptime *c = Mach_clock_addr; volatile u_int *imaskp = (volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_IMSK); volatile u_int *intrp = (volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_INTR); unsigned int old_mask; struct clockframe cf; int temp; static int user_warned = 0; old_mask = *imaskp & kmin_tc3_imask; *imaskp = old_mask; if (mask & MACH_INT_MASK_4) (*callv->halt)((int *)0, 0); if (mask & MACH_INT_MASK_3) { intr = *intrp; /* masked interrupts are still observable */ intr &= old_mask; if (intr & KMIN_INTR_SCSI_PTR_LOAD) { *intrp &= ~KMIN_INTR_SCSI_PTR_LOAD;#ifdef notdef asc_dma_intr();#endif } if (intr & (KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E)) *intrp &= ~(KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E); if (intr & KMIN_INTR_LANCE_READ_E) *intrp &= ~KMIN_INTR_LANCE_READ_E; if (intr & KMIN_INTR_TIMEOUT) kn02ba_errintr(); if (intr & KMIN_INTR_CLOCK) { temp = c->regc; /* XXX clear interrupt bits */ cf.pc = pc; cf.sr = statusReg; hardclock(&cf); } if ((intr & KMIN_INTR_SCC_0) && tc_slot_info[KMIN_SCC0_SLOT].intr) (*(tc_slot_info[KMIN_SCC0_SLOT].intr)) (tc_slot_info[KMIN_SCC0_SLOT].unit); if ((intr & KMIN_INTR_SCC_1) && tc_slot_info[KMIN_SCC1_SLOT].intr) (*(tc_slot_info[KMIN_SCC1_SLOT].intr)) (tc_slot_info[KMIN_SCC1_SLOT].unit); if ((intr & KMIN_INTR_SCSI) && tc_slot_info[KMIN_SCSI_SLOT].intr) (*(tc_slot_info[KMIN_SCSI_SLOT].intr)) (tc_slot_info[KMIN_SCSI_SLOT].unit); if ((intr & KMIN_INTR_LANCE) && tc_slot_info[KMIN_LANCE_SLOT].intr) (*(tc_slot_info[KMIN_LANCE_SLOT].intr)) (tc_slot_info[KMIN_LANCE_SLOT].unit); if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) { printf("%s\n", "Power supply ok now."); user_warned = 0; } if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) { user_warned++; printf("%s\n", "Power supply overheating"); } } if ((mask & MACH_INT_MASK_0) && tc_slot_info[0].intr) (*tc_slot_info[0].intr)(tc_slot_info[0].unit); if ((mask & MACH_INT_MASK_1) && tc_slot_info[1].intr) (*tc_slot_info[1].intr)(tc_slot_info[1].unit); if ((mask & MACH_INT_MASK_2) && tc_slot_info[2].intr) (*tc_slot_info[2].intr)(tc_slot_info[2].unit); return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);}/* * Maxine hardware interrupts. (Personal DECstation 5000/xx) */xine_intr(mask, pc, statusReg, causeReg) unsigned mask; unsigned pc; unsigned statusReg; unsigned causeReg;{ register u_int intr; register volatile struct chiptime *c = Mach_clock_addr; volatile u_int *imaskp = (volatile u_int *) MACH_PHYS_TO_UNCACHED(XINE_REG_IMSK); volatile u_int *intrp = (volatile u_int *) MACH_PHYS_TO_UNCACHED(XINE_REG_INTR); u_int old_mask; struct clockframe cf; int temp; old_mask = *imaskp & xine_tc3_imask; *imaskp = old_mask; if (mask & MACH_INT_MASK_4) (*callv->halt)((int *)0, 0); /* handle clock interrupts ASAP */ if (mask & MACH_INT_MASK_1) { temp = c->regc; /* XXX clear interrupt bits */ cf.pc = pc; cf.sr = statusReg; hardclock(&cf); causeReg &= ~MACH_INT_MASK_1; /* reenable clock interrupts */ splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR); } if (mask & MACH_INT_MASK_3) { intr = *intrp; /* masked interrupts are still observable */ intr &= old_mask; if (intr & XINE_INTR_SCSI_PTR_LOAD) { *intrp &= ~XINE_INTR_SCSI_PTR_LOAD;#ifdef notdef asc_dma_intr();#endif } if (intr & (XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E)) *intrp &= ~(XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E); if (intr & XINE_INTR_LANCE_READ_E) *intrp &= ~XINE_INTR_LANCE_READ_E; if ((intr & XINE_INTR_SCC_0) && tc_slot_info[XINE_SCC0_SLOT].intr) (*(tc_slot_info[XINE_SCC0_SLOT].intr)) (tc_slot_info[XINE_SCC0_SLOT].unit); if ((intr & XINE_INTR_DTOP_RX) && tc_slot_info[XINE_DTOP_SLOT].intr) (*(tc_slot_info[XINE_DTOP_SLOT].intr)) (tc_slot_info[XINE_DTOP_SLOT].unit); if ((intr & XINE_INTR_FLOPPY) && tc_slot_info[XINE_FLOPPY_SLOT].intr) (*(tc_slot_info[XINE_FLOPPY_SLOT].intr)) (tc_slot_info[XINE_FLOPPY_SLOT].unit); if ((intr & XINE_INTR_TC_0) && tc_slot_info[0].intr) (*(tc_slot_info[0].intr)) (tc_slot_info[0].unit); if ((intr & XINE_INTR_TC_1) && tc_slot_info[1].intr) (*(tc_slot_info[1].intr)) (tc_slot_info[1].unit); if ((intr & XINE_INTR_ISDN) && tc_slot_info[XINE_ISDN_SLOT].intr) (*(tc_slot_info[XINE_ISDN_SLOT].intr)) (tc_slot_info[XINE_ISDN_SLOT].unit); if ((intr & XINE_INTR_SCSI) && tc_slot_info[XINE_SCSI_SLOT].intr) (*(tc_slot_info[XINE_SCSI_SLOT].intr)) (tc_slot_info[XINE_SCSI_SLOT].unit); if ((intr & XINE_INTR_LANCE) && tc_slot_info[XINE_LANCE_SLOT].intr) (*(tc_slot_info[XINE_LANCE_SLOT].intr)) (tc_slot_info[XINE_LANCE_SLOT].unit); } if (mask & MACH_INT_MASK_2) kn02ba_errintr(); return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);}#ifdef DS5000_240/* * 3Max+ hardware interrupts. (DECstation 5000/240) UNTESTED!! */kn03_intr(mask, pc, statusReg, causeReg) unsigned mask; unsigned pc; unsigned statusReg; unsigned causeReg;{ register u_int intr; register volatile struct chiptime *c = Mach_clock_addr; volatile u_int *imaskp = (volatile u_int *) MACH_PHYS_TO_UNCACHED(KN03_REG_IMSK); volatile u_int *intrp = (volatile u_int *) MACH_PHYS_TO_UNCACHED(KN03_REG_INTR); u_int old_mask; struct clockframe cf; int temp; static int user_warned = 0; old_mask = *imaskp & kn03_tc3_imask; *imaskp = old_mask; if (mask & MACH_INT_MASK_4) (*callv->halt)((int *)0, 0); /* handle clock interrupts ASAP */ if (mask & MACH_INT_MASK_1) { temp = c->regc; /* XXX clear interrupt bits */ cf.pc = pc; cf.sr = statusReg; hardclock(&cf); causeReg &= ~MACH_INT_MASK_1; /* reenable clock interrupts */ splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR); } if (mask & MACH_INT_MASK_0) { intr = *intrp; /* masked interrupts are still observable */ intr &= old_mask; if (intr & KN03_INTR_SCSI_PTR_LOAD) { *intrp &= ~KN03_INTR_SCSI_PTR_LOAD;#ifdef notdef asc_dma_intr();#endif } if (intr & (KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E)) *intrp &= ~(KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E); if (intr & KN03_INTR_LANCE_READ_E) *intrp &= ~KN03_INTR_LANCE_READ_E; if ((intr & KN03_INTR_SCC_0) && tc_slot_info[KN03_SCC0_SLOT].intr) (*(tc_slot_info[KN03_SCC0_SLOT].intr)) (tc_slot_info[KN03_SCC0_SLOT].unit); if ((intr & KN03_INTR_SCC_1) && tc_slot_info[KN03_SCC1_SLOT].intr) (*(tc_slot_info[KN03_SCC1_SLOT].intr)) (tc_slot_info[KN03_SCC1_SLOT].unit); if ((intr & KN03_INTR_TC_0) && tc_slot_info[0].intr) (*(tc_slot_info[0].intr)) (tc_slot_info[0].unit); if ((intr & KN03_INTR_TC_1) && tc_slot_info[1].intr) (*(tc_slot_info[1].intr)) (tc_slot_info[1].unit); if ((intr & KN03_INTR_TC_2) && tc_slot_info[2].intr)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -