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

📄 trap.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	int clockintr, i;	Vctl *v;	va = intrregs->icip;	if(va & (1<<IRQtimer0))		clockintr = 1;	else		clockintr = 0;	for(i = 0; i < 32; i++){		if(((1<<i) & va) == 0)			continue;		for(v = vctl[i]; v != nil; v = v->next){			v->f(ur, v->a);			va &= ~(1<<i);		}	}	if(va)		print("unknown interrupt: %lux\n", va);	return clockintr;}/* *  here on gpio interrupts */static voidgpiointr(Ureg *ur, void*){	ulong va;	int i;	Vctl *v;	va = gpioregs->edgestatus;	gpioregs->edgestatus = va;	for(i = 0; i < 27; i++){		if(((1<<i) & va) == 0)			continue;		for(v = gpiovctl[i]; v != nil; v = v->next){			v->f(ur, v->a);			va &= ~(1<<i);		}	}	if(va)		print("unknown gpio interrupt: %lux\n", va);}/* *  system calls */#include "../port/systab.h"/* *  Syscall is called directly from assembler without going through trap(). */voidsyscall(Ureg* ureg){	char *e;	ulong	sp;	long	ret;	int	i, scallnr;	if((ureg->psr & PsrMask) != PsrMusr) {		panic("syscall: pc 0x%lux r14 0x%lux cs 0x%lux\n", ureg->pc, ureg->r14, ureg->psr);	}	m->syscall++;	up->insyscall = 1;	up->pc = ureg->pc;	up->dbgreg = ureg;	scallnr = ureg->r0;	up->scallnr = scallnr;	spllo();	sp = ureg->sp;	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();	}else{		/* failure: save the error buffer for errstr */		e = up->syserrstr;		up->syserrstr = up->errstr;		up->errstr = e;	}	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->r0 = ret;	if(scallnr == NOTED)		noted(ureg, *(ulong*)(sp+BY2WD));	if(up->delaysched)		sched();	splhi();	if(scallnr != RFORK && (up->procctl || up->nnote))		notify(ureg);}/* *   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);	}	/* don't let user change system flags */	nureg->psr = (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq)) |			(nureg->psr & (PsrMask|PsrDfiq|PsrDirq));	memmove(ureg, nureg, sizeof(Ureg));	switch(arg0){	case NCONT:	case NRSTR:		if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->sp, 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->sp, BY2WD, 0)){			qunlock(&up->debug);			pprint("suicide: trap in noted\n");			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){ 			qunlock(&up->debug);			pprint("suicide: %s\n", up->lastnote.msg);		} else			qunlock(&up->debug);		pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);	}}/* *  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 > ERRMAX-15)	/* " pc=0x12345678\0" */			l = ERRMAX-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->sp;	sp -= sizeof(Ureg);	if(!okaddr((ulong)up->notify, 1, 0)	|| !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+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+ERRMAX;	memmove((char*)sp, up->note[0].msg, ERRMAX);	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->sp = 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;}/* 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;	ureg->r14 = (ulong)sched;}/* *  return the userpc the last exception happened at */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){	USED(ureg, pureg, uva, n);}/* *  this is the body for all kproc's */static voidlinkproc(void){	spllo();	up->kpfun(up->kparg);	pexit("kproc exiting", 0);}/* *  setup stack and initial PC for a new kernel proc.  This is architecture *  dependent because of the starting stack location */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;}/*  *  Craft a return frame which will cause the child to pop out of *  the scheduler in user mode with the return register zero.  Set *  pc to point to a l.s return function. */voidforkchild(Proc *p, Ureg *ureg){	Ureg *cureg;//print("%lud setting up for forking child %lud\n", up->pid, p->pid);	p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);	p->sched.pc = (ulong)forkret;	cureg = (Ureg*)(p->sched.sp);	memmove(cureg, ureg, sizeof(Ureg));	/* syscall returns 0 for child */	cureg->r0 = 0;	/* Things from bottom of syscall which were never executed */	p->psstate = 0;	p->insyscall = 0;}/* *  setup stack, initial PC, and any arch dependent regs for an execing user proc. */longexecregs(ulong entry, ulong ssize, ulong nargs){	ulong *sp;	Ureg *ureg;	sp = (ulong*)(USTKTOP - ssize);	*--sp = nargs;	ureg = up->dbgreg;	memset(ureg, 0, 15*sizeof(ulong));	ureg->r13 = (ulong)sp;	ureg->pc = entry;//print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13);	return USTKTOP-sizeof(Tos);		/* address of kernel/user shared data */}/* * Fill in enough of Ureg to get a stack trace, and call a function. * Used by debugging interface rdb. */voidcallwithureg(void (*fn)(Ureg*)){	Ureg ureg;	ureg.pc = getcallerpc(&fn);	ureg.sp = (ulong)&fn;	fn(&ureg);}static void_dumpstack(Ureg *ureg){	ulong l, v, i;	ulong *p;	extern ulong etext;	if(up == 0){		iprint("no current proc\n");		return;	}	iprint("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);	i = 0;	for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){		v = *(ulong*)l;		if(KTZERO < v && v < (ulong)&etext && (v&3)==0){			v -= 4;			p = (ulong*)v;			if((*p & 0x0f000000) == 0x0b000000){				iprint("%.8lux=%.8lux ", l, v);				i++;			}		}		if(i == 4){			i = 0;			iprint("\n");		}	}	if(i)		iprint("\n");}voiddumpstack(void){	callwithureg(_dumpstack);}/* *  pc output by ps */ulongdbgpc(Proc *p){	Ureg *ureg;	ureg = p->dbgreg;	if(ureg == 0)		return 0;	return ureg->pc;}/* * called in sysfile.c */voidevenaddr(ulong addr){	if(addr & 3){		postnote(up, 1, "sys: odd address", NDebug);		error(Ebadarg);	}}

⌨️ 快捷键说明

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