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

📄 trap.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
			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);#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;		}		/* restore original instruction and clear BP  */		i = suiword((caddr_t)va, p->p_md.md_ss_instr);		if (i < 0) {			vm_offset_t sa, ea;			int rv;			sa = trunc_page((vm_offset_t)va);			ea = round_page((vm_offset_t)va+sizeof(int)-1);			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,				VM_PROT_DEFAULT, FALSE);			if (rv == KERN_SUCCESS) {				i = suiword((caddr_t)va, p->p_md.md_ss_instr);				(void) vm_map_protect(&p->p_vmspace->vm_map,					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,					FALSE);			}		}		if (i < 0) {			i = SIGTRAP;			break;		}		p->p_md.md_ss_addr = 0;		goto out;	    }	case T_RES_INST+T_USER:		i = SIGILL;		break;	case T_COP_UNUSABLE+T_USER:		if ((causeReg & MACH_CR_COP_ERR) != 0x10000000) {			i = SIGILL;	/* only FPU instructions allowed */			break;		}		MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs);		machFPCurProcPtr = p;		p->p_md.md_regs[PS] |= MACH_SR_COP_1_BIT;		p->p_md.md_flags |= MDP_FPUSED;		goto out;	case T_OVFLOW+T_USER:		i = SIGFPE;		break;	case T_ADDR_ERR_LD:	/* misaligned access */	case T_ADDR_ERR_ST:	/* misaligned access */	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */		if (i = ((struct pcb *)UADDR)->pcb_onfault) {			((struct pcb *)UADDR)->pcb_onfault = 0;			return (onfault_table[i]);		}		/* FALLTHROUGH */	default:	err:#ifdef KADB	    {		extern struct pcb kdbpcb;		if (USERMODE(statusReg))			kdbpcb = p->p_addr->u_pcb;		else {			kdbpcb.pcb_regs[ZERO] = 0;			kdbpcb.pcb_regs[AST] = ((int *)&args)[2];			kdbpcb.pcb_regs[V0] = ((int *)&args)[3];			kdbpcb.pcb_regs[V1] = ((int *)&args)[4];			kdbpcb.pcb_regs[A0] = ((int *)&args)[5];			kdbpcb.pcb_regs[A1] = ((int *)&args)[6];			kdbpcb.pcb_regs[A2] = ((int *)&args)[7];			kdbpcb.pcb_regs[A3] = ((int *)&args)[8];			kdbpcb.pcb_regs[T0] = ((int *)&args)[9];			kdbpcb.pcb_regs[T1] = ((int *)&args)[10];			kdbpcb.pcb_regs[T2] = ((int *)&args)[11];			kdbpcb.pcb_regs[T3] = ((int *)&args)[12];			kdbpcb.pcb_regs[T4] = ((int *)&args)[13];			kdbpcb.pcb_regs[T5] = ((int *)&args)[14];			kdbpcb.pcb_regs[T6] = ((int *)&args)[15];			kdbpcb.pcb_regs[T7] = ((int *)&args)[16];			kdbpcb.pcb_regs[T8] = ((int *)&args)[17];			kdbpcb.pcb_regs[T9] = ((int *)&args)[18];			kdbpcb.pcb_regs[RA] = ((int *)&args)[19];			kdbpcb.pcb_regs[MULLO] = ((int *)&args)[21];			kdbpcb.pcb_regs[MULHI] = ((int *)&args)[22];			kdbpcb.pcb_regs[PC] = pc;			kdbpcb.pcb_regs[SR] = statusReg;			bzero((caddr_t)&kdbpcb.pcb_regs[F0], 33 * sizeof(int));		}		if (kdb(causeReg, vadr, p, !USERMODE(statusReg)))			return (kdbpcb.pcb_regs[PC]);	    }#else#ifdef DEBUG		printf("trap: pid %d %s sig %d adr %x pc %x ra %x\n", p->p_pid,			p->p_comm, i, vadr, pc, p->p_md.md_regs[RA]); /* XXX */		trapDump("trap");#endif#endif		panic("trap");	}	trapsignal(p, i, ucode);out:	/*	 * Note: we should only get here if returning to user mode.	 */	/* take pending signals */	while ((i = CURSIG(p)) != 0)		postsig(i);	p->p_priority = p->p_usrpri;	astpending = 0;	if (want_resched) {		int s;		/*		 * 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 switch()'ed, 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 ((i = CURSIG(p)) != 0)			postsig(i);	}	/*	 * If profiling, charge system time to the trapped pc.	 */	if (p->p_flag & P_PROFIL) {		extern int psratio;		addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);	}	curpriority = p->p_priority;	return (pc);}int	badaddr_flag;/* * Handle an interrupt. * Called from MachKernIntr() or MachUserIntr() * Note: curproc might be NULL. */interrupt(statusReg, causeReg, pc)	unsigned statusReg;	/* status register at time of the exception */	unsigned causeReg;	/* cause register at time of exception */	unsigned pc;		/* program counter where to continue */{	register unsigned mask;	struct clockframe cf;	int oonfault = ((struct pcb *)UADDR)->pcb_onfault;#ifdef DEBUG	trp->status = statusReg;	trp->cause = causeReg;	trp->vadr = 0;	trp->pc = pc;	trp->ra = 0;	trp->code = 0;	if (++trp == &trapdebug[TRAPSIZE])		trp = trapdebug;#endif	mask = causeReg & statusReg;	/* pending interrupts & enable mask */	if (mask & MACH_INT_MASK_5) {		/* level 5 interrupt */		splx((MACH_SPL_MASK_8 & ~causeReg) | MACH_SR_INT_ENA_CUR);		printf("level 5 interrupt: PC %x CR %x SR %x\n",			pc, causeReg, statusReg);		causeReg &= ~MACH_INT_MASK_5;	}	if (mask & MACH_INT_MASK_4) {		/* level 4 interrupt */		/*		 * asynchronous bus error		 */		splx((MACH_SPL_MASK_7 & ~causeReg) | MACH_SR_INT_ENA_CUR);		*(char *)INTCLR0 = INTCLR0_BERR;		causeReg &= ~MACH_INT_MASK_4;#define BADADDR 1		if (oonfault == BADADDR) {		/* XXX */			badaddr_flag = 1;		} else {			printf("level 4 interrupt: PC %x CR %x SR %x\n",				pc, causeReg, statusReg);		}	}	if (mask & MACH_INT_MASK_3) {		/* level 3 interrupt */		/*		 * fp error		 */		splx((MACH_SPL_MASK_6 & ~causeReg) | MACH_SR_INT_ENA_CUR);		if (!USERMODE(statusReg)) {#ifdef DEBUG			trapDump("fpintr");#else			printf("FPU interrupt: PC %x CR %x SR %x\n",				pc, causeReg, statusReg);#endif		} else			MachFPInterrupt(statusReg, causeReg, pc);		causeReg &= ~MACH_INT_MASK_3;	}	if (mask & MACH_INT_MASK_2) {		/* level 2 interrupt */		register int stat;		splx((MACH_SPL_MASK_5 & ~causeReg) | MACH_SR_INT_ENA_CUR);		stat = *(volatile u_char *)INTST0;		if (stat & INTST0_TIMINT) {	/* timer */			static int led_count = 0;			*(volatile u_char *)INTCLR0 = INTCLR0_TIMINT;			cf.pc = pc;			cf.sr = statusReg;			hardclock(&cf);			if (++led_count > hz) {				led_count = 0;				*(volatile u_char *)DEBUG_PORT ^= DP_LED1;			}		}#if NBM > 0		if (stat & INTST0_KBDINT)	/* keyboard */			kbm_rint(SCC_KEYBOARD);#endif#if NMS > 0		if (stat & INTST0_MSINT)	/* mouse */			kbm_rint(SCC_MOUSE);#endif		causeReg &= ~MACH_INT_MASK_2;	}	if (mask & MACH_INT_MASK_1) {		/* level 1 interrupt */		splx((MACH_SPL_MASK_4 & ~causeReg) | MACH_SR_INT_ENA_CUR);		level1_intr();		causeReg &= ~MACH_INT_MASK_1;	}	if (mask & MACH_INT_MASK_0) {		/* level 0 interrupt */		splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR);		level0_intr();		causeReg &= ~MACH_INT_MASK_0;	}	splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR);	if (mask & MACH_SOFT_INT_MASK_0) {		struct clockframe cf;		clearsoftclock();		cnt.v_soft++;		cf.pc = pc;		cf.sr = statusReg;		softclock();	}	/* process network interrupt if we trapped or will very soon */	if ((mask & MACH_SOFT_INT_MASK_1) ||	    netisr && (statusReg & MACH_SOFT_INT_MASK_1)) {		clearsoftnet();		cnt.v_soft++;#ifdef INET		if (netisr & (1 << NETISR_ARP)) {			netisr &= ~(1 << NETISR_ARP);			arpintr();		}		if (netisr & (1 << NETISR_IP)) {			netisr &= ~(1 << NETISR_IP);			ipintr();		}#endif#ifdef NS		if (netisr & (1 << NETISR_NS)) {			netisr &= ~(1 << NETISR_NS);			nsintr();		}#endif#ifdef ISO		if (netisr & (1 << NETISR_ISO)) {			netisr &= ~(1 << NETISR_ISO);			clnlintr();		}#endif	}	/* restore onfault flag */	((struct pcb *)UADDR)->pcb_onfault = oonfault;}/* * This is called from MachUserIntr() if astpending is set. * This is very similar to the tail of trap(). */softintr(statusReg, pc)	unsigned statusReg;	/* status register at time of the exception */	unsigned pc;		/* program counter where to continue */{	register struct proc *p = curproc;	int sig;	cnt.v_soft++;	/* take pending signals */	while ((sig = CURSIG(p)) != 0)		postsig(sig);	p->p_priority = p->p_usrpri;	astpending = 0;	if (p->p_flag & P_OWEUPC) {		p->p_flag &= ~P_OWEUPC;		ADDUPROF(p);	}	if (want_resched) {		int s;		/*		 * 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 switch()'ed, 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);	}	curpriority = p->p_priority;}#ifdef DEBUGtrapDump(msg)	char *msg;{	register int i;	int s;	s = splhigh();	printf("trapDump(%s)\n", msg);	for (i = 0; i < TRAPSIZE; i++) {		if (trp == trapdebug)			trp = &trapdebug[TRAPSIZE - 1];		else			trp--;		if (trp->cause == 0)			break;		printf("%s: ADR %x PC %x CR %x SR %x\n",			trap_type[(trp->cause & MACH_CR_EXC_CODE) >>				MACH_CR_EXC_CODE_SHIFT],			trp->vadr, trp->pc, trp->cause, trp->status);		printf("   RA %x code %d\n", trp->ra, trp->code);	}	bzero(trapdebug, sizeof(trapdebug));	trp = trapdebug;	splx(s);}#endif/* * Return the resulting PC as if the branch was executed. */unsignedMachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch)	unsigned *regsPtr;	unsigned instPC;	unsigned fpcCSR;	int allowNonBranch;{	InstFmt inst;	unsigned retAddr;	int condition;	extern unsigned GetBranchDest();#if 0	printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,		*(unsigned *)instPC, fpcCSR);#endif	inst = *(InstFmt *)instPC;	switch ((int)inst.JType.op) {	case OP_SPECIAL:

⌨️ 快捷键说明

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