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

📄 trap.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
			(*(tc_slot_info[2].intr))			(tc_slot_info[2].unit);			if ((intr & KN03_INTR_SCSI) &&			tc_slot_info[KN03_SCSI_SLOT].intr)			(*(tc_slot_info[KN03_SCSI_SLOT].intr))			(tc_slot_info[KN03_SCSI_SLOT].unit);			if ((intr & KN03_INTR_LANCE) &&			tc_slot_info[KN03_LANCE_SLOT].intr)			(*(tc_slot_info[KN03_LANCE_SLOT].intr))			(tc_slot_info[KN03_LANCE_SLOT].unit);			if (user_warned && ((intr & KN03_INTR_PSWARN) == 0)) {			printf("%s\n", "Power supply ok now.");			user_warned = 0;		}		if ((intr & KN03_INTR_PSWARN) && (user_warned < 3)) {			user_warned++;			printf("%s\n", "Power supply overheating");		}	}	if (mask & MACH_INT_MASK_3)		kn03_errintr();	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |		MACH_SR_INT_ENA_CUR);}#endif /* DS5000_240 *//* * 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 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);	}	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/* *---------------------------------------------------------------------- * * MemErrorInterrupts -- *   pmax_errintr - for the DS2100/DS3100 *   kn02_errintr - for the DS5000/200 *   kn02ba_errintr - for the DS5000/1xx and DS5000/xx * *	Handler an interrupt for the control register. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidpmax_errintr(){	volatile u_short *sysCSRPtr =		(u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR);	u_short csr;	csr = *sysCSRPtr;	if (csr & KN01_CSR_MERR) {		printf("Memory error at 0x%x\n",			*(unsigned *)MACH_PHYS_TO_UNCACHED(KN01_SYS_ERRADR));		panic("Mem error interrupt");	}	*sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;}static voidkn02_errintr(){	u_int erradr, chksyn, physadr;	int i;	erradr = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR);	chksyn = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN);	*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;	MachEmptyWriteBuffer();	if (!(erradr & KN02_ERR_VALID))		return;	/* extract the physical word address and compensate for pipelining */	physadr = erradr & KN02_ERR_ADDRESS;	if (!(erradr & KN02_ERR_WRITE))		physadr = (physadr & ~0xfff) | ((physadr & 0xfff) - 5);	physadr <<= 2;	printf("%s memory %s %s error at 0x%x\n",		(erradr & KN02_ERR_CPU) ? "CPU" : "DMA",		(erradr & KN02_ERR_WRITE) ? "write" : "read",		(erradr & KN02_ERR_ECCERR) ? "ECC" : "timeout",		physadr);	if (erradr & KN02_ERR_ECCERR) {		*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN) = 0;		MachEmptyWriteBuffer();		printf("ECC 0x%x\n", chksyn);		/* check for a corrected, single bit, read error */		if (!(erradr & KN02_ERR_WRITE)) {			if (physadr & 0x4) {				/* check high word */				if (chksyn & KN02_ECC_SNGHI)					return;			} else {				/* check low word */				if (chksyn & KN02_ECC_SNGLO)					return;			}		}	}	panic("Mem error interrupt");}#ifdef DS5000_240static voidkn03_errintr(){	printf("erradr %x\n", *(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR));	*(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0;	MachEmptyWriteBuffer();}#endif /* DS5000_240 */static voidkn02ba_errintr(){	register int mer, adr, siz;	static int errintr_cnt = 0;	siz = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MSR);	mer = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MER);	adr = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_AER);	/* clear interrupt bit */	*(unsigned int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;	errintr_cnt++;	printf("(%d)%s%x [%x %x %x]\n", errintr_cnt,	       "Bad memory chip at phys ",	       kn02ba_recover_erradr(adr, mer),	       mer, siz, adr);}static unsignedkn02ba_recover_erradr(phys, mer)	register unsigned phys, mer;{	/* phys holds bits 28:2, mer knows which byte */	switch (mer & KMIN_MER_LASTBYTE) {	case KMIN_LASTB31:		mer = 3; break;	case KMIN_LASTB23:		mer = 2; break;	case KMIN_LASTB15:		mer = 1; break;	case KMIN_LASTB07:		mer = 0; break;	}	return ((phys & KMIN_AER_ADDR_MASK) | mer);}/* * 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();	inst = *(InstFmt *)instPC;#if 0	printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,		inst.word, fpcCSR); /* XXX */#endif	switch ((int)inst.JType.op) {	case OP_SPECIAL:		switch ((int)inst.RType.func) {		case OP_JR:		case OP_JALR:			retAddr = regsPtr[inst.RType.rs];			break;		default:			if (!allowNonBranch)				panic("MachEmulateBranch: Non-branch");			retAddr = instPC + 4;			break;		}		break;	case OP_BCOND:		switch ((int)inst.IType.rt) {		case OP_BLTZ:		case OP_BLTZAL:			if ((int)(regsPtr[inst.RType.rs]) < 0)				retAddr = GetBranchDest((InstFmt *)instPC);			else				retAddr = instPC + 8;			break;		case OP_BGEZAL:		case OP_BGEZ:			if ((int)(regsPtr[inst.RType.rs]) >= 0)				retAddr = GetBranchDest((InstFmt *)instPC);			else				retAddr = instPC + 8;			break;		default:			panic("MachEmulateBranch: Bad branch cond");		}		break;	case OP_J:	case OP_JAL:		retAddr = (inst.JType.target << 2) | 			((unsigned)instPC & 0xF0000000);		break;	case OP_BEQ:		if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])			retAddr = GetBranchDest((InstFmt *)instPC);		else			retAddr = instPC + 8;		break;	case OP_BNE:		if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])			retAddr = GetBranchDest((InstFmt *)instPC);		else			retAddr = instPC + 8;		break;	case OP_BLEZ:		if ((int)(regsPtr[inst.RType.rs]) <= 0)			retAddr = GetBranchDest((InstFmt *)instPC);		else			retAddr = instPC + 8;		break;	case OP_BGTZ:		if ((int)(regsPtr[inst.RType.rs]) > 0)			retAddr = GetBranchDest((InstFmt *)instPC);		else			retAddr = instPC + 8;		break;	case OP_COP1:		switch (inst.RType.rs) {		case OP_BCx:		case OP_BCy:			if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)				condition = fpcCSR & MACH_FPC_COND_BIT;			else				condition = !(fpcCSR & MACH_FPC_COND_BIT);			if (condition)				retAddr = GetBranchDest((InstFmt *)instPC);			else				retAddr = instPC + 8;			break;		default:			if (!allowNonBranch)				panic("MachEmulateBranch: Bad coproc branch instruction");			retAddr = instPC + 4;		}		break;	default:		if (!allowNonBranch)			panic("MachEmulateBranch: Non-branch instruction");		retAddr = instPC + 4;	}#if 0	printf("Target addr=%x\n", retAddr); /* XXX */#endif	return (retAddr);}unsignedGetBranchDest(InstPtr)	InstFmt *InstPtr;{	return ((unsigned)InstPtr + 4 + ((short)InstPtr->IType.imm << 2));}/* * This routine is called by procxmt() to single step one instruction. * We do this by storing a break instruction after the current instruction, * resuming execution, and then restoring the old instruction. */cpu_singlestep(p)	register struct proc *p;{	register unsigned va;	register int *locr0 = p->p_md.md_regs;	int i;	/* compute next address after current location */	va = MachEmulateBranch(locr0, locr0[PC], locr0[FSR], 1);	if (p->p_md.md_ss_addr || p->p_md.md_ss_addr == va ||	    !useracc((caddr_t)va, 4, B_READ)) {		printf("SS %s (%d): breakpoint already set at %x (va %x)\n",			p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */		return (EFAULT);	}	p->p_md.md_ss_addr = va;	p->p_md.md_ss_instr = fuiword((caddr_t)va);	i = suiword((caddr_t)va, MACH_BREAK_SSTEP);	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, MACH_BREAK_SSTEP);			(void) vm_map_protect(&p->p_vmspace->vm_map,				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);		}	}	if (i < 0)		return (EFAULT);#if 0	printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",		p->p_comm, p->p_pid, p->p_md.md_ss_addr,		p->p_md.md_ss_instr, locr0[PC], fuword((caddr_t)va)); /* XXX */#endif	return (0);}#ifdef DEBUGkdbpeek(addr){	if (addr & 3) {		printf("kdbpeek: unaligned address %x\n", addr);		return (-1);	}	return (*(int *)addr);}#define MIPS_JR_RA	0x03e00008	/* instruction code for jr ra *//* * Print a stack backtrace. */voidstacktrace(a0, a1, a2, a3)	int a0, a1, a2, a3;{	unsigned pc, sp, fp, ra, va, subr;	unsigned instr, mask;	InstFmt i;	int more, stksize;	int regs[3];	extern setsoftclock();	extern char start[], edata[];	cpu_getregs(regs);	/* get initial values from the exception frame */	sp = regs[0];	pc = regs[1];	ra = 0;	fp = regs[2];loop:	/* check for current PC in the kernel interrupt handler code */	if (pc >= (unsigned)MachKernIntr && pc < (unsigned)MachUserIntr) {		/* NOTE: the offsets depend on the code in locore.s */		printf("interrupt\n");		a0 = kdbpeek(sp + 36);		a1 = kdbpeek(sp + 40);		a2 = kdbpeek(sp + 44);		a3 = kdbpeek(sp + 48);		pc = kdbpeek(sp + 20);		ra = kdbpeek(sp + 92);		sp = kdbpeek(sp + 100);		fp = kdbpeek(sp + 104);	}	/* check for current PC in the exception handler code */	if (pc >= 0x80000000 && pc < (unsigned)setsoftclock) {		ra = 0;		subr = 0;		goto done;	}	/* check for bad PC */	if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {		printf("PC 0x%x: not in kernel\n", pc);		ra = 0;		subr = 0;		goto done;	}	/*	 * Find the beginning of the current subroutine by scanning backwards	 * from the current PC for the end of the previous subroutine.	 */	va = pc - sizeof(int);	while ((instr = kdbpeek(va)) != MIPS_JR_RA)		va -= sizeof(int);	va += 2 * sizeof(int);	/* skip back over branch & delay slot */	/* skip over nulls which might separate .o files */	while ((instr = kdbpeek(va)) == 0)		va += sizeof(int);	subr = va;	/* scan forwards to find stack size and any saved registers */	stksize = 0;	more = 3;	mask = 0;	for (; more; va += sizeof(int), more = (more == 3) ? 3 : more - 1) {		/* stop if hit our current position */		if (va >= pc)			break;		instr = kdbpeek(va);		i.word = instr;		switch (i.JType.op) {		case OP_SPECIAL:			switch (i.RType.func) {			case OP_JR:			case OP_JALR:				more = 2; /* stop after next instruction */				break;			case OP_SYSCALL:			case OP_BREAK:				more = 1; /* stop now */			};			break;		case OP_BCOND:		case OP_J:		case OP_JAL:		case OP_BEQ:		case OP_BNE:		case OP_BLEZ:		case OP_BGTZ:			more = 2; /* stop after next instruction */			break;		case OP_COP0:		case OP_COP1:		case OP_COP2:		case OP_COP3:			switch (i.RType.rs) {			case OP_BCx:			case OP_BCy:				more = 2; /* stop after next instruction */			};			break;		case OP_SW:			/* look for saved registers on the stack */			if (i.IType.rs != 29)				break;			/* only restore the first one */			if (mask & (1 << i.IType.rt))				break;			mask |= 1 << i.IType.rt;			switch (i.IType.rt) {			case 4: /* a0 */				a0 = kdbpeek(sp + (short)i.IType.imm);				break;			case 5: /* a1 */				a1 = kdbpeek(sp + (short)i.IType.imm);				break;			case 6: /* a2 */				a2 = kdbpeek(sp + (short)i.IType.imm);				break;			case 7: /* a3 */				a3 = kdbpeek(sp + (short)i.IType.imm);				break;			case 30: /* fp */				fp = kdbpeek(sp + (short)i.IType.imm);				break;			case 31: /* ra */				ra = kdbpeek(sp + (short)i.IType.imm);			}			break;		case OP_ADDI:		case OP_ADDIU:			/* look for stack pointer adjustment */			if (i.IType.rs != 29 || i.IType.rt != 29)				break;			stksize = (short)i.IType.imm;		}	}done:	printf("%x+%x (%x,%x,%x,%x) ra %x sz %d\n",		subr, pc - subr, a0, a1, a2, a3, ra, stksize);	if (ra) {		if (pc == ra && stksize == 0)			printf("stacktrace: loop!\n");		else {			pc = ra;			sp -= stksize;			goto loop;		}	}}#endif /* DEBUG */

⌨️ 快捷键说明

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