📄 trap.c
字号:
turnoff_printer(){ cprintf("%s",p_off);}static int dumpstack_once = 0;dumpstack(ep)unsigned *ep;{ register int i; if (dumpstack_once) return; dumpstack_once++; while((unsigned)ep < (unsigned)(KERNELSTACK-4*4)) { printf("0x%x\t0x%x\t0x%x\t0x%x\t0x%x\n", ep,*ep,*(ep+1),*(ep+2),*(ep+3)); ep += 4; DELAY(300000); } /* print the last few stack addresses (no more than 4 left) */ if((unsigned)ep < (unsigned)(KERNELSTACK-4)) { printf("0x%x\t0x%x",ep,*ep);prloop: ep++; if((unsigned)ep < (unsigned)(KERNELSTACK-4)) { printf("\t0x%x",*ep); goto prloop; } printf("\n"); }}/* * install_bp -- install breakpoints to implement single stepping */staticinstall_bp(){ unsigned inst; unsigned target_pc; if (u.u_pcb.pcb_ssi.ssi_cnt) panic("install_bp2"); /* * If user can't access where his pc points, we give up. * He'll be getting a SIGSEGV shortly anyway! */ if (!useracc(USER_REG(EF_EPC), sizeof(int), B_READ)) return; inst = fuiword(USER_REG(EF_EPC)); if (is_branch(inst)) { target_pc = branch_target(inst, USER_REG(EF_EPC)); /* * Can't single step self-branches, so just wait * until they fall through */ if (target_pc != USER_REG(EF_EPC)) set_bp(target_pc); set_bp(USER_REG(EF_EPC)+8); } else set_bp(USER_REG(EF_EPC)+4); /* * only install breakpoints once! */ u.u_pcb.pcb_sstep = 0;}staticset_bp(addr)unsigned *addr;{ register struct ssi_bp *ssibp; ssibp = &u.u_pcb.pcb_ssi.ssi_bp[u.u_pcb.pcb_ssi.ssi_cnt]; ssibp->bp_addr = addr; /* * Assume that if the fuiword fails, the write_utext will also */ ssibp->bp_inst = fuiword(addr); if (write_utext(addr, *sstepbp)) u.u_pcb.pcb_ssi.ssi_cnt++;}/* * remove_bp -- remove single step breakpoints from current process */remove_bp(){ register struct ssi_bp *ssibp; while (u.u_pcb.pcb_ssi.ssi_cnt > 0) { u.u_pcb.pcb_ssi.ssi_cnt--; ssibp = &u.u_pcb.pcb_ssi.ssi_bp[u.u_pcb.pcb_ssi.ssi_cnt]; if (!write_utext(ssibp->bp_addr, ssibp->bp_inst)) { uprintf("couldn't remove breakpoint\n"); continue; } }}staticis_branch(inst){ union mips_instruction i; i.word = inst; switch (i.j_format.opcode) { case spec_op: switch (i.r_format.func) { case jr_op: case jalr_op: return(1); } return(0); case bcond_op: case j_op: case jal_op: case beq_op: case bne_op: case blez_op: case bgtz_op: return(1); case cop0_op: case cop1_op: case cop2_op: case cop3_op: switch (i.r_format.rs) { case bc_op: return(1); } return(0); } return(0);}#define REGVAL(x) ((x)?USER_REG((x)+EF_AT-1):0)staticbranch_target(inst, pc){ union mips_instruction i; i.word = inst; switch (i.j_format.opcode) { case spec_op: switch (i.r_format.func) { case jr_op: case jalr_op: return(REGVAL(i.r_format.rs)); } break; case j_op: case jal_op: return( ((pc+4)&~((1<<28)-1)) | (i.j_format.target<<2) ); case bcond_op: case beq_op: case bne_op: case blez_op: case bgtz_op: return(pc+4+(i.i_format.simmediate<<2)); case cop0_op: case cop1_op: case cop2_op: case cop3_op: switch (i.r_format.rs) { case bc_op: return(pc+4+(i.i_format.simmediate<<2)); } break; } panic("branch_target");}ldst_addr(ep)register u_int *ep;{ register u_int *pc; union mips_instruction i; int base; pc = (u_int *)ep[EF_EPC]; if (ep[EF_CAUSE] & CAUSE_BD) pc++; i.word = *pc; /* theoretically can't fault */ if (i.i_format.opcode < lb_op) { panic("DBE not on load or store"); } base = (i.i_format.rs == 0) ? 0 : ep[EF_AT + i.i_format.rs - 1]; return (base + i.i_format.simmediate);} trap_nofault(ep, code, sr, cause)register u_int *ep;register u_int code;u_int sr, cause;{ register int i; struct cpudata *pcpu; pcpu = CURRENT_CPUDATA; switch(code) { case EXC_DBE: /* nofault handler */ if (pcpu->cpu_nofault) { extern (*nofault_pc[])(); i = pcpu->cpu_nofault; pcpu->cpu_nofault = 0; if (i < 1 || i >= NF_NENTRIES) panic("bad nofault"); ep[EF_EPC] = (u_int)nofault_pc[i]; return; } /* fall through to default */ default: splhigh(); panic("trap_nofault"); }}dumpregs(ep)unsigned *ep;{ extern struct reg_desc cause_desc[], sr_desc[]; /* * Dump out other items of interest */ printf("Faulting PC: 0x%x\n", ep[EF_EPC]); printf("Cause register: %R\n", ep[EF_CAUSE], cause_desc); printf("Status register: %R\n", ep[EF_SR], sr_desc); printf("Bad Vaddress: 0x%x\n", ep[EF_BADVADDR]); printf("Stack Pointer: 0x%x\n", ep[EF_SP]);}#ifdef TLBMISS_STUCK /* must be power of 2 */#define VADDR_RING_SIZE (1<<3)u_int vaddr_ring[VADDR_RING_SIZE];int vaddr_ring_index = 0;#endif TLBMISS_STUCKtlbmiss(ep, code, vaddr, cause)u_int *ep;u_int code, vaddr, cause;{ register u_int vpn, uvpn; register struct pte *pte; register u_int kvpn; register struct tlbinfo *ti; struct pte tpte; struct proc *p; extern unsigned Syssize;#if CNT_TLBMISS_HACK==1 u.u_ru.ru_oublock++;#endif CNT_TLBMISS_HACK /* * Workaround for 3.0/4.0 chip bug. If badvaddr has been trashed * by chip, epc is correct vaddr */ if (vaddr == E_VEC) vaddr = ep[EF_EPC]; vpn = btop(vaddr); p = u.u_procp; pte = (struct pte *)0; if (IS_KUSEG(vaddr)) { pte = vtopte(p, vpn);#ifdef TLBMISS_STUCK { int i; vaddr_ring[vaddr_ring_index++ & (VADDR_RING_SIZE-1)] = vaddr; for (i=0; i < VADDR_RING_SIZE-1; i++) if (vaddr_ring[i] != vaddr_ring[i+1]) break; if (i == VADDR_RING_SIZE-1) { printf("vaddr==%8x\tproc_slot==%d\tpte==%8x\tpte/%8x\n", vaddr, p - &proc[0], pte, *(int *)pte); panic("tlbmiss: stuck on same vaddr"); } }#endif TLBMISS_STUCK } else if (IS_KPTESEG(vaddr)) { extern char utlbmiss[], eutlbmiss[]; int is_utlbmiss = ep[EF_EPC] >= UT_VEC && ep[EF_EPC] < UT_VEC + (eutlbmiss - utlbmiss); if (!is_utlbmiss && !IS_Forkmap(vaddr)) { printf("epc= 0x%x, vaddr= 0x%x\n", ep[EF_EPC], vaddr); panic("kpteseg miss outside utlbmiss"); } uvpn = (struct pte *)vaddr - (struct pte *)KPTEBASE; if (uvpn >= btop(KUSIZE)) panic("kpteseg"); /* * set-up the EPC and SR so that return to place that * caused the original utlbmiss */ if (is_utlbmiss) { ep[EF_EPC] = ep[EF_K1]; ep[EF_SR] &= ~(SR_KUP|SR_IEP); ep[EF_SR] |= (ep[EF_SR] & (SR_KUO|SR_IEO)) >> 2; } pte = vtopte(p, uvpn); if (!pte) { /* * User referenced a bad page that caused a two * level miss. Drop in an invalid pte for the * user and retry the reference so that BADVADDR * can be fully determined for the signal handler. */ vaddr = (u_int)ptob(uvpn); tlbdropin(p->p_tlbpid, vaddr, 0); return(0); } /* * Map kpte window */ kvpn = btop((unsigned)pte - K2BASE); tpte = Sysmap[kvpn]; if (!tpte.pg_v) panic("tlbmiss page table not valid"); tpte.pg_g = 0;#if NOMEMCACHE==1 tpte.pg_n = 1;#endif ti = p->p_tlbinfo; if (p->p_tlbindx < NPAGEMAP) { ti += p->p_tlbindx; ti->lo.tl_word = *(unsigned *)&tpte; ti->hi.th_word = (unsigned)vaddr & TLBHI_VPNMASK; tlbwired(p->p_tlbindx+UPAGES, p->p_tlbpid, vaddr, tpte); p->p_tlbindx++; } else { tlbdropin(p->p_tlbpid, vaddr, tpte); } if (!is_utlbmiss) return(0); vaddr = (u_int)ptob(uvpn); ep[EF_BADVADDR] = vaddr; } else if (IS_KSEG2(vaddr)) { vpn -= btop(K2BASE); if (vpn < Syssize) { pte = &Sysmap[vpn]; if (!pte->pg_v) { printf("vaddr= 0x%x, pte= 0x%x\n", vaddr, *pte); printf("epc = 0x%x\n", ep[EF_EPC]); panic("tlbmiss on invalid kernel page"); }#if NOMEMCACHE==1 pte->pg_n = 1;#endif } } if (pte) { XPRINTF(XPR_TLB, "tlbmiss pte va: 0x%x pte: %r\n", vaddr, *(int *)pte, pte_desc, 0); if (!pte->pg_v) { /* if "no access" */ if (pte->pg_prot < PROT_URKR) return(SEXC_SEGV); return(SEXC_PAGEIN); } if (pte->pg_g) { tlbdropin(0, vaddr, *(int *)pte); } else if ((p->p_tlbpid != -1) || (CURRENT_CPUDATA->cpu_tps[p->p_tlbpid].tps_procpid == p->p_pid)) { tlbdropin(p->p_tlbpid, vaddr, *(int *)pte); } else { panic("tlbmiss no tlbpid assigned"); } return(0); } XPRINTF(XPR_TLB, "tlbmiss segv va 0x%x\n", vaddr, 0, 0, 0); return(SEXC_SEGV);}/* * Changes for ULTRIX include: * 1. if a shared memory segment, then account for some users having * read only and some users having read/write */tlbmod(ep, code, vaddr, cause)u_int *ep;{ register unsigned vpn; register struct pte *pte; register struct proc *p; register int shm_page = 0; int smindex; vpn = btop(vaddr); p = u.u_procp; pte = vtopte(p, vpn); if (!pte) panic("tlbmod on invalid pte"); XPRINTF(XPR_TLB, "tlbmod vaddr 0x%x pte %r\n", vaddr, *(int *)pte, pte_desc, 0); if (pte->pg_prot != PROT_UW) { if (isasmsv(p, vpn, &smindex) && /* SHMEM */ (p->p_sm[smindex].sm_pflag) == PROT_UW) { shm_page++; goto good; } return(SEXC_SEGV); }good: if (shm_page) { pte->pg_swapm = 1; tlbdropin(p->p_tlbpid, vaddr, (*(int *)pte | PG_M)); } else { pte->pg_m = 1; tlbdropin(p->p_tlbpid, vaddr, *(int *)pte); } return(0);}softnet(){ extern int netisr; register struct isrent { int value; int (*function)(); } *pisr; extern struct isrent netisr_tab[]; int s, signo; acksoftnet(); /* see if any "extreme" priority signals posted by the fpu code */ if (CURRENT_CPUDATA->cpu_fpe_event) { s = splfpu(); /* sync with fpu */ /* send the signals...lowest numbered (highest priority) first */ while(CURRENT_CPUDATA->cpu_fpe_sendsig) { signo=ffs(CURRENT_CPUDATA->cpu_fpe_sendsig); /* note signo is 1-32 */ CURRENT_CPUDATA->cpu_fpe_sendsig &= ~(1<<(signo-1)); splx(s); psignal(CURRENT_CPUDATA->cpu_fpe_event,signo); s = splfpu(); } CURRENT_CPUDATA->cpu_fpe_event = 0; /* no more */ splx(s); } pisr = netisr_tab; while(pisr->value != -1) { s = splimp(); if ((netisr & (1<<pisr->value)) && clear_bit_atomic(pisr->value, &netisr)) { splx(s); (*pisr->function)(); } else splx(s); pisr++; } if (CURRENT_CPUDATA->cpu_wto_event) { if (mmap_debug || (sm_killp(CURRENT_CPUDATA->cpu_wto_pfn) == -1)){ /* * log the information into error log buffer, * print the error info on the console and then crash. */ (*(cpup->log_errinfo))(CURRENT_CPUDATA->cpu_log_errinfo); (*(cpup->print_consinfo))(CURRENT_CPUDATA->cpu_consinfo); CURRENT_CPUDATA->cpu_wto_event = 0; panic("CPU write timeout"); } else CURRENT_CPUDATA->cpu_wto_event = 0; }}int traceopens = 0;syscall(ep, code, sr, cause)register u_int *ep;u_int code;{ register int regparams, nargs; register struct sysent *callp; register struct proc *p; register int *params; struct timeval syst; extern char *syscallnames[]; struct cpudata *pcpu; syst = u.u_ru.ru_stime; u.u_error = 0; if (!USERMODE(sr)) panic("syscall"); ep[EF_EPC] += 4; /* normal return executes next inst */ regparams = EF_A0; if (code >= nsysent) { callp = &sysent[0]; /* indir (illegal) */ ep[EF_EPC] -= 4; /* just leave pc at the syscall inst */ } else { callp = &sysent[code]; if (callp == sysent) { /* * indirect system call (syscall), first param is * sys call number */ code = ep[EF_A0]; regparams++; if (code >= nsysent) callp = &sysent[0]; else callp = &sysent[code]; } } u.u_eosys = NORMALRETURN; params = (int *)u.u_arg; for (nargs = callp->sy_narg; nargs && regparams <= EF_A3; nargs--) *params++ = ep[regparams++]; if (nargs) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -