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

📄 trap.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * 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, Lawrence Berkeley Laboratory. * * 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. * *	@(#)trap.c	8.4 (Berkeley) 9/23/93 * * from: $Header: trap.c,v 1.34 93/05/28 04:34:50 torek Exp $ */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/kernel.h>#include <sys/malloc.h>#include <sys/resource.h>#include <sys/signal.h>#include <sys/wait.h>#include <sys/syscall.h>#include <sys/syslog.h>#ifdef KTRACE#include <sys/ktrace.h>#endif#include <vm/vm_kern.h>#include <machine/cpu.h>#include <machine/ctlreg.h>#include <machine/frame.h>#include <machine/trap.h>#define	offsetof(s, f) ((int)&((s *)0)->f)extern int cold;int	rwindow_debug = 0;/* * Initial FPU state is all registers == all 1s, everything else == all 0s. * This makes every floating point register a signalling NaN, with sign bit * set, no matter how it is interpreted.  Appendix N of the Sparc V8 document * seems to imply that we should do this, and it does make sense. */struct	fpstate initfpstate = {	{ ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,	  ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 }};/* * There are more than 100 trap types, but most are unused. * * Trap type 0 is taken over as an `Asynchronous System Trap'. * This is left-over Vax emulation crap that should be fixed. */static const char T[] = "trap";const char *trap_type[] = {	/* non-user vectors */	"ast",			/* 0 */	"text fault",		/* 1 */	"illegal instruction",	/* 2 */	"privileged instruction",/*3 */	"fp disabled",		/* 4 */	"window overflow",	/* 5 */	"window underflow",	/* 6 */	"alignment fault",	/* 7 */	"fp exception",		/* 8 */	"data fault",		/* 9 */	"tag overflow",		/* 0a */	T, T, T, T, T, T,	/* 0b..10 */	"level 1 int",		/* 11 */	"level 2 int",		/* 12 */	"level 3 int",		/* 13 */	"level 4 int",		/* 14 */	"level 5 int",		/* 15 */	"level 6 int",		/* 16 */	"level 7 int",		/* 17 */	"level 8 int",		/* 18 */	"level 9 int",		/* 19 */	"level 10 int",		/* 1a */	"level 11 int",		/* 1b */	"level 12 int",		/* 1c */	"level 13 int",		/* 1d */	"level 14 int",		/* 1e */	"level 15 int",		/* 1f */	T, T, T, T, T, T, T, T,	/* 20..27 */	T, T, T, T, T, T, T, T,	/* 28..2f */	T, T, T, T, T, T,	/* 30..35 */	"cp disabled",		/* 36 */	T,			/* 37 */	T, T, T, T, T, T, T, T,	/* 38..3f */	"cp exception",		/* 40 */	T, T, T, T, T, T, T,	/* 41..47 */	T, T, T, T, T, T, T, T,	/* 48..4f */	T, T, T, T, T, T, T, T,	/* 50..57 */	T, T, T, T, T, T, T, T,	/* 58..5f */	T, T, T, T, T, T, T, T,	/* 60..67 */	T, T, T, T, T, T, T, T,	/* 68..6f */	T, T, T, T, T, T, T, T,	/* 70..77 */	T, T, T, T, T, T, T, T,	/* 78..7f */	/* user (software trap) vectors */	"sun syscall",		/* 80 */	"breakpoint",		/* 81 */	"zero divide",		/* 82 */	"flush windows",	/* 83 */	"clean windows",	/* 84 */	"range check",		/* 85 */	"fix align",		/* 86 */	"integer overflow",	/* 87 */	"kgdb exec",		/* 88 */	"syscall"		/* 89 */};#define	N_TRAP_TYPES	(sizeof trap_type / sizeof *trap_type)/* * Define the code needed before returning to user mode, for * trap, mem_access_fault, and syscall. */static inline voiduserret(struct proc *p, int pc, u_quad_t oticks){	int sig;	/* take pending signals */	while ((sig = CURSIG(p)) != 0)		postsig(sig);	p->p_priority = p->p_usrpri;	if (want_ast) {		want_ast = 0;		if (p->p_flag & P_OWEUPC) {			p->p_flag &= ~P_OWEUPC;			ADDUPROF(p);		}	}	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.		 */		(void) splstatclock();		setrunqueue(p);		p->p_stats->p_ru.ru_nivcsw++;		mi_switch();		(void) spl0();		while ((sig = CURSIG(p)) != 0)			postsig(sig);	}	/*	 * If profiling, charge recent system time to the trapped pc.	 */	if (p->p_flag & P_PROFIL)		addupc_task(p, pc, (int)(p->p_sticks - oticks));	curpriority = p->p_priority;}/* * If someone stole the FPU while we were away, do not enable it * on return.  This is not done in userret() above as it must follow * the ktrsysret() in syscall().  Actually, it is likely that the * ktrsysret should occur before the call to userret. */static inline void share_fpu(struct proc *p, struct trapframe *tf) {	if ((tf->tf_psr & PSR_EF) != 0 && fpproc != p)		tf->tf_psr &= ~PSR_EF;}/* * Called from locore.s trap handling, for non-MMU-related traps. * (MMU-related traps go through mem_access_fault, below.) */trap(type, psr, pc, tf)	register unsigned type;	register int psr, pc;	register struct trapframe *tf;{	register struct proc *p;	register struct pcb *pcb;	register int n;	u_quad_t sticks;	/* This steps the PC over the trap. */#define	ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4)	cnt.v_trap++;	/*	 * Generally, kernel traps cause a panic.  Any exceptions are	 * handled early here.	 */	if (psr & PSR_PS) {		/*		 * Storing %fsr in cpu_attach will cause this trap		 * even though the fpu has been enabled, if and only		 * if there is no FPU.		 */		if (type == T_FPDISABLED && cold) {			ADVANCE;			return;		}		goto dopanic;	}	if ((p = curproc) == NULL)		p = &proc0;	sticks = p->p_sticks;	pcb = &p->p_addr->u_pcb;	p->p_md.md_tf = tf;	/* for ptrace/signals */	switch (type) {	default:		if (type < 0x80) {dopanic:			printf("trap type 0x%x: pc=%x npc=%x psr=%b\n",			    type, pc, tf->tf_npc, psr, PSR_BITS);			panic(type < N_TRAP_TYPES ? trap_type[type] : T);			/* NOTREACHED */		}		/* the following message is gratuitous */		/* ... but leave it in until we find anything */		printf("%s[%d]: unimplemented software trap 0x%x\n",		    p->p_comm, p->p_pid, type);		trapsignal(p, SIGILL, type);		break;	case T_AST:		break;	/* the work is all in userret() */	case T_ILLINST:		trapsignal(p, SIGILL, 0);	/* XXX code?? */		break;	case T_PRIVINST:		trapsignal(p, SIGILL, 0);	/* XXX code?? */		break;	case T_FPDISABLED: {		register struct fpstate *fs = p->p_md.md_fpstate;		if (fs == NULL) {			fs = malloc(sizeof *fs, M_SUBPROC, M_WAITOK);			*fs = initfpstate;			p->p_md.md_fpstate = fs;		}		/*		 * If we have not found an FPU, we have to emulate it.		 */		if (!foundfpu) {#ifdef notyet			fpu_emulate(p, tf, fs);			break;#else			trapsignal(p, SIGFPE, 0);	/* XXX code?? */			break;#endif		}		/*		 * We may have more FPEs stored up and/or ops queued.		 * If they exist, handle them and get out.  Otherwise,		 * resolve the FPU state, turn it on, and try again.		 */		if (fs->fs_qsize) {			fpu_cleanup(p, fs);			break;		}		if (fpproc != p) {		/* we do not have it */			if (fpproc != NULL)	/* someone else had it */				savefpstate(fpproc->p_md.md_fpstate);			loadfpstate(fs);			fpproc = p;		/* now we do have it */		}		tf->tf_psr |= PSR_EF;		break;	}	case T_WINOF:		if (rwindow_save(p))			sigexit(p, SIGILL);		break;#define read_rw(src, dst) \	copyin((caddr_t)(src), (caddr_t)(dst), sizeof(struct rwindow))	case T_RWRET:		/*		 * T_RWRET is a window load needed in order to rett.		 * It simply needs the window to which tf->tf_out[6]		 * (%sp) points.  There are no user or saved windows now.		 * Copy the one from %sp into pcb->pcb_rw[0] and set		 * nsaved to -1.  If we decide to deliver a signal on		 * our way out, we will clear nsaved.		 */if (pcb->pcb_uw || pcb->pcb_nsaved) panic("trap T_RWRET 1");if (rwindow_debug)printf("%s[%d]: rwindow: pcb<-stack: %x\n", p->p_comm, p->p_pid, tf->tf_out[6]);		if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0]))			sigexit(p, SIGILL);if (pcb->pcb_nsaved) panic("trap T_RWRET 2");		pcb->pcb_nsaved = -1;		/* mark success */		break;	case T_WINUF:		/*		 * T_WINUF is a real window underflow, from a restore		 * instruction.  It needs to have the contents of two		 * windows---the one belonging to the restore instruction		 * itself, which is at its %sp, and the one belonging to		 * the window above, which is at its %fp or %i6---both		 * in the pcb.  The restore's window may still be in		 * the cpu; we need to force it out to the stack.		 */if (rwindow_debug)printf("%s[%d]: rwindow: T_WINUF 0: pcb<-stack: %x\n",p->p_comm, p->p_pid, tf->tf_out[6]);		write_user_windows();		if (rwindow_save(p) || read_rw(tf->tf_out[6], &pcb->pcb_rw[0]))			sigexit(p, SIGILL);if (rwindow_debug)printf("%s[%d]: rwindow: T_WINUF 1: pcb<-stack: %x\n",p->p_comm, p->p_pid, pcb->pcb_rw[0].rw_in[6]);		if (read_rw(pcb->pcb_rw[0].rw_in[6], &pcb->pcb_rw[1]))			sigexit(p, SIGILL);if (pcb->pcb_nsaved) panic("trap T_WINUF");		pcb->pcb_nsaved = -1;		/* mark success */		break;	case T_ALIGN:		trapsignal(p, SIGBUS, 0);	/* XXX code?? */		break;	case T_FPE:		/*		 * Clean up after a floating point exception.		 * fpu_cleanup can (and usually does) modify the		 * state we save here, so we must `give up' the FPU		 * chip context.  (The software and hardware states		 * will not match once fpu_cleanup does its job, so		 * we must not save again later.)		 */		if (p != fpproc)			panic("fpe without being the FP user");		savefpstate(p->p_md.md_fpstate);		fpproc = NULL;		/* tf->tf_psr &= ~PSR_EF; */	/* share_fpu will do this */		fpu_cleanup(p, p->p_md.md_fpstate);		/* fpu_cleanup posts signals if needed */#if 0		/* ??? really never??? */		ADVANCE;#endif		break;	case T_TAGOF:		trapsignal(p, SIGEMT, 0);	/* XXX code?? */		break;	case T_CPDISABLED:		uprintf("coprocessor instruction\n");	/* XXX */		trapsignal(p, SIGILL, 0);	/* XXX code?? */		break;

⌨️ 快捷键说明

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