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

📄 trap.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"ureg.h"#include	"io.h"#include	"../port/error.h"void	noted(Ureg*, Ureg**, ulong);void	rfnote(Ureg**);void	kernfault(Ureg*, int);void	illegal(Ureg *);void	fen(Ureg *);char *regname[]={	"type",	"a0",		"a1",	"a2",		"R0",		"R1",	"R2",		"R3",		"R4",	"R5",		"R6",		"R7",	"R8",		"R9",		"R10",	"R11",	"R12",	"R13",	"R14",	"R15",	"R19",	"R20",	"R21",	"R22",	"R23",	"R24",	"R25",	"R26",	"R27",	"R28",	"R30",	"status",	"PC",	"R29",	"R16",	"R17",	"R18",};static Lock vctllock;static Vctl *vctl[256];voidintrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name){	int vno;	Vctl *v;	if(f == nil){		print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",			irq, tbdf, name);		return;	}	v = xalloc(sizeof(Vctl));	v->isintr = 1;	v->irq = irq;	v->tbdf = tbdf;	v->f = f;	v->a = a;	strncpy(v->name, name, KNAMELEN-1);	v->name[KNAMELEN-1] = 0;	ilock(&vctllock);	vno = arch->intrenable(v);	if(vno == -1){		iunlock(&vctllock);		print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",			irq, tbdf, v->name);		xfree(v);		return;	}	if(vctl[vno]){		if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)			panic("intrenable: handler: %s %s %luX %luX %luX %luX\n",				vctl[vno]->name, v->name,				vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);		v->next = vctl[vno];	}	vctl[vno] = v;	iunlock(&vctllock);}intintrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name){	Vctl **pv, *v;	int vno;	/*	 * For now, none of this will work with the APIC code,	 * there is no mapping between irq and vector as the IRQ	 * is pretty meaningless.	 */	if(arch->intrvecno == nil)		return -1;	vno = arch->intrvecno(irq);	ilock(&vctllock);	for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){		if((*pv)->irq != irq)			continue;		if((*pv)->tbdf != tbdf)			continue;		if((*pv)->f != f)			continue;		if((*pv)->a != a)			continue;		if(strcmp((*pv)->name, name) != 0)			continue;		break;	}	assert(*pv != nil);	v = *pv;	*pv = (*pv)->next;	/* Link out the entry */		if (vctl[vno] == nil && arch->intrdisable != nil)		arch->intrdisable(irq);	iunlock(&vctllock);	xfree(v);	return 0;}intirqallocread(char *buf, long n, vlong offset){	int vno;	Vctl *v;	long oldn;	char str[11+1+KNAMELEN+1], *p;	int m;	if(n < 0 || offset < 0)		error(Ebadarg);	oldn = n;	for(vno=0; vno<nelem(vctl); vno++){		for(v=vctl[vno]; v; v=v->next){			m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);			if(m <= offset)	/* if do not want this, skip entry */				offset -= m;			else{				/* skip offset bytes */				m -= offset;				p = str+offset;				offset = 0;				/* write at most max(n,m) bytes */				if(m > n)					m = n;				memmove(buf, p, m);				n -= m;				buf += m;				if(n == 0)					return oldn;			}			}	}	return oldn - n;}typedef struct Mcheck Mcheck;struct Mcheck{	ulong	len;	ulong	inprogress;	ulong	procoff;	ulong	sysoff;	ulong	code;};static char *smcheck(ulong code){	switch (code) {	case 0x80: return "tag parity error";	case 0x82: return "tag control parity error";	case 0x84: return "generic hard error";	case 0x86: return "correctable ECC error";	case 0x88: return "uncorrectable ECC error";	case 0x8a: return "OS-specific PAL bugcheck";	case 0x90: return "callsys in kernel mode";	case 0x96: return "i-cache read retryable error";	case 0x98: return "processor detected hard error";	case 0x203: return "system detected uncorrectable ECC error";	case 0x205: return "parity error detected by CIA";	case 0x207: return "non-existent memory error";	case 0x209: return "PCI SERR detected";	case 0x20b: return "PCI data parity error detected";	case 0x20d: return "PCI address parity error detected";	case 0x20f: return "PCI master abort error";	case 0x211: return "PCI target abort error";	case 0x213: return "scatter/gather PTE invalid error";	case 0x215: return "flash ROM write error";	case 0x217: return "IOA timeout detected";	case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error";	case 0x21b: return "EISA fail-safe timer timeout";	case 0x21d: return "EISA bus time-out";	case 0x21f: return "EISA software generated NMI";	case 0x221: return "unexpected ev5 IRQ[3] interrupt";	default: return "unknown mcheck";	}}voidmcheck(Ureg *ur, void *x){	Mcheck *m;	uvlong *data;	int i, col;	m = x;	data = x;	iprint("panic: Machine Check @%lux: %s (%lux) len %lud\n",			m, smcheck(m->code), m->code, m->len);	iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff);	for (i = 0, col = 0; i < m->len/8; i++) {		iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : "    ");		if (col++ == 2)			col = 0;	}	if(col != 2)		print("\n");	print("\n");	dumpregs(ur);	prflush();	firmware();}voidintr(Ureg *ur){	int i, vno;	Vctl *ctl, *v;	Mach *mach;	vno = (ulong)ur->a1>>4;	vno -= 0x80;	if(vno < nelem(vctl) && (ctl = vctl[vno])){		if(ctl->isintr){			m->intr++;			if(vno >= VectorPIC && vno <= MaxVectorPIC)				m->lastintr = vno-VectorPIC;		}		if(ctl->isr)			ctl->isr(vno);		for(v = ctl; v != nil; v = v->next) {			if(v->f)				v->f(ur, v->a);		}		if(ctl->eoi)			ctl->eoi(vno);		if(ctl->isintr && up)			preempted();	}	else if(vno >= VectorPIC && vno <= MaxVectorPIC){		/*		 * An unknown interrupt.		 * Check for a default IRQ7. This can happen when		 * the IRQ input goes away before the acknowledge.		 * In this case, a 'default IRQ7' is generated, but		 * the corresponding bit in the ISR isn't set.		 * In fact, just ignore all such interrupts.		 */		iprint("cpu%d: spurious interrupt %d, last %d",			m->machno, vno-VectorPIC, m->lastintr);		for(i = 0; i < 32; i++){			if(!(active.machs & (1<<i)))				continue;			mach = MACHP(i);			if(m->machno == mach->machno)				continue;			iprint(": cpu%d: last %d", mach->machno, mach->lastintr);		}		iprint("\n");		m->spuriousintr++;		return;	}	else{		dumpregs(ur);		print("unknown intr: %d\n", vno); /* */	}}voidtrap(Ureg *ur){	char buf[ERRMAX];	int clockintr, user, x;	user = ur->status&UMODE;	if(user){		up = m->proc;		up->dbgreg = ur;	}	clockintr = 0;	switch ((int)ur->type) {	case 1:	/* arith */		fptrap(ur);		break;	case 2:	/* bad instr or FEN */		illegal(ur);		break;	case 3:	/* intr */		m->intr++;		switch ((int)ur->a0) {		case 0:	/* interprocessor */			panic("interprocessor intr");			break;		case 1:	/* clock */			clockintr = 1;			clock(ur);			break;		case 2:	/* machine check */			mcheck(ur, (void*)(KZERO|(ulong)ur->a2));			break;		case 3:	/* device */			intr(ur);			break;		case 4:	/* perf counter */			panic("perf count");			break;		default:			panic("bad intr");			break;		}		break;	case 4:	/* memory fault */		if(up == 0)			kernfault(ur, (ulong)ur->a1);		x = up->insyscall;		up->insyscall = 1;		spllo();		faultalpha(ur);		up->insyscall = x;		break;	case 6:	/* alignment fault */		ur->pc -= 4;		sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);		fataltrap(ur, buf);		break;	default:	/* cannot happen */		panic("bad trap type %d", (int)ur->type);		break;	}	splhi();	/* delaysched set because we held a lock or because our quantum ended */	if(up && up->delaysched && clockintr){		sched();		splhi();	}	if(user){		if(up->procctl || up->nnote)			notify(ur);		kexit(ur);	}}voidtrapinit(void){	splhi();	wrent(0, intr0);	wrent(1, arith);	wrent(2, fault0);	wrent(3, illegal0);	wrent(4, unaligned);	wrent(5, syscall0);}voidfataltrap(Ureg *ur, char *reason){	char buf[ERRMAX];	if(ur->status&UMODE) {		spllo();		sprint(buf, "sys: %s", reason);		postnote(up, 1, buf, NDebug);		return;	}	print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);	dumpregs(ur);	dumpstack();	if(m->machno == 0)		spllo();	exit(1);}voidkernfault(Ureg *ur, int code){	Label l;	char *s;	splhi();	if (code == 0)		s = "read";	else if (code == 1)		s = "write";	else		s = "ifetch";	print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);	print("u=0x%lux status=0x%lux pc=0x%lux sp=0x%lux\n",				up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);	dumpregs(ur);	l.sp = ur->sp;	l.pc = ur->pc;	dumpstack();	exit(1);}voiddumpregs(Ureg *ur){	int i, col;	uvlong *l;	if(up)		print("registers for %s %ld\n", up->text, up->pid);	else		print("registers for kernel\n");	l = &ur->type;	col = 0;	for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {		print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : "     ");		if (col++ == 2)			col = 0;	}	print("\n");}/* * 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-8;}voidcallwithureg(void (*fn)(Ureg*)){	Ureg ureg;	getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);	ureg.r26 = getcallerpc(&fn);	fn(&ureg);}

⌨️ 快捷键说明

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