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

📄 trap.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"ureg.h"#include	"../port/error.h"#include	"tos.h"Intrregs *intrregs;typedef struct Vctl {	Vctl*	next;			/* handlers on this vector */	char	*name;		/* of driver, xallocated */	void	(*f)(Ureg*, void*);	/* handler to call */	void*	a;			/* argument to call it with */} Vctl;static Lock	vctllock;static Vctl	*vctl[32];static Vctl	*gpiovctl[27];static int	gpioirqref[12];/* *   Layout at virtual address 0. */typedef struct Vpage0 {	void	(*vectors[8])(void);	ulong	vtable[8];} Vpage0;Vpage0 *vpage0;static int	irq(Ureg*);static void	gpiointr(Ureg*, void*);/* recover state after power suspend * NB: to help debugging bad suspend code, *     I changed some prints below to iprints, *     to avoid deadlocks when a panic is being *     issued during the suspend/resume handler. */voidtrapresume(void){	vpage0 = (Vpage0*)EVECTORS;	memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));	memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));	wbflush();	mappedIvecEnable();}/* *  set up for exceptions */voidtrapinit(void){	/* set up the exception vectors */	vpage0 = (Vpage0*)EVECTORS;	memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));	memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));	wbflush();	/* use exception vectors at 0xFFFF0000 */	mappedIvecEnable();	/* set up the stacks for the interrupt modes */	setr13(PsrMfiq, m->sfiq);	setr13(PsrMirq, m->sirq);	setr13(PsrMabt, m->sabt);	setr13(PsrMund, m->sund);	/* map in interrupt registers */	intrregs = mapspecial(INTRREGS, sizeof(*intrregs));	/* make all interrupts IRQ (i.e. not FIQ) and disable all interrupts */	intrregs->iclr = 0;	intrregs->icmr = 0;	/* turn off all gpio interrupts */	gpioregs->rising = 0;	gpioregs->falling = 0;	gpioregs->edgestatus = gpioregs->edgestatus;	/* allow all enabled interrupts to take processor out of sleep mode */	intrregs->iccr = 0;}voidtrapdump(char *tag){	iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",		tag, intrregs->icip, intrregs->icmr, intrregs->iclr,		intrregs->iccr, intrregs->icfp);}voidwarnregs(Ureg *ur, char *tag){	char buf[1024];	char *e = buf+sizeof(buf);	char *p;	p = seprint(buf, e, "%s:\n", tag);	p = seprint(p, e, "type 0x%.8lux psr 0x%.8lux pc 0x%.8lux\n",		ur->type, ur->psr, ur->pc);	p = seprint(p, e, "r0  0x%.8lux r1  0x%.8lux r2  0x%.8lux r3  0x%.8lux\n",		ur->r0, ur->r1, ur->r2, ur->r3);	p = seprint(p, e, "r4  0x%.8lux r5  0x%.8lux r6  0x%.8lux r7  0x%.8lux\n",		ur->r4, ur->r5, ur->r6, ur->r7);	p = seprint(p, e, "r8  0x%.8lux r9  0x%.8lux r10 0x%.8lux r11 0x%.8lux\n",		ur->r8, ur->r9, ur->r10, ur->r11);	seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",		ur->r12, ur->r13, ur->r14);	iprint("%s", buf);}/* *  enable an irq interrupt */static voidirqenable(int irq, IntrHandler *f, void* a, char *name){	Vctl *v;	if(irq >= nelem(vctl) || irq < 0)		panic("intrenable");	v = malloc(sizeof(Vctl));	v->f = f;	v->a = a;	v->name = xalloc(strlen(name)+1);	strcpy(v->name, name);	lock(&vctllock);	v->next = vctl[irq];	vctl[irq] = v;	intrregs->icmr |= 1<<irq;	unlock(&vctllock);}/* *  disable an irq interrupt */static voidirqdisable(int irq, IntrHandler *f, void* a, char *name){	Vctl **vp, *v;	if(irq >= nelem(vctl) || irq < 0)		panic("intrdisable");	lock(&vctllock);	for(vp = &vctl[irq]; v = *vp; vp = &v->next)		if (v->f == f && v->a == a && strcmp(v->name, name) == 0){			print("irqdisable: remove %s\n", name);			*vp = v->next;			free(v);			break;		}	if (v == nil)		print("irqdisable: irq %d, name %s not enabled\n", irq, name);	if (vctl[irq] == nil){		print("irqdisable: clear icmr bit %d\n", irq);		intrregs->icmr &= ~(1<<irq);	}	unlock(&vctllock);}/* *  enable an interrupt */voidintrenable(int type, int which, IntrHandler *f, void* a, char *name){	int irq;	Vctl *v;	if(type == IRQ){		irqenable(which, f, a, name);		return;	}	/* from here down, it must be a GPIO edge interrupt */	irq = which;	if(which >= nelem(gpiovctl) || which < 0)		panic("intrenable");	if(which > 11)		irq = 11;	/* the pin had better be configured as input */	if((1<<which) & gpioregs->direction)		panic("intrenable of output pin %d", which);	/* create a second level vctl for the gpio edge interrupt */	v = malloc(sizeof(Vctl));	v->f = f;	v->a = a;	v->name = xalloc(strlen(name)+1);	strcpy(v->name, name);	lock(&vctllock);	v->next = gpiovctl[which];	gpiovctl[which] = v;	/* set edge register to enable interrupt */	switch(type){	case GPIOboth:		gpioregs->rising |= 1<<which;		gpioregs->falling |= 1<<which;		break;	case GPIOfalling:		gpioregs->falling |= 1<<which;		break;	case GPIOrising:		gpioregs->rising |= 1<<which;		break;	}	unlock(&vctllock);	/* point the irq to the gpio interrupt handler */	if(gpioirqref[irq]++ == 0)		irqenable(irq, gpiointr, nil, "gpio edge");}/* *  disable an interrupt */voidintrdisable(int type, int which, IntrHandler *f, void* a, char *name){	int irq;	Vctl **vp, *v;	if(type == IRQ){		irqdisable(which, f, a, name);		return;	}	/* from here down, it must be a GPIO edge interrupt */	irq = which;	if(which >= nelem(gpiovctl) || which < 0)		panic("intrdisable");	if(which > 11)		irq = 11;	lock(&vctllock);	for(vp = &gpiovctl[which]; v = *vp; vp = &v->next)		if (v->f == f && v->a == a && strcmp(v->name, name) == 0){			break;		}	if (gpiovctl[which] == nil){		/* set edge register to enable interrupt */		switch(type){		case GPIOboth:			print("intrdisable: gpio-rising+falling clear bit %d\n", which);			gpioregs->rising &= ~(1<<which);			gpioregs->falling &= ~(1<<which);			break;		case GPIOfalling:			print("intrdisable: gpio-falling clear bit %d\n", which);			gpioregs->falling &= ~(1<<which);			break;		case GPIOrising:			print("intrdisable: gpio-rising clear bit %d\n", which);			gpioregs->rising &= ~(1<<which);			break;		}		}	if (v) {		print("intrdisable: removing %s\n", name);		*vp = v->next;	}else		print("intrdisable: which %d, name %s not enabled\n", which, name);	unlock(&vctllock);	/* disable the gpio interrupt handler if necessary */	if(--gpioirqref[irq] == 0){		print("intrdisable: inrqdisable gpiointr\n");		irqdisable(irq, gpiointr, nil, "gpio edge");	}	free(v);}/* *  called by trap to handle access faults */static voidfaultarm(Ureg *ureg, ulong va, int user, int read){	int n, insyscall;	char buf[ERRMAX];	if (up == nil) {		warnregs(ureg, "kernel fault");		panic("fault: nil up in faultarm, accessing 0x%lux\n", va);	}	insyscall = up->insyscall;	up->insyscall = 1;	n = fault(va, read);	if(n < 0){		if(!user){			warnregs(ureg, "kernel fault");			panic("fault: kernel accessing 0x%lux\n", va);		}//		warnregs(ureg, "user fault");		sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va);		postnote(up, 1, buf, NDebug);	}	up->insyscall = insyscall;}/* *  returns 1 if the instruction writes memory, 0 otherwise */intwritetomem(ulong inst){	/* swap always write memory */	if((inst & 0x0FC00000) == 0x01000000)		return 1;	/* loads and stores are distinguished by bit 20 */	if(inst & (1<<20))		return 0;	return 1;}/* *  here on all exceptions other than syscall (SWI) */voidtrap(Ureg *ureg){	ulong inst;	int clockintr, user, x, rv;	ulong va, fsr;	char buf[ERRMAX];	int rem;	if(up != nil)		rem = ((char*)ureg)-up->kstack;	else		rem = ((char*)ureg)-((char*)(MACHADDR+sizeof(Mach)));	if(rem < 256) {		dumpstack();		panic("trap %d bytes remaining, up = 0x%lux, ureg = 0x%lux, at pc 0x%lux",			rem, up, ureg, ureg->pc);	}	user = (ureg->psr & PsrMask) == PsrMusr;	/*	 * All interrupts/exceptions should be resumed at ureg->pc-4,	 * except for Data Abort which resumes at ureg->pc-8.	 */	if(ureg->type == (PsrMabt+1))		ureg->pc -= 8;	else		ureg->pc -= 4;	clockintr = 0;	switch(ureg->type){	default:		panic("unknown trap");		break;	case PsrMirq:		clockintr = irq(ureg);		break;	case PsrMabt:	/* prefetch fault */		faultarm(ureg, ureg->pc, user, 1);		break;	case PsrMabt+1:	/* data fault */		va = getfar();		inst = *(ulong*)(ureg->pc);		fsr = getfsr() & 0xf;		switch(fsr){		case 0x0:			panic("vector exception at %lux\n", ureg->pc);			break;		case 0x1:		case 0x3:			if(user){				snprint(buf, sizeof(buf), "sys: alignment: pc 0x%lux va 0x%lux\n",					ureg->pc, va);				postnote(up, 1, buf, NDebug);			} else				panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va);			break;		case 0x2:			panic("terminal exception at %lux\n", ureg->pc);			break;		case 0x4:		case 0x6:		case 0x8:		case 0xa:		case 0xc:		case 0xe:			panic("external abort 0x%lux pc 0x%lux addr 0x%lux\n", fsr, ureg->pc, va);			break;		case 0x5:		case 0x7:			/* translation fault, i.e., no pte entry */			faultarm(ureg, va, user, !writetomem(inst));			break;		case 0x9:		case 0xb:			/* domain fault, accessing something we shouldn't */			if(user){				sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n",					ureg->pc, va);				postnote(up, 1, buf, NDebug);			} else				panic("kernel access violation: pc 0x%lux va 0x%lux\n",					ureg->pc, va);			break;		case 0xd:		case 0xf:			/* permission error, copy on write or real permission error */			faultarm(ureg, va, user, !writetomem(inst));			break;		}		break;	case PsrMund:	/* undefined instruction */		if (user) {			/* look for floating point instructions to interpret */			x = spllo();			rv = fpiarm(ureg);			splx(x);			if (rv == 0) {				sprint(buf, "undefined instruction: pc 0x%lux\n", ureg->pc);				postnote(up, 1, buf, NDebug);			}		}else{			iprint("undefined instruction: pc=0x%lux, inst=0x%lux, 0x%lux, 0x%lux, 0x%lux, 0x%lux\n", ureg->pc, ((ulong*)ureg->pc)[-2], ((ulong*)ureg->pc)[-1], ((ulong*)ureg->pc)[0], ((ulong*)ureg->pc)[1], ((ulong*)ureg->pc)[2]);			panic("undefined instruction");		}		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(ureg);		kexit(ureg);	}}/* *  here on irq's */static intirq(Ureg *ur){	ulong va;

⌨️ 快捷键说明

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