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

📄 trap.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1992, 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 and Ralph Campbell. * * 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.32 91/04/06$ * *	@(#)trap.c	8.5 (Berkeley) 1/11/94 */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/kernel.h>#include <sys/signalvar.h>#include <sys/syscall.h>#include <sys/user.h>#include <sys/buf.h>#ifdef KTRACE#include <sys/ktrace.h>#endif#include <net/netisr.h>#include <machine/trap.h>#include <machine/psl.h>#include <machine/reg.h>#include <machine/cpu.h>#include <machine/pte.h>#include <machine/mips_opcode.h>#include <vm/vm.h>#include <vm/vm_kern.h>#include <vm/vm_page.h>#include <pmax/pmax/clockreg.h>#include <pmax/pmax/kn01.h>#include <pmax/pmax/kn02.h>#include <pmax/pmax/kmin.h>#include <pmax/pmax/maxine.h>#include <pmax/pmax/kn03.h>#include <pmax/pmax/asic.h>#include <pmax/pmax/turbochannel.h>#include <pmax/stand/dec_prom.h>#include <asc.h>#include <sii.h>#include <le.h>#include <dc.h>struct	proc *machFPCurProcPtr;		/* pointer to last proc to use FP */extern void MachKernGenException();extern void MachUserGenException();extern void MachKernIntr();extern void MachUserIntr();extern void MachTLBModException();extern void MachTLBMissException();extern unsigned MachEmulateBranch();void (*machExceptionTable[])() = {/* * The kernel exception handlers. */	MachKernIntr,			/* external interrupt */	MachKernGenException,		/* TLB modification */	MachTLBMissException,		/* TLB miss (load or instr. fetch) */	MachTLBMissException,		/* TLB miss (store) */	MachKernGenException,		/* address error (load or I-fetch) */	MachKernGenException,		/* address error (store) */	MachKernGenException,		/* bus error (I-fetch) */	MachKernGenException,		/* bus error (load or store) */	MachKernGenException,		/* system call */	MachKernGenException,		/* breakpoint */	MachKernGenException,		/* reserved instruction */	MachKernGenException,		/* coprocessor unusable */	MachKernGenException,		/* arithmetic overflow */	MachKernGenException,		/* reserved */	MachKernGenException,		/* reserved */	MachKernGenException,		/* reserved *//* * The user exception handlers. */	MachUserIntr,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,	MachUserGenException,};char	*trap_type[] = {	"external interrupt",	"TLB modification",	"TLB miss (load or instr. fetch)",	"TLB miss (store)",	"address error (load or I-fetch)",	"address error (store)",	"bus error (I-fetch)",	"bus error (load or store)",	"system call",	"breakpoint",	"reserved instruction",	"coprocessor unusable",	"arithmetic overflow",	"reserved 13",	"reserved 14",	"reserved 15",};#ifdef DEBUG#define TRAPSIZE	10struct trapdebug {		/* trap history buffer for debugging */	u_int	status;	u_int	cause;	u_int	vadr;	u_int	pc;	u_int	ra;	u_int	code;} trapdebug[TRAPSIZE], *trp = trapdebug;#endifstatic void pmax_errintr();static void kn02_errintr(), kn02ba_errintr();#ifdef DS5000_240static void kn03_errintr();#endifstatic unsigned kn02ba_recover_erradr();extern tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];extern u_long kmin_tc3_imask, xine_tc3_imask;extern const struct callback *callv;#ifdef DS5000_240extern u_long kn03_tc3_imask;#endifint (*pmax_hardware_intr)() = (int (*)())0;extern volatile struct chiptime *Mach_clock_addr;/* * Handle an exception. * Called from MachKernGenException() or MachUserGenException() * when a processor trap occurs. * In the case of a kernel trap, we return the pc where to resume if * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc. */unsignedtrap(statusReg, causeReg, vadr, pc, args)	unsigned statusReg;	/* status register at time of the exception */	unsigned causeReg;	/* cause register at time of exception */	unsigned vadr;		/* address (if any) the fault occured on */	unsigned pc;		/* program counter where to continue */{	register int type, i;	unsigned ucode = 0;	register struct proc *p = curproc;	u_quad_t sticks;	vm_prot_t ftype;	extern unsigned onfault_table[];#ifdef DEBUG	trp->status = statusReg;	trp->cause = causeReg;	trp->vadr = vadr;	trp->pc = pc;	trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] :		p->p_md.md_regs[RA];	trp->code = 0;	if (++trp == &trapdebug[TRAPSIZE])		trp = trapdebug;#endif	cnt.v_trap++;	type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;	if (USERMODE(statusReg)) {		type |= T_USER;		sticks = p->p_sticks;	}	/*	 * Enable hardware interrupts if they were on before.	 * We only respond to software interrupts when returning to user mode.	 */	if (statusReg & MACH_SR_INT_ENA_PREV)		splx((statusReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);	switch (type) {	case T_TLB_MOD:		/* check for kernel address */		if ((int)vadr < 0) {			register pt_entry_t *pte;			register unsigned entry;			register vm_offset_t pa;			pte = kvtopte(vadr);			entry = pte->pt_entry;#ifdef DIAGNOSTIC			if (!(entry & PG_V) || (entry & PG_M))				panic("trap: ktlbmod: invalid pte");#endif			if (entry & PG_RO) {				/* write to read only page in the kernel */				ftype = VM_PROT_WRITE;				goto kernel_fault;			}			entry |= PG_M;			pte->pt_entry = entry;			vadr &= ~PGOFSET;			MachTLBUpdate(vadr, entry);			pa = entry & PG_FRAME;#ifdef ATTR			pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;#else			if (!IS_VM_PHYSADDR(pa))				panic("trap: ktlbmod: unmanaged page");			PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;#endif			return (pc);		}		/* FALLTHROUGH */	case T_TLB_MOD+T_USER:	    {		register pt_entry_t *pte;		register unsigned entry;		register vm_offset_t pa;		pmap_t pmap = &p->p_vmspace->vm_pmap;		if (!(pte = pmap_segmap(pmap, vadr)))			panic("trap: utlbmod: invalid segmap");		pte += (vadr >> PGSHIFT) & (NPTEPG - 1);		entry = pte->pt_entry;#ifdef DIAGNOSTIC		if (!(entry & PG_V) || (entry & PG_M))			panic("trap: utlbmod: invalid pte");#endif		if (entry & PG_RO) {			/* write to read only page */			ftype = VM_PROT_WRITE;			goto dofault;		}		entry |= PG_M;		pte->pt_entry = entry;		vadr = (vadr & ~PGOFSET) |			(pmap->pm_tlbpid << VMMACH_TLB_PID_SHIFT);		MachTLBUpdate(vadr, entry);		pa = entry & PG_FRAME;#ifdef ATTR		pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;#else		if (!IS_VM_PHYSADDR(pa))			panic("trap: utlbmod: unmanaged page");		PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;#endif		if (!USERMODE(statusReg))			return (pc);		goto out;	    }	case T_TLB_LD_MISS:	case T_TLB_ST_MISS:		ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;		/* check for kernel address */		if ((int)vadr < 0) {			register vm_offset_t va;			int rv;		kernel_fault:			va = trunc_page((vm_offset_t)vadr);			rv = vm_fault(kernel_map, va, ftype, FALSE);			if (rv == KERN_SUCCESS)				return (pc);			if (i = ((struct pcb *)UADDR)->pcb_onfault) {				((struct pcb *)UADDR)->pcb_onfault = 0;				return (onfault_table[i]);			}			goto err;		}		/*		 * It is an error for the kernel to access user space except		 * through the copyin/copyout routines.		 */		if ((i = ((struct pcb *)UADDR)->pcb_onfault) == 0)			goto err;		/* check for fuswintr() or suswintr() getting a page fault */		if (i == 4)			return (onfault_table[i]);		goto dofault;	case T_TLB_LD_MISS+T_USER:		ftype = VM_PROT_READ;		goto dofault;	case T_TLB_ST_MISS+T_USER:		ftype = VM_PROT_WRITE;	dofault:	    {		register vm_offset_t va;		register struct vmspace *vm;		register vm_map_t map;		int rv;		vm = p->p_vmspace;		map = &vm->vm_map;		va = trunc_page((vm_offset_t)vadr);		rv = vm_fault(map, va, ftype, FALSE);		/*		 * 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.		 */		if ((caddr_t)va >= vm->vm_maxsaddr) {			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 (!USERMODE(statusReg))				return (pc);			goto out;		}		if (!USERMODE(statusReg)) {			if (i = ((struct pcb *)UADDR)->pcb_onfault) {				((struct pcb *)UADDR)->pcb_onfault = 0;				return (onfault_table[i]);			}			goto err;		}		ucode = vadr;		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;		break;	    }	case T_ADDR_ERR_LD+T_USER:	/* misaligned or kseg access */	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to cpu */	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to cpu */		i = SIGSEGV;		break;	case T_SYSCALL+T_USER:	    {		register int *locr0 = p->p_md.md_regs;		register struct sysent *callp;		unsigned int code;		int numsys;		struct args {			int i[8];		} args;		int rval[2];		struct sysent *systab;		extern int nsysent;#ifdef ULTRIXCOMPAT		extern struct sysent ultrixsysent[];		extern int ultrixnsysent;#endif		cnt.v_syscall++;		/* compute next PC after syscall instruction */		if ((int)causeReg < 0)			locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0);		else			locr0[PC] += 4;		systab = sysent;		numsys = nsysent;#ifdef ULTRIXCOMPAT		if (p->p_md.md_flags & MDP_ULTRIX) {			systab = ultrixsysent;			numsys = ultrixnsysent;		}#endif		code = locr0[V0];		switch (code) {		case SYS_syscall:			/*			 * Code is first argument, followed by actual args.			 */			code = locr0[A0];			if (code >= numsys)				callp = &systab[SYS_syscall]; /* (illegal) */			else				callp = &systab[code];			i = callp->sy_narg;			args.i[0] = locr0[A1];			args.i[1] = locr0[A2];			args.i[2] = locr0[A3];			if (i > 3) {				i = copyin((caddr_t)(locr0[SP] +						4 * sizeof(int)),					(caddr_t)&args.i[3],					(u_int)(i - 3) * sizeof(int));				if (i) {					locr0[V0] = i;					locr0[A3] = 1;#ifdef KTRACE					if (KTRPOINT(p, KTR_SYSCALL))						ktrsyscall(p->p_tracep, code,							callp->sy_narg, args.i);#endif					goto done;				}			}			break;		case SYS___syscall:			/*			 * Like syscall, but code is a quad, so as to maintain			 * quad alignment for the rest of the arguments.			 */			code = locr0[A0 + _QUAD_LOWWORD];			if (code >= numsys)				callp = &systab[SYS_syscall]; /* (illegal) */			else				callp = &systab[code];			i = callp->sy_narg;			args.i[0] = locr0[A2];			args.i[1] = locr0[A3];			if (i > 2) {				i = copyin((caddr_t)(locr0[SP] +						4 * sizeof(int)),					(caddr_t)&args.i[2],					(u_int)(i - 2) * sizeof(int));				if (i) {					locr0[V0] = i;					locr0[A3] = 1;#ifdef KTRACE					if (KTRPOINT(p, KTR_SYSCALL))						ktrsyscall(p->p_tracep, code,							callp->sy_narg, args.i);#endif					goto done;				}			}			break;		default:			if (code >= numsys)				callp = &systab[SYS_syscall]; /* (illegal) */			else				callp = &systab[code];			i = callp->sy_narg;			args.i[0] = locr0[A0];			args.i[1] = locr0[A1];			args.i[2] = locr0[A2];			args.i[3] = locr0[A3];			if (i > 4) {				i = copyin((caddr_t)(locr0[SP] +						4 * sizeof(int)),					(caddr_t)&args.i[4],					(u_int)(i - 4) * sizeof(int));				if (i) {					locr0[V0] = i;					locr0[A3] = 1;#ifdef KTRACE					if (KTRPOINT(p, KTR_SYSCALL))						ktrsyscall(p->p_tracep, code,							callp->sy_narg, args.i);#endif					goto done;				}			}		}#ifdef KTRACE		if (KTRPOINT(p, KTR_SYSCALL))			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);#endif		rval[0] = 0;		rval[1] = locr0[V1];#ifdef DEBUG		if (trp == trapdebug)			trapdebug[TRAPSIZE - 1].code = code;		else			trp[-1].code = code;#endif		i = (*callp->sy_call)(p, &args, rval);		/*		 * Reinitialize proc pointer `p' as it may be different		 * if this is a child returning from fork syscall.		 */		p = curproc;		locr0 = p->p_md.md_regs;#ifdef DEBUG		{ int s;		s = splhigh();		trp->status = statusReg;		trp->cause = causeReg;		trp->vadr = locr0[SP];		trp->pc = locr0[PC];		trp->ra = locr0[RA];		trp->code = -code;		if (++trp == &trapdebug[TRAPSIZE])			trp = trapdebug;		splx(s);		}#endif		switch (i) {		case 0:			locr0[V0] = rval[0];			locr0[V1] = rval[1];			locr0[A3] = 0;			break;		case ERESTART:			locr0[PC] = pc;			break;		case EJUSTRETURN:			break;	/* nothing to do */		default:			locr0[V0] = i;			locr0[A3] = 1;		}	done:#ifdef KTRACE		if (KTRPOINT(p, KTR_SYSRET))			ktrsysret(p->p_tracep, code, i, rval[0]);#endif		goto out;	    }	case T_BREAK+T_USER:	    {		register unsigned va, instr;		/* compute address of break instruction */		va = pc;		if ((int)causeReg < 0)			va += 4;		/* read break instruction */		instr = fuiword((caddr_t)va);#if 0		printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",			p->p_comm, p->p_pid, instr, pc,			p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */#endif#ifdef KADB		if (instr == MACH_BREAK_BRKPT || instr == MACH_BREAK_SSTEP)			goto err;#endif		if (p->p_md.md_ss_addr != va || instr != MACH_BREAK_SSTEP) {			i = SIGTRAP;			break;		}

⌨️ 快捷键说明

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