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

📄 trap.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1992 OMRON Corporation. * Copyright (c) 1982, 1986, 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: trap.c 1.35 91/12/26$ * from: hp300/hp300/trap.c	8.4 (Berkeley) 9/23/93 * *	@(#)trap.c	8.5 (Berkeley) 12/6/93 */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/acct.h>#include <sys/kernel.h>#include <sys/signalvar.h>#include <sys/resourcevar.h>#include <sys/syscall.h>#include <sys/syslog.h>#include <sys/user.h>#ifdef KTRACE#include <sys/ktrace.h>#endif#include <machine/psl.h>#include <machine/trap.h>#include <machine/cpu.h>#include <machine/reg.h>#include <machine/mtpr.h>#include <vm/vm.h>#include <vm/pmap.h>struct	sysent	sysent[];int	nsysent;char	*trap_type[] = {	"Bus error",	"Address error",	"Illegal instruction",	"Zero divide",	"CHK instruction",	"TRAPV instruction",	"Privilege violation",	"Trace trap",	"MMU fault",	"SSIR trap",	"Format error",	"68881 exception",	"Coprocessor violation",	"Async system trap"};#define	TRAP_TYPES	(sizeof trap_type / sizeof trap_type[0])/* * Size of various exception stack frames (minus the standard 8 bytes) */short	exframesize[] = {	FMT0SIZE,	/* type 0 - normal (68020/030/040) */	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040) */	FMT3SIZE,	/* type 3 - FP post-instruction (68040) */	-1, -1, -1,	/* type 4-6 - undefined */	FMT7SIZE,	/* type 7 - access error (68040) */	58,		/* type 8 - bus fault (68010) */	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */	FMTASIZE,	/* type A - short bus fault (68020/030) */	FMTBSIZE,	/* type B - long bus fault (68020/030) */	-1, -1, -1, -1	/* type C-F - undefined */};#ifdef LUNA2#define KDFAULT(c)	(mmutype == MMU_68040 ? \			    ((c) & SSW4_TMMASK) == SSW4_TMKD : \			    ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))#define WRFAULT(c) 	(mmutype == MMU_68040 ? \			    ((c) & SSW4_RW) == 0 : \			    ((c) & (SSW_DF|SSW_RW)) == SSW_DF)#else#define KDFAULT(c)	(((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))#define WRFAULT(c)	(((c) & (SSW_DF|SSW_RW)) == SSW_DF)#endif#ifdef DEBUGint mmudebug = 0;int mmupid = -1;#define MDB_FOLLOW	1#define MDB_WBFOLLOW	2#define MDB_WBFAILED	4#define MDB_ISPID(p)	(p) == mmupid#endif/* * trap and syscall both need the following work done before returning * to user mode. */static inline voiduserret(p, fp, oticks, faultaddr, fromtrap)	register struct proc *p;	register struct frame *fp;	u_quad_t oticks;	u_int faultaddr;	int fromtrap;{	int sig, s;#ifdef LUNA2	int beenhere = 0;again:#endif	/* take pending signals */	while ((sig = CURSIG(p)) != 0)		postsig(sig);	p->p_priority = p->p_usrpri;	if (want_resched) {		/*		 * 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 ((sig = CURSIG(p)) != 0)			postsig(sig);	}	/*	 * If profiling, charge system time to the trapped pc.	 */	if (p->p_flag & P_PROFIL) {		extern int psratio;		addupc_task(p, fp->f_pc,			    (int)(p->p_sticks - oticks) * psratio);	}#ifdef LUNA2	/*	 * Deal with user mode writebacks (from trap, or from sigreturn).	 * If any writeback fails, go back and attempt signal delivery.	 * unless we have already been here and attempted the writeback	 * (e.g. bad address with user ignoring SIGSEGV).  In that case	 * we just return to the user without sucessfully completing	 * the writebacks.  Maybe we should just drop the sucker?	 */	if (mmutype == MMU_68040 && fp->f_format == FMT7) {		if (beenhere) {#ifdef DEBUG			if (mmudebug & MDB_WBFAILED)				printf(fromtrap ?		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);#endif		} else if (sig = writeback(fp, fromtrap)) {			beenhere = 1;			oticks = p->p_sticks;			trapsignal(p, sig, faultaddr);			goto again;		}	}#endif	curpriority = p->p_priority;}/* * Trap is called from locore to handle most types of processor traps, * including events such as simulated software interrupts/AST's. * System calls are broken out for efficiency. *//*ARGSUSED*/trap(type, code, v, frame)	int type;	unsigned code;	register unsigned v;	struct frame frame;{	register int i;	unsigned ucode;	register struct proc *p;	u_quad_t sticks;	unsigned ncode;	extern char fswintr[];	cnt.v_trap++;	p = curproc;	ucode = 0;	if (USERMODE(frame.f_sr)) {		type |= T_USER;		sticks = p->p_sticks;		p->p_md.md_regs = frame.f_regs;	}	switch (type) {	default:dopanic:		printf("trap type %d, code = %x, v = %x\n", type, code, v);		regdump(&frame, 128);		type &= ~T_USER;		if ((unsigned)type < TRAP_TYPES)			panic(trap_type[type]);		panic("trap");	case T_BUSERR:		/* kernel bus error */		if (!p->p_addr->u_pcb.pcb_onfault)			goto dopanic;		/*		 * If we have arranged to catch this fault in any of the		 * copy to/from user space routines, set PC to return to		 * indicated location and set flag informing buserror code		 * that it may need to clean up stack frame.		 */copyfault:		frame.f_stackadj = exframesize[frame.f_format];		frame.f_format = frame.f_vector = 0;		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;		return;	case T_BUSERR|T_USER:	/* bus error */	case T_ADDRERR|T_USER:	/* address error */		ucode = v;		i = SIGBUS;		break;#ifdef FPCOPROC	case T_COPERR:		/* kernel coprocessor violation */#endif	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */	case T_FMTERR:		/* ...just in case... */	/*	 * The user has most likely trashed the RTE or FP state info	 * in the stack frame of a signal handler.	 */		type |= T_USER;		printf("pid %d: kernel %s exception\n", p->p_pid,		       type==T_COPERR ? "coprocessor" : "format");		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;		i = sigmask(SIGILL);		p->p_sigignore &= ~i;		p->p_sigcatch &= ~i;		p->p_sigmask &= ~i;		i = SIGILL;		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */		break;#ifdef FPCOPROC	case T_COPERR|T_USER:	/* user coprocessor violation */	/* What is a proper response here? */		ucode = 0;		i = SIGFPE;		break;	case T_FPERR|T_USER:	/* 68881 exceptions */	/*	 * We pass along the 68881 status register which locore stashed	 * in code for us.  Note that there is a possibility that the	 * bit pattern of this register will conflict with one of the	 * FPE_* codes defined in signal.h.  Fortunately for us, the	 * only such codes we use are all in the range 1-7 and the low	 * 3 bits of the status register are defined as 0 so there is	 * no clash.	 */		ucode = code;		i = SIGFPE;		break;#endif#ifdef LUNA2	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */	case T_FPEMULD|T_USER:	/* unimplemented FP data type */		/* XXX need to FSAVE */		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",		       p->p_pid, p->p_comm,		       frame.f_format == 2 ? "instruction" : "data type",		       frame.f_pc, frame.f_fmt2.f_iaddr);		/* XXX need to FRESTORE */		i = SIGFPE;		break;#endif	case T_ILLINST|T_USER:	/* illegal instruction fault */	case T_PRIVINST|T_USER:	/* privileged instruction fault */		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */		i = SIGILL;		break;	case T_ZERODIV|T_USER:	/* Divide by zero */		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */		i = SIGFPE;		break;	case T_CHKINST|T_USER:	/* CHK instruction trap */		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */		i = SIGFPE;		break;	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */		i = SIGFPE;		break;	/*	 * XXX: Trace traps are a nightmare.	 *	 *	HP-UX uses trap #1 for breakpoints,	 *	HPBSD uses trap #2,	 *	SUN 3.x uses trap #15,	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).	 *	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.	 * SUN 3.x traps get passed through as T_TRAP15 and are not really	 * supported yet.	 */	case T_TRACE:		/* kernel trace trap */	case T_TRAP15:		/* SUN trace trap */		frame.f_sr &= ~PSL_T;		i = SIGTRAP;		break;	case T_TRACE|T_USER:	/* user trace trap */	case T_TRAP15|T_USER:	/* SUN user trace trap */		frame.f_sr &= ~PSL_T;		i = SIGTRAP;		break;	case T_ASTFLT:		/* system async trap, cannot happen */		goto dopanic;	case T_ASTFLT|T_USER:	/* user async trap */		astpending = 0;		/*		 * We check for software interrupts first.  This is because		 * they are at a higher level than ASTs, and on a VAX would		 * interrupt the AST.  We assume that if we are processing		 * an AST that we must be at IPL0 so we don't bother to		 * check.  Note that we ensure that we are at least at SIR		 * IPL while processing the SIR.		 */		spl1();		/* fall into... */	case T_SSIR:		/* software interrupt */	case T_SSIR|T_USER:		if (ssir & SIR_NET) {			siroff(SIR_NET);			cnt.v_soft++;			netintr();		}		if (ssir & SIR_CLOCK) {			siroff(SIR_CLOCK);			cnt.v_soft++;			softclock();		}		/*		 * If this was not an AST trap, we are all done.		 */		if (type != (T_ASTFLT|T_USER)) {			cnt.v_trap--;			return;		}		spl0();		if (p->p_flag & P_OWEUPC) {			p->p_flag &= ~P_OWEUPC;			ADDUPROF(p);		}		goto out;	case T_MMUFLT:		/* kernel mode page fault */		/*		 * If we were doing profiling ticks or other user mode		 * stuff from interrupt code, Just Say No.		 */		if (p->p_addr->u_pcb.pcb_onfault == fswintr)			goto copyfault;		/* fall into ... */	case T_MMUFLT|T_USER:	/* page fault */	    {		register vm_offset_t va;		register struct vmspace *vm = p->p_vmspace;		register vm_map_t map;		int rv;		vm_prot_t ftype;		extern vm_map_t kernel_map;#ifdef DEBUG		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",		       p->p_pid, code, v, frame.f_pc, frame.f_sr);#endif		/*		 * It is only a kernel address space fault iff:		 * 	1. (type & T_USER) == 0  and		 * 	2. pcb_onfault not set or		 *	3. pcb_onfault set but supervisor space data fault		 * The last can occur during an exec() copyin where the		 * argument space is lazy-allocated.		 */		if (type == T_MMUFLT &&		    (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))			map = kernel_map;		else			map = &vm->vm_map;		if (WRFAULT(code))			ftype = VM_PROT_READ | VM_PROT_WRITE;		else			ftype = VM_PROT_READ;		va = trunc_page((vm_offset_t)v);#ifdef DEBUG		if (map == kernel_map && va == 0) {			printf("trap: bad kernel access at %x\n", v);			goto dopanic;		}#endif		rv = vm_fault(map, va, ftype, FALSE);#ifdef DEBUG		if (rv && MDB_ISPID(p->p_pid))			printf("vm_fault(%x, %x, %x, 0) -> %x\n",			       map, va, ftype, rv);#endif		/*		 * If this was a stack access we keep track of the maximum		 * accessed stack size.  Also, if vm_fault gets a protection		 * failure it is due to accessing the stack region outside		 * the current limit and we need to reflect that as an access		 * error.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -