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

📄 trap.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
			print("\n");		}	}	if(i)		print("\n");}voiddumpstack(void){	callwithureg(_dumpstack);}static voiddebugbpt(Ureg* ureg, void*){	char buf[ERRLEN];	if(up == 0)		panic("kernel bpt");	/* restore pc to instruction that caused the trap */	ureg->pc--;	sprint(buf, "sys: breakpoint");	postnote(up, 1, buf, NDebug);}static voidfault386(Ureg* ureg, void*){	ulong addr;	int read, user, n, insyscall;	char buf[ERRLEN];	addr = getcr2();	user = (ureg->cs & 0xFFFF) == UESEL;	if(!user && mmukmapsync(addr))		return;	read = !(ureg->ecode & 2);	insyscall = up->insyscall;	up->insyscall = 1;	n = fault(addr, read);	if(n < 0){		if(!user){			dumpregs(ureg);			panic("fault: 0x%lux\n", addr);		}		sprint(buf, "sys: trap: fault %s addr=0x%lux",			read? "read" : "write", addr);		postnote(up, 1, buf, NDebug);	}	up->insyscall = insyscall;}/* *  system calls */#include "../port/systab.h"/* *  Syscall is called directly from assembler without going through trap(). */voidsyscall(Ureg* ureg){	ulong	sp;	long	ret;	int	i, scallnr;	if((ureg->cs & 0xFFFF) != UESEL)		panic("syscall: cs 0x%4.4uX\n", ureg->cs);	m->syscall++;	up->insyscall = 1;	up->pc = ureg->pc;	up->dbgreg = ureg;	scallnr = ureg->ax;	up->scallnr = scallnr;	if(scallnr == RFORK && up->fpstate == FPactive){		fpsave(&up->fpsave);		up->fpstate = FPinactive;	}	spllo();	sp = ureg->usp;	up->nerrlab = 0;	ret = -1;	if(!waserror()){		if(scallnr >= nsyscall){			pprint("bad sys call number %d pc %lux\n",				scallnr, ureg->pc);			postnote(up, 1, "sys: bad sys call", NDebug);			error(Ebadarg);		}		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))			validaddr(sp, sizeof(Sargs)+BY2WD, 0);		up->s = *((Sargs*)(sp+BY2WD));		up->psstate = sysctab[scallnr];		ret = systab[scallnr](up->s.args);		poperror();	}	if(up->nerrlab){		print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);		for(i = 0; i < NERR; i++)			print("sp=%lux pc=%lux\n",				up->errlab[i].sp, up->errlab[i].pc);		panic("error stack");	}	up->insyscall = 0;	up->psstate = 0;	/*	 *  Put return value in frame.  On the x86 the syscall is	 *  just another trap and the return value from syscall is	 *  ignored.  On other machines the return value is put into	 *  the results register by caller of syscall.	 */	ureg->ax = ret;	if(scallnr == NOTED)		noted(ureg, *(ulong*)(sp+BY2WD));	if(scallnr!=RFORK && (up->procctl || up->nnote)){		splhi();		notify(ureg);	}}/* *  Call user, if necessary, with note. *  Pass user the Ureg struct and the note on his stack. */intnotify(Ureg* ureg){	int l;	ulong s, sp;	Note *n;	if(up->procctl)		procctl(up);	if(up->nnote == 0)		return 0;	s = spllo();	qlock(&up->debug);	up->notepending = 0;	n = &up->note[0];	if(strncmp(n->msg, "sys:", 4) == 0){		l = strlen(n->msg);		if(l > ERRLEN-15)	/* " pc=0x12345678\0" */			l = ERRLEN-15;		sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);	}	if(n->flag!=NUser && (up->notified || up->notify==0)){		if(n->flag == NDebug)			pprint("suicide: %s\n", n->msg);		qunlock(&up->debug);		pexit(n->msg, n->flag!=NDebug);	}	if(up->notified) {		qunlock(&up->debug);		splhi();		return 0;	}			if(!up->notify){		qunlock(&up->debug);		pexit(n->msg, n->flag!=NDebug);	}	sp = ureg->usp;	sp -= sizeof(Ureg);	if(!okaddr((ulong)up->notify, 1, 0)	|| !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)){		pprint("suicide: bad address in notify\n");		qunlock(&up->debug);		pexit("Suicide", 0);	}	up->ureg = (void*)sp;	memmove((Ureg*)sp, ureg, sizeof(Ureg));	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */	up->ureg = (void*)sp;	sp -= BY2WD+ERRLEN;	memmove((char*)sp, up->note[0].msg, ERRLEN);	sp -= 3*BY2WD;	*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;	/* arg 2 is string */	*(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;	/* arg 1 is ureg* */	*(ulong*)(sp+0*BY2WD) = 0;		/* arg 0 is pc */	ureg->usp = sp;	ureg->pc = (ulong)up->notify;	up->notified = 1;	up->nnote--;	memmove(&up->lastnote, &up->note[0], sizeof(Note));	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));	qunlock(&up->debug);	splx(s);	return 1;}/* *   Return user to state before notify() */voidnoted(Ureg* ureg, ulong arg0){	Ureg *nureg;	ulong oureg, sp;	qlock(&up->debug);	if(arg0!=NRSTR && !up->notified) {		qunlock(&up->debug);		pprint("call to noted() when not notified\n");		pexit("Suicide", 0);	}	up->notified = 0;	nureg = up->ureg;	/* pointer to user returned Ureg struct */	/* sanity clause */	oureg = (ulong)nureg;	if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){		pprint("bad ureg in noted or call to noted when not notified\n");		qunlock(&up->debug);		pexit("Suicide", 0);	}	/*	 * Check the segment selectors are all valid, otherwise	 * a fault will be taken on attempting to return to the	 * user process.	 * Take care with the comparisons as different processor	 * generations push segment descriptors in different ways.	 */	if((nureg->cs & 0xFFFF) != UESEL || (nureg->ss & 0xFFFF) != UDSEL	  || (nureg->ds & 0xFFFF) != UDSEL || (nureg->es & 0xFFFF) != UDSEL	  || (nureg->fs & 0xFFFF) != UDSEL || (nureg->gs & 0xFFFF) != UDSEL){		pprint("bad segment selector in noted\n");		qunlock(&up->debug);		pexit("Suicide", 0);	}	/* don't let user change system flags */	nureg->flags = (ureg->flags & ~0xCD5) | (nureg->flags & 0xCD5);	memmove(ureg, nureg, sizeof(Ureg));	switch(arg0){	case NCONT:	case NRSTR:		if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){			qunlock(&up->debug);			pprint("suicide: trap in noted\n");			pexit("Suicide", 0);		}		up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));		qunlock(&up->debug);		break;	case NSAVE:		if(!okaddr(nureg->pc, BY2WD, 0)		|| !okaddr(nureg->usp, BY2WD, 0)){			qunlock(&up->debug);			pprint("suicide: trap in noted\n");			pexit("Suicide", 0);		}		qunlock(&up->debug);		sp = oureg-4*BY2WD-ERRLEN;		splhi();		ureg->sp = sp;		((ulong*)sp)[1] = oureg;	/* arg 1 0(FP) is ureg* */		((ulong*)sp)[0] = 0;		/* arg 0 is pc */		break;	default:		pprint("unknown noted arg 0x%lux\n", arg0);		up->lastnote.flag = NDebug;		/* fall through */			case NDFLT:		if(up->lastnote.flag == NDebug){ 			qunlock(&up->debug);			pprint("suicide: %s\n", up->lastnote.msg);		} else			qunlock(&up->debug);		pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);	}}longexecregs(ulong entry, ulong ssize, ulong nargs){	ulong *sp;	Ureg *ureg;	sp = (ulong*)(USTKTOP - ssize);	*--sp = nargs;	ureg = up->dbgreg;	ureg->usp = (ulong)sp;	ureg->pc = entry;	return USTKTOP-BY2WD;		/* address of user-level clock */}ulonguserpc(void){	Ureg *ureg;	ureg = (Ureg*)up->dbgreg;	return ureg->pc;}/* This routine must save the values of registers the user is not permitted * to write from devproc and then restore the saved values before returning. */voidsetregisters(Ureg* ureg, char* pureg, char* uva, int n){	ulong flags;	ulong cs;	ulong ss;	flags = ureg->flags;	cs = ureg->cs;	ss = ureg->ss;	memmove(pureg, uva, n);	ureg->flags = (ureg->flags & 0x00FF) | (flags & 0xFF00);	ureg->cs = cs;	ureg->ss = ss;}static voidlinkproc(void){	spllo();	up->kpfun(up->kparg);}voidkprocchild(Proc* p, void (*func)(void*), void* arg){	/*	 * gotolabel() needs a word on the stack in	 * which to place the return PC used to jump	 * to linkproc().	 */	p->sched.pc = (ulong)linkproc;	p->sched.sp = (ulong)p->kstack+KSTACK-BY2WD;	p->kpfun = func;	p->kparg = arg;}voidforkchild(Proc *p, Ureg *ureg){	Ureg *cureg;	/*	 * Add 2*BY2WD to the stack to account for	 *  - the return PC	 *  - trap's argument (ur)	 */	p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Ureg)+2*BY2WD);	p->sched.pc = (ulong)forkret;	cureg = (Ureg*)(p->sched.sp+2*BY2WD);	memmove(cureg, ureg, sizeof(Ureg));	/* return value of syscall in child */	cureg->ax = 0;	/* Things from bottom of syscall which were never executed */	p->psstate = 0;	p->insyscall = 0;}/* Give enough context in the ureg to produce a kernel stack for * a sleeping process */voidsetkernur(Ureg* ureg, Proc* p){	ureg->pc = p->sched.pc;	ureg->sp = p->sched.sp+4;}ulongdbgpc(Proc *p){	Ureg *ureg;	ureg = p->dbgreg;	if(ureg == 0)		return 0;	return ureg->pc;}

⌨️ 快捷键说明

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