⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trap.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		 */		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 + -