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

📄 trap.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
		u.u_error = copyin(ep[EF_SP]+4*sizeof(int), params,		    nargs*sizeof(int));		if (u.u_error)			goto done;	}	u.u_r.r_val1 = 0;	u.u_r.r_val2 = ep[EF_V1];	if (setjmp(&u.u_qsave)) {		if (CURRENT_CPUDATA->cpu_hlock) {			while(CURRENT_CPUDATA->cpu_hlock) {				mprintf("lock held on syscall exit %x pc %x\n",					CURRENT_CPUDATA->cpu_hlock,					CURRENT_CPUDATA->cpu_hlock->l_pc);				smp_unlock(CURRENT_CPUDATA->cpu_hlock);			}		}		if (u.u_error == 0 && u.u_eosys != RESTARTSYS)			u.u_error = EINTR;	} else {		if ( audswitch == 0) {#ifdef ultrix#ifdef SYS_TRACE	                /* trace it just before we do it! (only if open) */	                if (traceopens) {	                        syscall_trace(code,callp->sy_narg,BEFORE);	                        (*(callp->sy_call))(u.u_arg);	                        syscall_trace(code,callp->sy_narg,AFTER);	                } else#endif SYS_TRACE#endif ultrix			(*(callp->sy_call))(u.u_arg);		}		else {			u.u_narg = callp->sy_narg;			u.u_gno_indx = 0;			u.u_event = code;#ifdef ultrix#ifdef SYS_TRACE	                /* trace it just before we do it! (only if open) */	                if (traceopens) {	                        syscall_trace(code,callp->sy_narg,BEFORE);	                        (*(callp->sy_call))(u.u_arg);	                        syscall_trace(code,callp->sy_narg,AFTER);	                } else#endif SYS_TRACE#endif ultrix			(*(callp->sy_call))(u.u_arg);			if ( aud_param[code][AUD_NPARAM-1] != 'X' )				AUDIT_CALL ( code, u.u_error, u.u_r.r_val1, AUD_GNO|AUD_HDR|AUD_PRM|AUD_RES, (int *)0, 0 );		}	}done:	/*	 * a3 is returned to user 0 if indicate no errors on syscall,	 * non-zero otherwise	 */	if (u.u_eosys == NORMALRETURN) {		if (u.u_error) {			ep[EF_V0] = u.u_error;			ep[EF_A3] = 1;		} else {			ep[EF_V0] = u.u_r.r_val1;			ep[EF_V1] = u.u_r.r_val2;			ep[EF_A3] = 0;		}	} else if (u.u_eosys == RESTARTSYS)		ep[EF_EPC] -= 4;	/* else if (u.u_eosys == FULLRESTORE) */		/* returning from sigreturn, force full state restore */	p = u.u_procp;	if (p->p_cursig || ISSIG(p,0))		psig();	pcpu = CURRENT_CPUDATA;	if (smp) {		if (p->p_affinity != ALLCPU) {			if (p != pcpu->cpu_fpowner) {				p->p_affinity = ALLCPU;			}		}	}	pcpu->cpu_syscall++;	p->p_pri = p->p_usrpri;	if (pcpu->cpu_runrun) {		/*		 * Since we are u.u_procp, 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 setrq ourselves but before we		 * swtch()'ed, we might not be on the queue indicated by		 * our priority.		 */		(void) splclock();		smp_lock(&lk_rq,LK_RETRY);		setrq(p);		u.u_ru.ru_nivcsw++;		swtch();	}	/*	 * if single stepping this process, install breakpoints before	 * returning to user mode.  Do this here rather than in procxmt	 * so single stepping will work when signals are delivered.	 */	if (u.u_pcb.pcb_sstep)		install_bp();	if (u.u_prof.pr_scale > 1) {		int ticks = times_to_ticks(&u.u_ru.ru_stime,&syst);		if (ticks)			addupc(ep[EF_EPC], &u.u_prof, ticks);	}	/*	 * if u_eosys == FULLRESTORE, then force full state restore	 */	return (u.u_eosys == FULLRESTORE);}int iplmask[IPLSIZE];		/* afdfix: this can vary with cpu type */int nstrays;/* * TODO: pending interrupts now come for CAUSE reg which is passed as arg4 */kn01_intr(ep, code, sr, cause)u_int *ep;u_int code, sr, cause;{	register int req;	register int prevmask;	register int nintr = 0;	/* number of interrupts serviced */	extern struct reg_desc cause_desc[], sr_desc[];/*	XPRINTF(XPR_INTR, "intr cause=%r  sr=%r\n", cause, cause_desc,	    sr, sr_desc);*/	CURRENT_CPUDATA->cpu_inisr++;	prevmask = (sr & SR_IMASK);	cause &= prevmask;	/*	 * Should probably direct vector these	 */	if (req = ffintr(cause)) {		nintr++;		req--;		splx(iplmask[req]);/*		XPRINTF(XPR_INTR, "calling intr %d\n", req, 0, 0, 0);	*/		(*c0vec_tbl[req])(ep);	}	if (nintr == 0) {		nstrays++;	}	CURRENT_CPUDATA->cpu_intr += nintr;	CURRENT_CPUDATA->cpu_inisr--;}/* * Note: stray interrupts cannot happen on the PMAX system */stray_intr(ep)u_int *ep;{	unsigned cause, get_cause();	cause = get_cause();	mprintf("intr: stray interrupt\n");	mprintf("\tPC: 0x%x\n\tCause register: %R\n\tCause register: %R\n\tStatus register: %R\n",		ep[EF_EPC], ep[EF_CAUSE], cause_desc, cause, cause_desc,		ep[EF_SR], sr_desc);}/* * Interrupt for hard error comes here. * then we call system specific error handling routine. */memintr(ep)	u_int *ep;		/* exception frame ptr */{	if ((*(cpup->harderr_intr))(ep) < 0)		panic("no hard error interrupt routine configured");}buserror(ep)u_int *ep;{	/*	 * attempt to scrub the error by writing it to zero	 */	wbadaddr(ep[EF_BADVADDR] &~ (sizeof(int)-1), sizeof(int));}/* * nonexistent system call-- signal process (may want to handle it) * flag error if process won't see signal immediately * Q: should we do that all the time ?? */nosys(){	if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)		u.u_error = EINVAL;	psignal(u.u_procp, SIGSYS);}/* * Masks and constants for the rs field of "coprocessor instructions" (25-21) * which are branch on coprocessor condition instructions. */#define	COPz_BC_MASK	0x1a#define COPz_BC		0x08/* * Masks and constants for the rt field of "branch on coprocessor condition * instructions" (20-16). */#define	COPz_BC_TF_MASK	0x01#define	COPz_BC_TRUE	0x01#define	COPz_BC_FALSE	0x00#define	PC_JMP_MASK	0xf0000000/* * emulate_branch is used by fpuintr() to calculate the resulting pc of a * branch instruction.  It is passed a pointer to the exception frame, * the branch instruction and the floating point control and status register. * The routine returns the resulting pc.  This routine will panic() if it * is called with a non-branch instruction or one it does not know how to * emulate. */unsignedemulate_branch(ep, instr, fpc_csr)u_int *ep;unsigned instr;union fpc_csr fpc_csr;{    union mips_instruction cpu_instr;    long condition;    long rs, rt;	cpu_instr.word = instr;	/*	 * The values for the rs and rt registers are taken from the exception	 * frame and since there is space for the 4 argument save registers and	 * doesn't save register zero this is accounted for (the +3).	 */	if(cpu_instr.r_format.rs == 0)	    rs = 0;	else	    rs = ep[cpu_instr.r_format.rs + 3];	if(cpu_instr.r_format.rt == 0)	    rt = 0;	else	    rt = ep[cpu_instr.r_format.rt + 3];	switch(cpu_instr.i_format.opcode){	case spec_op:	    switch(cpu_instr.r_format.func){	    case jalr_op:		/* r31 has already been updated by the hardware */	    case jr_op:		return(rs);	    }	    break;	case jal_op:	    /* r31 has already been updated by the hardware */	case j_op:	    return(((ep[EF_EPC] + 4) & PC_JMP_MASK) |		   (cpu_instr.j_format.target << 2));	case beq_op:	    condition = rs == rt;	    goto conditional;	case bne_op:	    condition = rs != rt;	    goto conditional;	case blez_op:	    condition = rs <= 0;	    goto conditional;	case bgtz_op:	    condition = rs > 0;	    goto conditional;	case bcond_op:	    switch(cpu_instr.r_format.rt){	    case bltzal_op:		/* r31 has already been updated by the hardware */	    case bltz_op:		condition = rs < 0;		goto conditional;	    case bgezal_op:		/* r31 has already been updated by the hardware */	    case bgez_op:		condition = rs >= 0;		goto conditional;	    }	    break;	case cop1_op:	    if((cpu_instr.r_format.rs & COPz_BC_MASK) == COPz_BC){		if((cpu_instr.r_format.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)		    condition = fpc_csr.fc_struct.condition;		else		    condition = !(fpc_csr.fc_struct.condition);		goto conditional;	    }	}	/*	 * For all other instructions (including branch on co-processor 2 & 3)	 * we panic because this routine is only called when in the branch	 * delay slot (as indicated by the hardware).	 */	if (CURRENT_CPUDATA->cpu_noproc) {		printf("Unknown branch instruction = 0x%x\n", instr);		panic("Unknown branch instruction");	} else {				CURRENT_CPUDATA->cpu_fpe_event = u.u_procp;		CURRENT_CPUDATA->cpu_fpe_sendsig |= sigmask(SIGILL);		setsoftnet();					}conditional:	if(condition)	    return(ep[EF_EPC] + 4 + (cpu_instr.i_format.simmediate << 2));	else	    return(ep[EF_EPC] + 8);}/* * Fixade() is called to fix unaligned loads and stores.  It returns a * zero value if can fix it and a non-zero error code if it can't fix it. * Error codes are: *	1 == its a kernel access from user space. *	2 == we couldn't fixup the alignment. * * Fixade() modifies the destination register (general or * floating-point) for loads or the destination memory location for * stores.  Also the epc is advanced past the instruction (possibly to the * target of a branch). */fixade(ep, cause)register u_int *ep;u_int cause;{    union mips_instruction inst, branch_inst;    u_int addr, new_epc, word;    int error;	if(cause & CAUSE_BD){	    branch_inst.word = fuiword((caddr_t)ep[EF_EPC]);	    inst.word = fuiword((caddr_t)(ep[EF_EPC] + 4));	    if(branch_inst.i_format.opcode == cop1_op)		checkfp(u.u_procp, 0);	    new_epc = emulate_branch(ep, branch_inst.word, u.u_pcb.pcb_fpc_csr);	}	else{	    inst.word = fuiword((caddr_t)ep[EF_EPC]);	    new_epc = ep[EF_EPC] + 4;	}	addr = REGVAL(inst.i_format.rs) + inst.i_format.simmediate;	/*	 * The addresses of both the left and right parts of the reference	 * have to be checked.  If either is a kernel address it is an	 * illegal reference.	 */	if(addr >= K0BASE || addr+3 >= K0BASE)	    return(1);	error = 0;	switch(inst.i_format.opcode){	case lw_op:	    error = uload_word(addr, &word);	    if(inst.i_format.rt == 0)		break;	    else	    	ep[inst.i_format.rt+3] = word;	    break;	case lh_op:	    error = uload_half(addr, &word);	    if(inst.i_format.rt == 0)		break;	    else	    	ep[inst.i_format.rt+3] = word;	    break;	case lhu_op:	    error = uload_uhalf(addr, &word);	    if(inst.i_format.rt == 0)		break;	    else	    	ep[inst.i_format.rt+3] = word;	    break;	case lwc1_op:	    checkfp(u.u_procp, 0);	    error = uload_word(addr, &word);	    u.u_pcb.pcb_fpregs[inst.i_format.rt] = word;	    break;	case sw_op:	    error = ustore_word(addr, REGVAL(inst.i_format.rt));	    break;	case sh_op:	    error = ustore_half(addr, REGVAL(inst.i_format.rt));	    break;	case swc1_op:	    checkfp(u.u_procp, 0);	    error = ustore_word(addr, u.u_pcb.pcb_fpregs[inst.i_format.rt]);	    break;	default:	    return(2);	}		if(error)	    return(2);	ep[EF_EPC] = new_epc;	return(0);}/* * Convert a virtual address to a physical address. * The virtual address is NOT guaranteed to be good, so we must continually *     check values before referencing pointers. */caddr_tvatophys(va)	register caddr_t va;	/* the virtual addr to convert to physical */	{	caddr_t pa;			/* the physical addr */		register struct pte *pte;	/* pointer to page table */	register unsigned pf;		/* page frame number */	if (IS_KSEG0(va))		pa = (caddr_t)K0_TO_PHYS(va);	else if (IS_KSEG1(va))		pa = (caddr_t)K1_TO_PHYS(va);	else if (IS_KSEG2(va)) {		pte = (struct pte *)(&Sysmap[btop((int)(va) & ~SEG_BITS)]);		/* 		 * kseg2 can have a 0 pfnum, but can it be mapped to anything?		 * if so, don't do the pfnum test here		 */		if (pte->pg_v && pte->pg_pfnum)			pa = (caddr_t)((int)ptob(pte->pg_pfnum) | ((int) (va) & VA_BYTEOFFS));		else			pa = (caddr_t)-1;	}	else if (IS_KUSEG(va)) {		if ((pte = vtopte(u.u_procp, btop(va))) == 0)			pa = (caddr_t)-1;		else if (pte->pg_v && pte->pg_pfnum)			pa = (caddr_t)((int)ptob(pte->pg_pfnum) | ((int) (va) & VA_BYTEOFFS));		else			pa = (caddr_t)-1;	}	else pa = (caddr_t)-1;	return(pa);}int     cpeintvl = CPEINTVL;	/* how often to log cache parity err count */int     cpecount = 0;		/* current cache parity error count */int     cpelogcount = 0;	/* count at last log *//* * This routine is initially called by startup() (after config), thereafter * it is called by timeout.  Its purpose is to log cache parity errors. * The count of cache parity errors is kept by hardclock. */chk_cpe(){	if (cpecount > cpelogcount) {		mprintf("Cache parity error count is %d\n", cpecount);		cpelogcount = cpecount;	}	if (cpeintvl > 0)		timeout (chk_cpe, (caddr_t) 0, cpeintvl * hz);}/* * Determines what spl we are currently set to. * Returns a define const (see cpu.h) for the integer number corresponding *    to the interrupt bits set in the Status Register. * */kn01_whatspl(sr)unsigned sr;{	register int	index;		/* index into the splm array */	register int	imask;		/* mask value we are looking for */	register int	found = 0;	/* Gets us out of the loop */	extern	 int	splm[];	imask = (sr & SR_IMASK);	index = (SPLMSIZE);	while ((index >= 0) && !found) {		index--;		switch (index) {		      case 4:	/* not used */		      case 3:	/* not used */			break;		      default:			if ((splm[index] & SR_IMASK) == imask) {				found = 1;			}			break;		}		if (found)			return(index);	}	return (0);}

⌨️ 快捷键说明

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