📄 trap.c
字号:
*/ if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) { if (rv == KERN_SUCCESS) { unsigned nss; nss = clrnd(btoc(USRSTACK-(unsigned)va)); if (nss > vm->vm_ssize) vm->vm_ssize = nss; } else if (rv == KERN_PROTECTION_FAILURE) rv = KERN_INVALID_ADDRESS; } if (rv == KERN_SUCCESS) { if (type == T_MMUFLT) {#ifdef LUNA2 if (mmutype == MMU_68040) (void) writeback(&frame, 1);#endif return; } goto out; } if (type == T_MMUFLT) { if (p->p_addr->u_pcb.pcb_onfault) goto copyfault; printf("vm_fault(%x, %x, %x, 0) -> %x\n", map, va, ftype, rv); printf(" type %x, code [mmu,,ssw]: %x\n", type, code); goto dopanic; } ucode = v; i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; break; } } trapsignal(p, i, ucode); if ((type & T_USER) == 0) return;out: userret(p, &frame, sticks, v, 1);}#ifdef LUNA2#ifdef DEBUGstruct writebackstats { int calls; int cpushes; int move16s; int wb1s, wb2s, wb3s; int wbsize[4];} wbstats;char *f7sz[] = { "longword", "byte", "word", "line" };char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", "M-code", "k-data", "k-code", "RES" };char wberrstr[] = "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";#endifwriteback(fp, docachepush) struct frame *fp; int docachepush;{ register struct fmt7 *f = &fp->f_fmt7; register struct proc *p = curproc; int err = 0; u_int fa; caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;#ifdef DEBUG if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); dumpssw(f->f_ssw); } wbstats.calls++;#endif /* * Deal with special cases first. */ if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { /* * Dcache push fault. * Line-align the address and write out the push data to * the indicated physical address. */#ifdef DEBUG if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { printf(" pushing %s to PA %x, data %x", f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], f->f_fa, f->f_pd0); if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) printf("/%x/%x/%x", f->f_pd1, f->f_pd2, f->f_pd3); printf("\n"); } if (f->f_wb1s & SSW4_WBSV) panic("writeback: cache push with WB1S valid"); wbstats.cpushes++;#endif /* * XXX there are security problems if we attempt to do a * cache push after a signal handler has been called. */ if (docachepush) { pmap_enter(kernel_pmap, (vm_offset_t)vmmap, trunc_page(f->f_fa), VM_PROT_WRITE, TRUE); fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16); DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa)); pmap_remove(kernel_pmap, (vm_offset_t)vmmap, (vm_offset_t)&vmmap[NBPG]); } else printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", p->p_pid, p->p_comm, p->p_ucred->cr_uid); } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { /* * MOVE16 fault. * Line-align the address and write out the push data to * the indicated virtual address. */#ifdef DEBUG if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, f->f_pd2, f->f_pd3); if (f->f_wb1s & SSW4_WBSV) panic("writeback: MOVE16 with WB1S valid"); wbstats.move16s++;#endif if (KDFAULT(f->f_wb1s)) bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16); else err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); if (err) { fa = f->f_fa & ~0xF;#ifdef DEBUG if (mmudebug & MDB_WBFAILED) printf(wberrstr, p->p_pid, p->p_comm, "MOVE16", fp->f_pc, f->f_fa, f->f_fa & ~0xF, f->f_pd0);#endif } } else if (f->f_wb1s & SSW4_WBSV) { /* * Writeback #1. * Position the "memory-aligned" data and write it out. */ register u_int wb1d = f->f_wb1d; register int off;#ifdef DEBUG if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); wbstats.wb1s++; wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;#endif off = (f->f_wb1a & 3) * 8; switch (f->f_wb1s & SSW4_SZMASK) { case SSW4_SZLW: if (off) wb1d = (wb1d >> (32 - off)) | (wb1d << off); if (KDFAULT(f->f_wb1s)) *(long *)f->f_wb1a = wb1d; else err = suword((caddr_t)f->f_wb1a, wb1d); break; case SSW4_SZB: off = 24 - off; if (off) wb1d >>= off; if (KDFAULT(f->f_wb1s)) *(char *)f->f_wb1a = wb1d; else err = subyte((caddr_t)f->f_wb1a, wb1d); break; case SSW4_SZW: off = (off + 16) % 32; if (off) wb1d = (wb1d >> (32 - off)) | (wb1d << off); if (KDFAULT(f->f_wb1s)) *(short *)f->f_wb1a = wb1d; else err = susword((caddr_t)f->f_wb1a, wb1d); break; } if (err) { fa = f->f_wb1a;#ifdef DEBUG if (mmudebug & MDB_WBFAILED) printf(wberrstr, p->p_pid, p->p_comm, "#1", fp->f_pc, f->f_fa, f->f_wb1a, f->f_wb1d);#endif } } /* * Deal with the "normal" writebacks. * * XXX writeback2 is known to reflect a LINE size writeback after * a MOVE16 was already dealt with above. Ignore it. */ if (err == 0 && (f->f_wb2s & SSW4_WBSV) && (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {#ifdef DEBUG if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); wbstats.wb2s++; wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;#endif switch (f->f_wb2s & SSW4_SZMASK) { case SSW4_SZLW: if (KDFAULT(f->f_wb2s)) *(long *)f->f_wb2a = f->f_wb2d; else err = suword((caddr_t)f->f_wb2a, f->f_wb2d); break; case SSW4_SZB: if (KDFAULT(f->f_wb2s)) *(char *)f->f_wb2a = f->f_wb2d; else err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); break; case SSW4_SZW: if (KDFAULT(f->f_wb2s)) *(short *)f->f_wb2a = f->f_wb2d; else err = susword((caddr_t)f->f_wb2a, f->f_wb2d); break; } if (err) { fa = f->f_wb2a;#ifdef DEBUG if (mmudebug & MDB_WBFAILED) { printf(wberrstr, p->p_pid, p->p_comm, "#2", fp->f_pc, f->f_fa, f->f_wb2a, f->f_wb2d); dumpssw(f->f_ssw); dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); }#endif } } if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {#ifdef DEBUG if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); wbstats.wb3s++; wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;#endif switch (f->f_wb3s & SSW4_SZMASK) { case SSW4_SZLW: if (KDFAULT(f->f_wb3s)) *(long *)f->f_wb3a = f->f_wb3d; else err = suword((caddr_t)f->f_wb3a, f->f_wb3d); break; case SSW4_SZB: if (KDFAULT(f->f_wb3s)) *(char *)f->f_wb3a = f->f_wb3d; else err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); break; case SSW4_SZW: if (KDFAULT(f->f_wb3s)) *(short *)f->f_wb3a = f->f_wb3d; else err = susword((caddr_t)f->f_wb3a, f->f_wb3d); break;#ifdef DEBUG case SSW4_SZLN: panic("writeback: wb3s indicates LINE write");#endif } if (err) { fa = f->f_wb3a;#ifdef DEBUG if (mmudebug & MDB_WBFAILED) printf(wberrstr, p->p_pid, p->p_comm, "#3", fp->f_pc, f->f_fa, f->f_wb3a, f->f_wb3d);#endif } } p->p_addr->u_pcb.pcb_onfault = oonfault; /* * Determine the cause of the failure if any translating to * a signal. If the corresponding VA is valid and RO it is * a protection fault (SIGBUS) otherwise consider it an * illegal reference (SIGSEGV). */ if (err) { if (vm_map_check_protection(&p->p_vmspace->vm_map, trunc_page(fa), round_page(fa), VM_PROT_READ) && !vm_map_check_protection(&p->p_vmspace->vm_map, trunc_page(fa), round_page(fa), VM_PROT_WRITE)) err = SIGBUS; else err = SIGSEGV; } return(err);}#ifdef DEBUGdumpssw(ssw) register u_short ssw;{ printf(" SSW: %x: ", ssw); if (ssw & SSW4_CP) printf("CP,"); if (ssw & SSW4_CU) printf("CU,"); if (ssw & SSW4_CT) printf("CT,"); if (ssw & SSW4_CM) printf("CM,"); if (ssw & SSW4_MA) printf("MA,"); if (ssw & SSW4_ATC) printf("ATC,"); if (ssw & SSW4_LK) printf("LK,"); if (ssw & SSW4_RW) printf("RW,"); printf(" SZ=%s, TT=%s, TM=%s\n", f7sz[(ssw & SSW4_SZMASK) >> 5], f7tt[(ssw & SSW4_TTMASK) >> 3], f7tm[ssw & SSW4_TMMASK]);}dumpwb(num, s, a, d) int num; u_short s; u_int a, d;{ register struct proc *p = curproc; vm_offset_t pa; printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); printf(" PA "); pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a); if (pa == 0) printf("<invalid address>"); else printf("%x, current value %x", pa, fuword((caddr_t)a)); printf("\n");}#endif#endif/* * Proces a system call. */syscall(code, frame) u_int code; struct frame frame;{ register caddr_t params; register struct sysent *callp; register struct proc *p; int error, opc, numsys, s; u_int argsize; struct args { int i[8]; } args; int rval[2]; u_quad_t sticks; cnt.v_syscall++; if (!USERMODE(frame.f_sr)) panic("syscall"); p = curproc; sticks = p->p_sticks; p->p_md.md_regs = frame.f_regs; opc = frame.f_pc - 2; callp = sysent, numsys = nsysent; params = (caddr_t)frame.f_regs[SP] + sizeof(int); switch (code) { case SYS_syscall: /* * Code is first argument, followed by actual args. */ code = fuword(params); params += sizeof(int); /* * XXX sigreturn requires special stack manipulation * that is only done if entered via the sigreturn * trap. Cannot allow it here so make sure we fail. */ if (code == SYS_sigreturn) code = numsys; break; case SYS___syscall: /* * Like syscall, but code is a quad, so as to maintain * quad alignment for the rest of the arguments. */ code = fuword(params + _QUAD_LOWWORD * sizeof(int)); params += sizeof(quad_t); break; default: /* nothing to do by default */ break; } if (code < numsys) callp += code; else callp += SYS_syscall; /* => nosys */ argsize = callp->sy_narg * sizeof(int); if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) {#ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);#endif goto bad; }#ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);#endif rval[0] = 0; rval[1] = frame.f_regs[D1]; error = (*callp->sy_call)(p, &args, rval); switch (error) { case 0: /* * Reinitialize proc pointer `p' as it may be different * if this is a child returning from fork syscall. */ p = curproc; frame.f_regs[D0] = rval[0]; frame.f_regs[D1] = rval[1]; frame.f_sr &= ~PSL_C; break; case ERESTART: frame.f_pc = opc; break; case EJUSTRETURN: break; /* nothing to do */ default: bad: frame.f_regs[D0] = error; frame.f_sr |= PSL_C; break; } userret(p, &frame, sticks, (u_int)0, 0);#ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p->p_tracep, code, error, rval[0]);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -