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

📄 trap.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* * Fill in enough of Ureg to get a stack trace, and call a function. * Used by debugging interface rdb. */static voidgetpcsp(ulong *pc, ulong *sp){	*pc = getcallerpc(&pc);	*sp = (ulong)&pc-4;}voidcallwithureg(void (*fn)(Ureg*)){	Ureg ureg;	getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);	ureg.lr = getcallerpc(&fn);	fn(&ureg);}static void_dumpstack(Ureg *ureg){	ulong l, sl, el, v;	int i;	l = (ulong)&l;	if(up == 0){		el = (ulong)m+BY2PG;		sl = el-KSTACK;	}	else{		sl = (ulong)up->kstack;		el = sl + KSTACK;	}	if(l > el || l < sl){		el = (ulong)m+BY2PG;		sl = el-KSTACK;	}	if(l > el || l < sl)		return;	print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->lr);	i = 0;	for(; l < el; l += 4){		v = *(ulong*)l;		if(KTZERO < v && v < (ulong)etext){			print("%.8lux=%.8lux ", l, v);			if(i++ == 4){				print("\n");				i = 0;			}		}	}}voiddumpstack(void){	callwithureg(_dumpstack);}voiddumpregs(Ureg *ur){	int i;	ulong *l;	if(up) {		print("registers for %s %ld\n", up->text, up->pid);		if(ur->srr1 & MSR_PR == 0)		if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK)			print("invalid stack ptr\n");	}	else		print("registers for kernel\n");	print("dsisr\t%.8lux\tdar\t%.8lux\n", getdsisr(), getdar());	l = &ur->cause;	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);}static voidlinkproc(void){	spllo();	(*up->kpfun)(up->kparg);	pexit("", 0);}voidkprocchild(Proc *p, void (*func)(void*), void *arg){	p->sched.pc = (ulong)linkproc;	p->sched.sp = (ulong)p->kstack+KSTACK;	p->kpfun = func;	p->kparg = arg;}/* * called in sysfile.c */voidevenaddr(ulong addr){	if(addr & 3){		postnote(up, 1, "sys: odd address", NDebug);		error(Ebadarg);	}}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;	ureg->srr1 &= ~MSR_FP;	return USTKTOP-sizeof(Tos);		/* address of kernel/user shared data */}voidforkchild(Proc *p, Ureg *ur){	Ureg *cur;	p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE;	p->sched.pc = (ulong)forkret;	cur = (Ureg*)(p->sched.sp+2*BY2WD);	memmove(cur, ur, sizeof(Ureg));	cur->r3 = 0;		/* Things from bottom of syscall we never got to execute */	p->psstate = 0;	p->insyscall = 0;}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 *xp, char *pureg, char *uva, int n){	ulong status;	status = xp->status;	memmove(pureg, uva, n);	xp->status = status;}/* 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;}/* *  system calls */#include "../port/systab.h"/* TODO: make this trap a separate asm entry point, like on other RISC architectures */voidsyscall(Ureg* ureg){	int i;	char *e;	long	ret;	ulong sp, scallnr;	m->syscall++;	up->insyscall = 1;	up->pc = ureg->pc;	up->dbgreg = ureg;	scallnr = ureg->r3;	up->scallnr = ureg->r3;	spllo();	sp = ureg->usp;	up->nerrlab = 0;	ret = -1;	if(!waserror()){		if(scallnr >= nsyscall || systab[scallnr] == nil){			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();	}else{		/* failure: save the error buffer for errstr */		e = up->syserrstr;		up->syserrstr = up->errstr;		up->errstr = e;	}	if(up->nerrlab){		print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);		print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);		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->r3 = ret;	if(scallnr == NOTED)		noted(ureg, *(ulong*)(sp+BY2WD));	/* restoreureg must execute at high IPL */	splhi();	if(scallnr!=RFORK)		notify(ureg);	if(up->fpstate == FPinactive)		ureg->srr1 &= ~MSR_FP;}/* *  Call user, if necessary, with note. *  Pass user the Ureg struct and the note on his stack. */intnotify(Ureg* ur){	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 > ERRMAX-15)	/* " pc=0x12345678\0" */			l = ERRMAX-15;		sprint(n->msg+l, " pc=0x%.8lux", ur->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 = ur->usp & ~(BY2V-1);	sp -= sizeof(Ureg);	if(!okaddr((ulong)up->notify, BY2WD, 0) ||	   !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) {		pprint("suicide: bad address or sp in notify\n");		qunlock(&up->debug);		pexit("Suicide", 0);	}	memmove((Ureg*)sp, ur, sizeof(Ureg));	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */	up->ureg = (void*)sp;	sp -= BY2WD+ERRMAX;	memmove((char*)sp, up->note[0].msg, ERRMAX);	sp -= 3*BY2WD;	*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;	/* arg 2 is string */	ur->r1 = (long)up->ureg;		/* arg 1 is ureg* */	((ulong*)sp)[1] = (ulong)up->ureg;	/* arg 1 0(FP) is ureg* */	((ulong*)sp)[0] = 0;			/* arg 0 is pc */	ur->usp = sp;	ur->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);	}	memmove(ureg, nureg, sizeof(Ureg));	switch(arg0){	case NCONT:	case NRSTR:		if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){			pprint("suicide: trap in noted\n");			qunlock(&up->debug);			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)){			pprint("suicide: trap in noted\n");			qunlock(&up->debug);			pexit("Suicide", 0);		}		qunlock(&up->debug);		sp = oureg-4*BY2WD-ERRMAX;		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)			pprint("suicide: %s\n", up->lastnote.msg);		qunlock(&up->debug);		pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);	}}

⌨️ 快捷键说明

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