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

📄 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	"tos.h"#include	"../port/error.h"static Lock vctllock;static Vctl *vctl[256];voidhwintrinit(void){	i8259init();	mpicenable(0, nil);	/* 8259 interrupts are routed through MPIC intr 0 */}static inthwintrenable(Vctl *v){	int vec, irq;	irq = v->irq;	if(BUSTYPE(v->tbdf) == BusPCI) {	/* MPIC? */		if(irq > 15) {			print("intrenable: pci irq %d out of range\n", v->irq);			return -1;		}		vec = irq;		mpicenable(vec, v);	}	else {		if(irq > MaxIrqPIC) {			print("intrenable: irq %d out of range\n", v->irq);			return -1;		}		vec = irq+VectorPIC;		if(i8259enable(v) == -1)			return -1;	}	return vec;}static inthwintrdisable(Vctl *v){	int vec, irq;	irq = v->irq;	if(BUSTYPE(v->tbdf) == BusPCI) {	/* MPIC? */		if(irq > 15) {			print("intrdisable: pci irq %d out of range\n", v->irq);			return -1;		}		vec = irq;		mpicdisable(vec);	}	else {		if(irq > MaxIrqPIC) {			print("intrdisable: irq %d out of range\n", v->irq);			return -1;		}		vec = irq+VectorPIC;		if(i8259disable(irq) == -1)			return -1;	}	return vec;}static inthwvecno(int irq, int tbdf){	if(BUSTYPE(tbdf) == BusPCI) 	/* MPIC? */		return irq;	else		return irq+VectorPIC;}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 = hwintrenable(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);}voidintrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name){	Vctl **pv, *v;	int vno;	vno = hwvecno(irq, tbdf);	ilock(&vctllock);	pv = &vctl[vno];	while (*pv && 		  ((*pv)->irq != irq || (*pv)->tbdf != tbdf || (*pv)->f != f || (*pv)->a != a ||		   strcmp((*pv)->name, name)))		pv = &((*pv)->next);	assert(*pv);	v = *pv;	*pv = (*pv)->next;	/* Link out the entry */		if(vctl[vno] == nil)		hwintrdisable(v);	iunlock(&vctllock);	xfree(v);}void	syscall(Ureg*);void	noted(Ureg*, ulong);static void _dumpstack(Ureg*);char *excname[] ={	"reserved 0",	"system reset",	"machine check",	"data access",	"instruction access",	"external interrupt",	"alignment",	"program exception",	"floating-point unavailable",	"decrementer",	"reserved A",	"reserved B",	"system call",	"trace trap",	"floating point assist",	"reserved F",	"reserved 10",	"reserved 11",	"reserved 12",	"instruction address breakpoint",	"system management interrupt",};char *fpcause[] ={	"inexact operation",	"division by zero",	"underflow",	"overflow",	"invalid operation",};char	*fpexcname(Ureg*, ulong, char*);#define FPEXPMASK	0xfff80300		/* Floating exception bits in fpscr */char *regname[]={	"CAUSE",	"SRR1",	"PC",		"GOK",	"LR",		"CR",	"XER",	"CTR",	"R0",		"R1",	"R2",		"R3",	"R4",		"R5",	"R6",		"R7",	"R8",		"R9",	"R10",	"R11",	"R12",	"R13",	"R14",	"R15",	"R16",	"R17",	"R18",	"R19",	"R20",	"R21",	"R22",	"R23",	"R24",	"R25",	"R26",	"R27",	"R28",	"R29",	"R30",	"R31",};voidtrap(Ureg *ureg){	ulong dsisr;	int ecode, user;	char buf[ERRMAX], *s;	ecode = (ureg->cause >> 8) & 0xff;	user = (ureg->srr1 & MSR_PR) != 0;	if(user)		up->dbgreg = ureg;	if(ureg->status & MSR_RI == 0)		print("double fault?: ecode = %d\n", ecode);	switch(ecode) {	case CEI:		intr(ureg);		break;	case CDEC:		clockintr(ureg);		break;	case CSYSCALL:		if(!user)			panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1);		syscall(ureg);		return;		/* syscall() calls notify itself, don't do it again */	case CFPU:		if(!user || up == nil) {			dumpregs(ureg);			panic("floating point in kernel");		}		switch(up->fpstate){		case FPinit:			fprestore(&initfp);			up->fpstate = FPactive;			break;		case FPinactive:			fprestore(&up->fpsave);			up->fpstate = FPactive;			break;		default:			panic("fpstate");		}		ureg->srr1 |= MSR_FP;		break;	case CISI:		faultpower(ureg, ureg->pc, 1);		break;	case CDSI:		dsisr = getdsisr();		if(dsisr & BIT(6))			faultpower(ureg, getdar(), 0);		else			faultpower(ureg, getdar(), 1);		break;	case CPROG:		if(ureg->status & (1<<19))			s = "floating point exception";		else if(ureg->status & (1<<18))			s = "illegal instruction";		else if(ureg->status & (1<<17))			s = "privileged instruction";		else			s = "undefined program exception";		if(user){			spllo();			sprint(buf, "sys: trap: %s", s);			postnote(up, 1, buf, NDebug);			break;		}		dumpregs(ureg);		panic(s);		break;	default:		if(ecode <= nelem(excname) && user){			spllo();			sprint(buf, "sys: trap: %s", excname[ecode]);			postnote(up, 1, buf, NDebug);			break;		}		dumpregs(ureg);		if(ecode < nelem(excname))			panic("%s", excname[ecode]);		panic("unknown trap/intr: %d\n", ecode);	}	/* restoreureg must execute at high IPL */	splhi();	/* delaysched set because we held a lock or because our quantum ended */	if(up && up->delaysched && ecode == CDEC){		sched();		splhi();	}	if(user) {		notify(ureg);		if(up->fpstate == FPinactive)			ureg->srr1 &= ~MSR_FP;		kexit(ureg);	}}voidfaultpower(Ureg *ureg, ulong addr, int read){	int user, insyscall, n;	char buf[ERRMAX];	user = (ureg->srr1 & MSR_PR) != 0;	insyscall = up->insyscall;	up->insyscall = 1;	n = fault(addr, read);	if(n < 0){		if(!user){			dumpregs(ureg);			panic("fault: 0x%lux", addr);		}		sprint(buf, "sys: trap: fault %s addr=0x%lux", read? "read" : "write", addr);		postnote(up, 1, buf, NDebug);	}	up->insyscall = insyscall;}voidsethvec(int v, void (*r)(void)){	ulong *vp, pa, o;	vp = KADDR(v);	vp[0] = 0x7c1043a6;	/* MOVW R0, SPR(SPRG0) */	vp[1] = 0x7c0802a6;	/* MOVW LR, R0 */	vp[2] = 0x7c1243a6;	/* MOVW R0, SPR(SPRG2) */	pa = PADDR(r);	o = pa >> 25;	if(o != 0 && o != 0x7F){		/* a branch too far */		vp[3] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */		vp[4] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */		vp[5] = 0x7c0803a6;	/* MOVW	R0, LR */		vp[6] = 0x4e800021;	/* BL (LR) */	}else		vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */	dcflush(vp, 8*sizeof(ulong));}voidtrapinit(void){	int i;	/*	 * set all exceptions to trap	 */	for(i = 0; i < 0x2000; i += 0x100)		sethvec(i, trapvec);	putmsr(getmsr() & ~MSR_IP);}voidintr(Ureg *ureg){	int vno;	Vctl *ctl, *v;	vno = mpicintack();	if(vno == 0) {			/* 8259, wired through MPIC vec 0 */		vno = i8259intack();		mpiceoi(0);	}	if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) {		panic("spurious intr %d", vno);		return;	}	if(ctl->isr)		ctl->isr(vno);	for(v = ctl; v != nil; v = v->next){		if(v->f)			v->f(ureg, v->a);	}	if(ctl->eoi)		ctl->eoi(vno);	if(up)		preempted();}char*fpexcname(Ureg *ur, ulong fpscr, char *buf){	int i;	char *s;	ulong fppc;	fppc = ur->pc;	s = 0;	fpscr >>= 3;		/* trap enable bits */	fpscr &= (fpscr>>22);	/* anded with exceptions */	for(i=0; i<5; i++)		if(fpscr & (1<<i))			s = fpcause[i];	if(s == 0)		return "no floating point exception";	sprint(buf, "%s fppc=0x%lux", s, fppc);	return buf;

⌨️ 快捷键说明

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