plan 9 kernel history: overview | file list | diff list

1997/0327/pc/trap.c (diff list | history)

1996/0802/sys/src/9/pc/trap.c:9,2301997/0327/sys/src/9/pc/trap.c:9,77 (short | long | prev | next)
1991/0613    
 
1991/0720    
void	noted(Ureg*, ulong); 
 
1991/0731    
void	intr0(void), intr1(void), intr2(void), intr3(void); 
void	intr4(void), intr5(void), intr6(void), intr7(void); 
void	intr8(void), intr9(void), intr10(void), intr11(void); 
void	intr12(void), intr13(void), intr14(void), intr15(void); 
1994/1029    
void	intr16(void), intr17(void), intr18(void); 
1991/0731    
void	intr24(void), intr25(void), intr26(void), intr27(void); 
void	intr28(void), intr29(void), intr30(void), intr31(void); 
1991/0904    
void	intr32(void), intr33(void), intr34(void), intr35(void); 
void	intr36(void), intr37(void), intr38(void), intr39(void); 
1991/0731    
void	intr64(void); 
void	intrbad(void); 
1997/0327    
static void debugbpt(Ureg*, void*); 
static void fault386(Ureg*, void*); 
static void syscall(Ureg*, void*); 
1991/0731    
 
1991/0613    
/* 
1991/0709    
 *  8259 interrupt controllers 
 */ 
enum 
{ 
	Int0ctl=	0x20,		/* control port (ICW1, OCW2, OCW3) */ 
	Int0aux=	0x21,		/* everything else (ICW2, ICW3, ICW4, OCW1) */ 
	Int1ctl=	0xA0,		/* control port */ 
	Int1aux=	0xA1,		/* everything else (ICW2, ICW3, ICW4, OCW1) */ 
1997/0327    
static Lock irqctllock; 
static Irqctl *irqctl[256]; 
1991/0709    
 
1995/0222    
	Icw1=		0x10,		/* select bit in ctl register */ 
	Ocw2=		0x00, 
	Ocw3=		0x08, 
                 
1991/0709    
	EOI=		0x20,		/* non-specific end of interrupt */ 
1993/0217    
                 
	Maxhandler=	128,		/* max number of interrupt handlers */ 
1991/0709    
}; 
                 
1991/1001    
int	int0mask = 0xff;	/* interrupts enabled for first 8259 */ 
int	int1mask = 0xff;	/* interrupts enabled for second 8259 */ 
1991/0709    
                 
/* 
1991/0614    
 *  trap/interrupt gates 
1991/0613    
 */ 
1991/0703    
Segdesc ilt[256]; 
1993/0224    
int badintr[16]; 
1991/0703    
                 
1993/0217    
typedef struct Handler	Handler; 
struct Handler 
{ 
1993/1124    
	void	(*r)(Ureg*, void*); 
	void	*arg; 
1993/0217    
	Handler	*next; 
}; 
                 
struct 
{ 
	Lock; 
	Handler	*ivec[256]; 
	Handler	h[Maxhandler]; 
	int	free; 
} halloc; 
                 
1991/0703    
void 
1991/0710    
sethvec(int v, void (*r)(void), int type, int pri) 
1997/0327    
intrenable(int v, void (*f)(Ureg*, void*), void* a, int tbdf) 
1991/0613    
{ 
1991/0703    
	ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16); 
1991/0710    
	ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type; 
1991/0703    
} 
1997/0327    
	Irq * irq; 
	Irqctl *ctl; 
1991/0614    
 
1991/0703    
void 
1993/1124    
setvec(int v, void (*r)(Ureg*, void*), void *arg) 
1991/0703    
{ 
1993/0217    
	Handler *h; 
1991/0709    
                 
1993/0217    
	lock(&halloc); 
	if(halloc.free >= Maxhandler) 
		panic("out of interrupt handlers"); 
	h = &halloc.h[halloc.free++]; 
	h->next = halloc.ivec[v]; 
	h->r = r; 
1993/1124    
	h->arg = arg; 
1993/0217    
	halloc.ivec[v] = h; 
	unlock(&halloc); 
                 
1991/0709    
	/* 
	 *  enable corresponding interrupt in 8259 
	 */ 
	if((v&~0x7) == Int0vec){ 
		int0mask &= ~(1<<(v&7)); 
		outb(Int0aux, int0mask); 
1991/0731    
	} else if((v&~0x7) == Int1vec){ 
		int1mask &= ~(1<<(v&7)); 
		outb(Int1aux, int1mask); 
1997/0327    
	lock(&irqctllock); 
	if(irqctl[v] == 0){ 
		ctl = xalloc(sizeof(Irqctl)); 
		if(arch->intrenable(v, tbdf, ctl) == -1){ 
			unlock(&irqctllock); 
			/* 
			print("intrenable: didn't find v %d, tbdf 0x%uX\n", v, tbdf); 
			 */ 
			xfree(ctl); 
			return; 
		} 
		irqctl[v] = ctl; 
1991/0709    
	} 
1997/0327    
	ctl = irqctl[v]; 
	irq = xalloc(sizeof(Irq)); 
	irq->f = f; 
	irq->a = a; 
	irq->next = ctl->irq; 
	ctl->irq = irq; 
	unlock(&irqctllock); 
1991/0703    
} 
 
1991/1112    
void 
1993/1124    
debugbpt(Ureg *ur, void *arg) 
1991/1112    
{ 
	char buf[ERRLEN]; 
                 
1993/1124    
	USED(arg); 
                 
1993/0915    
	if(up == 0) 
1991/1112    
		panic("kernel bpt"); 
	/* restore pc to instruction that caused the trap */ 
	ur->pc--; 
1991/1218    
	sprint(buf, "sys: breakpoint"); 
1993/1013    
	postnote(up, 1, buf, NDebug); 
1991/1112    
} 
                 
1991/0614    
/* 
1991/0703    
 *  set up the interrupt/trap gates 
1991/0614    
 */ 
1991/0703    
void 
trapinit(void) 
{ 
	int i; 
1997/0327    
	int v, pri; 
	ulong vaddr; 
	Segdesc *idt; 
1991/0614    
 
1991/0703    
	/* 
1991/0731    
	 *  set all interrupts to panics 
	 */ 
1991/0904    
	for(i = 0; i < 256; i++) 
1993/1114    
		sethvec(i, intrbad, SEGIG, 0); 
1997/0327    
	idt = (Segdesc*)IDTADDR; 
	vaddr = (ulong)vectortable; 
	for(v = 0; v < 256; v++){ 
		if(v == VectorBPT || v == VectorSYSCALL) 
			pri = 3; 
		else 
			pri = 0; 
		idt[v].d0 = (vaddr & 0xFFFF)|(KESEL<<16); 
		idt[v].d1 = (vaddr & 0xFFFF0000)|SEGP|SEGPL(pri)|SEGIG; 
		vaddr += 6; 
	} 
1991/0731    
 
	/* 
1991/0904    
	 *  80386 processor (and coprocessor) traps 
1991/0703    
	 */ 
1993/1114    
	sethvec(0, intr0, SEGIG, 0); 
	sethvec(1, intr1, SEGIG, 0); 
	sethvec(2, intr2, SEGIG, 0); 
	sethvec(4, intr4, SEGIG, 0); 
	sethvec(5, intr5, SEGIG, 0); 
	sethvec(6, intr6, SEGIG, 0); 
	sethvec(7, intr7, SEGIG, 0); 
	sethvec(8, intr8, SEGIG, 0); 
	sethvec(9, intr9, SEGIG, 0); 
	sethvec(10, intr10, SEGIG, 0); 
	sethvec(11, intr11, SEGIG, 0); 
	sethvec(12, intr12, SEGIG, 0); 
	sethvec(13, intr13, SEGIG, 0); 
1993/1115    
	sethvec(14, intr14, SEGIG, 0);	/* page fault */ 
1993/1114    
	sethvec(15, intr15, SEGIG, 0); 
1993/1115    
	sethvec(16, intr16, SEGIG, 0);	/* math coprocessor */ 
1994/1029    
	sethvec(17, intr17, SEGIG, 0); 
	sethvec(18, intr18, SEGIG, 0); 
1991/0731    
                 
	/* 
1991/0904    
	 *  device interrupts 
1991/0731    
	 */ 
1991/0904    
	sethvec(24, intr24, SEGIG, 0); 
	sethvec(25, intr25, SEGIG, 0); 
	sethvec(26, intr26, SEGIG, 0); 
	sethvec(27, intr27, SEGIG, 0); 
	sethvec(28, intr28, SEGIG, 0); 
	sethvec(29, intr29, SEGIG, 0); 
	sethvec(30, intr30, SEGIG, 0); 
	sethvec(31, intr31, SEGIG, 0); 
	sethvec(32, intr32, SEGIG, 0); 
	sethvec(33, intr33, SEGIG, 0); 
	sethvec(34, intr34, SEGIG, 0); 
	sethvec(35, intr35, SEGIG, 0); 
	sethvec(36, intr36, SEGIG, 0); 
1991/0913    
	sethvec(37, intr37, SEGIG, 0); 
1991/0904    
	sethvec(38, intr38, SEGIG, 0); 
	sethvec(39, intr39, SEGIG, 0); 
1991/0703    
                 
	/* 
1991/1214    
	 *  system calls and break points 
1991/0710    
	 */ 
1993/1114    
	sethvec(Syscallvec, intr64, SEGIG, 3); 
1993/1124    
	setvec(Syscallvec, syscall, 0); 
1993/1114    
	sethvec(Bptvec, intr3, SEGIG, 3); 
1993/1124    
	setvec(Bptvec, debugbpt, 0); 
1991/0710    
                 
1994/1007    
                 
1991/0710    
	/* 
1991/0703    
	 *  tell the hardware where the table is (and how long) 
	 */ 
1991/0718    
	putidt(ilt, sizeof(ilt)); 
1991/0704    
                 
	/* 
1991/0709    
	 *  Set up the first 8259 interrupt processor. 
	 *  Make 8259 interrupts start at CPU vector Int0vec. 
	 *  Set the 8259 as master with edge triggered 
	 *  input with fully nested interrupts. 
1991/0704    
	 */ 
1994/0603    
	outb(Int0ctl, (1<<4)|(0<<3)|(1<<0));	/* ICW1 - master, edge triggered, 
1994/0512    
					  	 ICW4 will be sent */ 
1991/0709    
	outb(Int0aux, Int0vec);		/* ICW2 - interrupt vector offset */ 
1991/0731    
	outb(Int0aux, 0x04);		/* ICW3 - have slave on level 2 */ 
1991/0709    
	outb(Int0aux, 0x01);		/* ICW4 - 8086 mode, not buffered */ 
1991/0731    
                 
	/* 
	 *  Set up the second 8259 interrupt processor. 
1994/0824    
	 *  Make 8259 interrupts start at CPU vector Int1vec. 
1995/0331    
	 *  Set the 8259 as master with level triggered 
1991/0731    
	 *  input with fully nested interrupts. 
	 */ 
1995/0502    
	outb(Int1ctl, (1<<4)|(0<<3)|(1<<0));	/* ICW1 - master, level triggered, 
1994/0512    
					  	 ICW4 will be sent */ 
1991/0731    
	outb(Int1aux, Int1vec);		/* ICW2 - interrupt vector offset */ 
	outb(Int1aux, 0x02);		/* ICW3 - I am a slave on level 2 */ 
	outb(Int1aux, 0x01);		/* ICW4 - 8086 mode, not buffered */ 
                 
	/* 
	 *  pass #2 8259 interrupts to #1 
	 */ 
	int0mask &= ~0x04; 
	outb(Int0aux, int0mask); 
1995/0222    
                 
	/* 
	 * Set Ocw3 to return the ISR when ctl read. 
	 */ 
	outb(Int0ctl, Ocw3|0x03); 
	outb(Int1ctl, Ocw3|0x03); 
1997/0327    
	intrenable(VectorBPT, debugbpt, 0, BUSUNKNOWN); 
	intrenable(VectorPF, fault386, 0, BUSUNKNOWN); 
	intrenable(VectorSYSCALL, syscall, 0, BUSUNKNOWN); 
1991/0703    
} 
 
1994/0722    
char *excname[] = { 
	[0]	"divide error", 
	[1]	"debug exception", 
	[2]	" nonmaskable interrupt", 
1997/0327    
	[2]	"nonmaskable interrupt", 
1994/0722    
	[3]	"breakpoint", 
	[4]	"overflow", 
	[5]	"bounds check", 
1996/0802/sys/src/9/pc/trap.c:231,2371997/0327/sys/src/9/pc/trap.c:78,84
1994/0722    
	[6]	"invalid opcode", 
	[7]	"coprocessor not available", 
	[8]	"double fault", 
	[9]	"9 (reserved)", 
1997/0327    
	[9]	"coprocessor segment overrun", 
1994/0722    
	[10]	"invalid TSS", 
	[11]	"segment not present", 
	[12]	"stack exception", 
1996/0802/sys/src/9/pc/trap.c:240,2501997/0327/sys/src/9/pc/trap.c:87,96
1994/0722    
	[15]	"15 (reserved)", 
	[16]	"coprocessor error", 
1994/1029    
	[17]	"alignment check", 
	[18]	"something bad happened", 
1997/0327    
	[18]	"machine check", 
1991/1113    
}; 
 
1994/1029    
Ureg lastur; 
Ureg scndlastur; 
1997/0327    
static int nspuriousintr; 
1994/1029    
 
1991/0614    
/* 
1993/1124    
 *  All traps come here.  It is slower to have all traps call trap() rather than 
1996/0802/sys/src/9/pc/trap.c:252,3491997/0327/sys/src/9/pc/trap.c:98,159
1994/0715    
 *  and possible bugs.  trap is called splhi(). 
1991/0614    
 */ 
1991/0710    
void 
1991/0703    
trap(Ureg *ur) 
1997/0327    
trap(Ureg* ureg) 
1991/0614    
{ 
1991/1112    
	int v, user; 
1991/0731    
	int c; 
1991/1113    
	char buf[ERRLEN]; 
1993/0217    
	Handler *h; 
1993/1116    
	static int iret_traps; 
1995/0223    
	ushort isr; 
1997/0327    
	Irqctl *ctl; 
	Irq *irq; 
1991/0703    
 
1991/0731    
	v = ur->trap; 
                 
1993/1113    
	user = (ur->cs&0xffff) == UESEL; 
1997/0327    
	user = (ureg->cs & 0xFFFF) == UESEL; 
1991/1112    
	if(user) 
1993/0915    
		up->dbgreg = ur; 
1993/1116    
	else if(ur->pc <= (ulong)end && *(uchar*)ur->pc == 0xCF) { 
		if(iret_traps++ > 10) 
			panic("iret trap"); 
1996/0626    
		goto saveout; 
1993/1116    
	} 
	iret_traps = 0; 
1997/0327    
		up->dbgreg = ureg; 
1991/1112    
 
1991/0709    
	/* 
	 *  tell the 8259 that we're done with the 
1991/0801    
	 *  highest level interrupt (interrupts are still 
	 *  off at this point) 
1991/0709    
	 */ 
1991/0731    
	c = v&~0x7; 
1995/0223    
	isr = 0; 
1991/0731    
	if(c==Int0vec || c==Int1vec){ 
1995/0223    
		isr = inb(Int0ctl); 
1993/0225    
		outb(Int0ctl, EOI); 
1995/0222    
		if(c == Int1vec){ 
1995/0223    
			isr |= inb(Int1ctl)<<8; 
1991/0731    
			outb(Int1ctl, EOI); 
1995/0222    
		} 
1991/1113    
	} 
1997/0327    
	v = ureg->trap; 
	if(ctl = irqctl[v]){ 
		if(ctl->isintr) 
			m->intr++; 
		if(ctl->isr) 
			ctl->isr(v); 
1991/1113    
 
1993/0217    
	if(v>=256 || (h = halloc.ivec[v]) == 0){ 
1997/0327    
		for(irq = ctl->irq; irq; irq = irq->next) 
			irq->f(ureg, irq->a); 
1993/0224    
 
		/* a processor or coprocessor error */ 
1991/1113    
		if(v <= 16){ 
			if(user){ 
1996/0626    
				spllo(); 
1991/1218    
				sprint(buf, "sys: trap: %s", excname[v]); 
1993/1013    
				postnote(up, 1, buf, NDebug); 
1994/1029    
				goto out; 
1991/1113    
			} else { 
				dumpregs(ur); 
				panic("%s pc=0x%lux", excname[v], ur->pc); 
			} 
		} 
1993/0224    
                 
1995/0223    
		if(v >= Int0vec && v < Int0vec+16){ 
1994/0722    
			/* an unknown interrupt */ 
1993/0224    
			v -= Int0vec; 
1995/0222    
			/* 
			 * 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. 
1995/0223    
			 * In fact, just ignore all such interrupts. 
1995/0222    
			 */ 
1995/0223    
			if((isr & (1<<v)) == 0) 
1996/0626    
				goto saveout; 
1995/0222    
			if(badintr[v]++ == 0 || (badintr[v]%100000) == 0){ 
1993/0224    
				print("unknown interrupt %d pc=0x%lux: total %d\n", v, 
					ur->pc, badintr[v]); 
1995/0223    
				print("isr = 0x%4.4ux\n", isr); 
1995/0222    
			} 
1993/0224    
		} else { 
			/* unimplemented traps */ 
			print("illegal trap %d pc=0x%lux\n", v, ur->pc); 
		} 
1996/0626    
		goto saveout; 
1997/0327    
		if(ctl->eoi) 
			ctl->eoi(v); 
1991/0731    
	} 
1997/0327    
	else if(v <= 16 && user){ 
		spllo(); 
		sprint(buf, "sys: trap: %s", excname[v]); 
		postnote(up, 1, buf, NDebug); 
	} 
	else if(v >= VectorPIC && v <= 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. 
		 */ 
		if(nspuriousintr < 2) 
			print("spurious interrupt %d\n", v-VectorPIC); 
		nspuriousintr++; 
		return; 
	} 
	else{ 
		dumpregs(ureg); 
		if(v < nelem(excname)) 
			panic("%s", excname[v]); 
		panic("unknown trap/intr: %d\n", v); 
	} 
1991/0801    
 
1993/0224    
	/* there may be multiple handlers on one interrupt level */ 
1993/0217    
	do { 
1993/1124    
		(*h->r)(ur, h->arg); 
1993/0217    
		h = h->next; 
	} while(h); 
1991/0910    
                 
1994/0715    
	/* 
	 *  check user since syscall does its own notifying 
	 */ 
1996/0626    
out: 
1993/0915    
	splhi(); 
1994/0715    
	if(v != Syscallvec && user && (up->procctl || up->nnote)) 
1991/0910    
		notify(ur); 
1996/0626    
saveout: 
1994/1029    
	scndlastur = lastur; 
	lastur = *ur; 
1997/0327    
	if(v != VectorSYSCALL && user && (up->procctl || up->nnote)) 
		notify(ureg); 
1991/0806    
} 
 
/* 
1996/0802/sys/src/9/pc/trap.c:350,3941997/0327/sys/src/9/pc/trap.c:160,214
1991/0718    
 *  dump registers 
 */ 
void 
1993/0915    
dumpregs2(Ureg *ur) 
1997/0327    
dumpregs2(Ureg* ureg) 
1991/0718    
{ 
1993/1115    
	ur->cs &= 0xffff; 
	ur->ds &= 0xffff; 
	ur->es &= 0xffff; 
	ur->fs &= 0xffff; 
	ur->gs &= 0xffff; 
1997/0327    
	ureg->cs &= 0xFFFF; 
	ureg->ds &= 0xFFFF; 
	ureg->es &= 0xFFFF; 
	ureg->fs &= 0xFFFF; 
	ureg->gs &= 0xFFFF; 
1993/1115    
 
1993/0915    
	if(up) 
		print("registers for %s %d\n", up->text, up->pid); 
1997/0327    
		print("cpu%d: registers for %s %d\n", m->machno, up->text, up->pid); 
1991/0718    
	else 
		print("registers for kernel\n"); 
1993/1115    
	print("FLAGS=%lux TRAP=%lux ECODE=%lux CS=%4.4lux PC=%lux", ur->flags, ur->trap, 
1993/1113    
		ur->ecode, ur->cs, ur->pc); 
1993/1115    
	print(" SS=%4.4lux USP=%lux\n", ur->ss&0xffff, ur->usp); 
1991/0718    
	print("  AX %8.8lux  BX %8.8lux  CX %8.8lux  DX %8.8lux\n", 
		ur->ax, ur->bx, ur->cx, ur->dx); 
1991/1214    
	print("  SI %8.8lux  DI %8.8lux  BP %8.8lux\n", 
		ur->si, ur->di, ur->bp); 
1993/1113    
	print("  DS %4.4lux  ES %4.4lux  FS %4.4lux  GS %4.4lux\n", 
		ur->ds, ur->es, ur->fs, ur->gs); 
1997/0327    
		print("cpu%d: registers for kernel\n", m->machno); 
	print("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX", ureg->flags, ureg->trap, 
		ureg->ecode, ureg->pc); 
	print(" SS=%4.4luX USP=%luX\n", ureg->ss & 0xFFFF, ureg->usp); 
	print("  AX %8.8luX  BX %8.8luX  CX %8.8luX  DX %8.8luX\n", 
		ureg->ax, ureg->bx, ureg->cx, ureg->dx); 
	print("  SI %8.8luX  DI %8.8luX  BP %8.8luX\n", 
		ureg->si, ureg->di, ureg->bp); 
	print("  CS %4.4uX  DS %4.4uX  ES %4.4uX  FS %4.4uX  GS %4.4uX\n", 
		ureg->cs, ureg->ds, ureg->es, ureg->fs, ureg->gs); 
1991/0718    
} 
 
1991/0720    
void 
1993/0915    
dumpregs(Ureg *ur) 
1997/0327    
dumpregs(Ureg* ureg) 
1993/0915    
{ 
1994/0813    
	extern ulong etext; 
1993/1113    
	ulong *x; 
1997/0327    
	ulong mca[2], mct[2]; 
1993/1113    
 
1997/0327    
	dumpregs2(ureg); 
1994/0813    
 
1993/1113    
	x = (ulong*)(ur+1); 
1996/0802    
/* 
1994/1029    
	dumpregs2(&scndlastur); 
	dumpregs2(&lastur); 
1996/0802    
*/ 
1993/0915    
	dumpregs2(ur); 
1994/0902    
	print("  CR0 %8.8lux CR2 %8.8lux\n", getcr0(), getcr2()); 
1993/1113    
	print("  magic %lux %lux %lux\n", x[0], x[1], x[2]); 
	print("  ur %lux up %lux\n", ur, up); 
1997/0327    
	/* 
	 * Processor control registers. 
	 * If machine check exception, time stamp counter, page size extensions or 
	 * enhanced virtual 8086 mode extensions are supported, there is a CR4. 
	 * If there is a CR4 and machine check extensions, read the machine check 
	 * address and machine check type registers if RDMSR supported. 
	 */ 
	print("  CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux", getcr0(), getcr2(), getcr3()); 
	if(m->cpuiddx & 0x9A){ 
		print(" CR4 %8.8luX", getcr4()); 
		if((m->cpuiddx & 0xA0) == 0xA0){ 
			rdmsr(0x00, &mca[1], &mca[0]); 
			rdmsr(0x01, &mct[1], &mct[0]); 
			print("\n  MCA %8.8luX:%8.8luX MCT %8.8luX", 
				mca[1], mca[0], mct[0]); 
		} 
	} 
	print("\n  ur %luX up %luX\n", ureg, up); 
1993/0915    
} 
 
void 
1996/0802/sys/src/9/pc/trap.c:395,4001997/0327/sys/src/9/pc/trap.c:215,221
1991/0720    
dumpstack(void) 
{ 
1992/0804    
	ulong l, v, i; 
1997/0327    
	uchar *p; 
1992/0804    
	extern ulong etext; 
 
1993/0915    
	if(up == 0) 
1996/0802/sys/src/9/pc/trap.c:404,4111997/0327/sys/src/9/pc/trap.c:225,235
1994/0816    
	for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){ 
1992/0804    
		v = *(ulong*)l; 
		if(KTZERO < v && v < (ulong)&etext){ 
			print("%lux ", v); 
			i++; 
1997/0327    
			p = (uchar*)v; 
			if(*(p-5) == 0xE8){ 
				print("%lux ", p-5); 
				i++; 
			} 
1992/0804    
		} 
1993/1113    
		if(i == 8){ 
1992/0804    
			i = 0; 
1996/0802/sys/src/9/pc/trap.c:414,4191997/0327/sys/src/9/pc/trap.c:238,283
1992/0804    
	} 
1991/0720    
} 
 
1997/0327    
static void 
debugbpt(Ureg* ureg, void*) 
{ 
	char buf[ERRLEN]; 
 
	if(up == 0) 
		panic("kernel bpt"); 
	/* restore pc to instruction that caused the trap */ 
	ureg->pc--; 
	sprint(buf, "sys: breakpoint"); 
	postnote(up, 1, buf, NDebug); 
} 
 
static void 
fault386(Ureg* ureg, void*) 
{ 
	ulong addr; 
	int read, user, n, insyscall; 
	char buf[ERRLEN]; 
 
	insyscall = up->insyscall; 
	up->insyscall = 1; 
	addr = getcr2(); 
	read = !(ureg->ecode & 2); 
	user = (ureg->cs&0xffff) == UESEL; 
	spllo(); 
	n = fault(addr, read); 
	if(n < 0){ 
		if(user){ 
			sprint(buf, "sys: trap: fault %s addr=0x%lux", 
				read? "read" : "write", addr); 
			postnote(up, 1, buf, NDebug); 
			return; 
		} 
		dumpregs(ureg); 
		panic("fault: 0x%lux\n", addr); 
	} 
	up->insyscall = insyscall; 
} 
 
1991/0718    
/* 
1991/0710    
 *  system calls 
 */ 
1996/0802/sys/src/9/pc/trap.c:422,4451997/0327/sys/src/9/pc/trap.c:286,307
1992/0103    
/* 
1994/0715    
 *  syscall is called splhi() 
1992/0103    
 */ 
1993/1124    
void 
syscall(Ureg *ur, void *arg) 
1997/0327    
static void 
syscall(Ureg* ureg, void*) 
1991/0710    
{ 
1991/0720    
	ulong	sp; 
	long	ret; 
	int	i; 
 
1993/1124    
	USED(arg); 
                 
1994/0715    
                 
1997/0327    
	m->syscall++; 
1993/0915    
	up->insyscall = 1; 
	up->pc = ur->pc; 
1993/1225    
	up->dbgreg = ur; 
1997/0327    
	up->pc = ureg->pc; 
	up->dbgreg = ureg; 
1993/1225    
 
1991/0720    
	if((ur->cs)&0xffff == KESEL) 
1997/0327    
	if((ureg->cs)&0xffff == KESEL) 
1991/0720    
		panic("recursive system call"); 
1991/0718    
 
1993/0915    
	up->scallnr = ur->ax; 
1997/0327    
	up->scallnr = ureg->ax; 
1993/0915    
	if(up->scallnr == RFORK && up->fpstate == FPactive){ 
1992/0805    
		/* 
		 *  so that the child starts out with the 
1996/0802/sys/src/9/pc/trap.c:454,4651997/0327/sys/src/9/pc/trap.c:316,327
1992/0805    
	} 
1994/0715    
	spllo(); 
 
1991/0720    
	sp = ur->usp; 
1997/0327    
	sp = ureg->usp; 
1993/0915    
	up->nerrlab = 0; 
1991/0720    
	ret = -1; 
	if(!waserror()){ 
1994/0407    
		if(up->scallnr >= nsyscall){ 
1993/0915    
			pprint("bad sys call number %d pc %lux\n", up->scallnr, ur->pc); 
1997/0327    
			pprint("bad sys call number %d pc %lux\n", up->scallnr, ureg->pc); 
1993/1013    
			postnote(up, 1, "sys: bad sys call", NDebug); 
1991/0720    
			error(Ebadarg); 
		} 
1996/0802/sys/src/9/pc/trap.c:470,4761997/0327/sys/src/9/pc/trap.c:332,338
1993/0915    
		up->s = *((Sargs*)(sp+1*BY2WD)); 
		up->psstate = sysctab[up->scallnr]; 
1992/0625    
 
1993/0915    
		ret = (*systab[up->scallnr])(up->s.args); 
1997/0327    
		ret = systab[up->scallnr](up->s.args); 
1991/0720    
		poperror(); 
	} 
1993/0915    
	if(up->nerrlab){ 
1996/0802/sys/src/9/pc/trap.c:489,5021997/0327/sys/src/9/pc/trap.c:351,364
1992/0609    
	 *  ignored.  On other machines the return value is put into 
	 *  the results register by caller of syscall. 
	 */ 
1991/0801    
	ur->ax = ret; 
1997/0327    
	ureg->ax = ret; 
1992/0609    
 
1993/0915    
	if(up->scallnr == NOTED) 
1991/0720    
		noted(ur, *(ulong*)(sp+BY2WD)); 
1997/0327    
		noted(ureg, *(ulong*)(sp+BY2WD)); 
1995/0105    
	splhi(); 
1991/1114    
 
1993/0915    
	if(up->scallnr!=RFORK && (up->procctl || up->nnote)) 
1991/0720    
		notify(ur); 
1997/0327    
		notify(ureg); 
1995/0115    
 
1991/0710    
} 
 
1996/0802/sys/src/9/pc/trap.c:505,5111997/0327/sys/src/9/pc/trap.c:367,373
1991/0720    
 *  Pass user the Ureg struct and the note on his stack. 
 */ 
1992/0108    
int 
1991/0720    
notify(Ureg *ur) 
1997/0327    
notify(Ureg* ureg) 
1991/0710    
{ 
1995/0202    
	int l; 
1991/1114    
	ulong s, sp; 
1996/0802/sys/src/9/pc/trap.c:524,5301997/0327/sys/src/9/pc/trap.c:386,392
1991/1218    
		l = strlen(n->msg); 
		if(l > ERRLEN-15)	/* " pc=0x12345678\0" */ 
			l = ERRLEN-15; 
		sprint(n->msg+l, " pc=0x%.8lux", ur->pc); 
1997/0327    
		sprint(n->msg+l, " pc=0x%.8lux", ureg->pc); 
1991/1218    
	} 
1995/0202    
 
1993/0915    
	if(n->flag!=NUser && (up->notified || up->notify==0)){ 
1996/0802/sys/src/9/pc/trap.c:544,5501997/0327/sys/src/9/pc/trap.c:406,412
1995/0202    
		qunlock(&up->debug); 
		pexit(n->msg, n->flag!=NDebug); 
	} 
	sp = ur->usp; 
1997/0327    
	sp = ureg->usp; 
1995/0202    
	sp -= sizeof(Ureg); 
 
	if(!okaddr((ulong)up->notify, 1, 0) 
1996/0802/sys/src/9/pc/trap.c:555,5611997/0327/sys/src/9/pc/trap.c:417,423
1995/0202    
	} 
 
	up->ureg = (void*)sp; 
	memmove((Ureg*)sp, ur, sizeof(Ureg)); 
1997/0327    
	memmove((Ureg*)sp, ureg, sizeof(Ureg)); 
1995/0202    
	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */ 
	up->ureg = (void*)sp; 
	sp -= BY2WD+ERRLEN; 
1996/0802/sys/src/9/pc/trap.c:564,5711997/0327/sys/src/9/pc/trap.c:426,433
1995/0202    
	*(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 */ 
	ur->usp = sp; 
	ur->pc = (ulong)up->notify; 
1997/0327    
	ureg->usp = sp; 
	ureg->pc = (ulong)up->notify; 
1995/0202    
	up->notified = 1; 
	up->nnote--; 
	memmove(&up->lastnote, &up->note[0], sizeof(Note)); 
1996/0802/sys/src/9/pc/trap.c:580,5881997/0327/sys/src/9/pc/trap.c:442,450
1991/0720    
 *   Return user to state before notify() 
 */ 
1991/0710    
void 
1991/0720    
noted(Ureg *ur, ulong arg0) 
1997/0327    
noted(Ureg* ureg, ulong arg0) 
1991/0710    
{ 
1991/0720    
	Ureg *nur; 
1997/0327    
	Ureg *nureg; 
1995/0202    
	ulong oureg, sp; 
1991/0720    
 
1993/0915    
	qlock(&up->debug); 
1996/0802/sys/src/9/pc/trap.c:593,6021997/0327/sys/src/9/pc/trap.c:455,464
1991/0720    
	} 
1993/0915    
	up->notified = 0; 
1994/0513    
 
	nur = up->ureg;		/* pointer to user returned Ureg struct */ 
1997/0327    
	nureg = up->ureg;		/* pointer to user returned Ureg struct */ 
1995/0202    
 
	/* sanity clause */ 
	oureg = (ulong)nur; 
1997/0327    
	oureg = (ulong)nureg; 
1995/02021    
	if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){ 
1995/0202    
		pprint("bad ureg in noted or call to noted() when not notified\n"); 
1994/0513    
		qunlock(&up->debug); 
1996/0802/sys/src/9/pc/trap.c:604,6211997/0327/sys/src/9/pc/trap.c:466,483
1994/0513    
	} 
 
1995/0202    
	/* don't let user change text or stack segments */ 
	nur->cs = ur->cs; 
	nur->ss = ur->ss; 
1997/0327    
	nureg->cs = ureg->cs; 
	nureg->ss = ureg->ss; 
1995/0202    
 
	/* don't let user change system flags */ 
	nur->flags = (ur->flags & ~0xCD5) | (nur->flags & 0xCD5); 
1997/0327    
	nureg->flags = (ureg->flags & ~0xCD5) | (nureg->flags & 0xCD5); 
1995/0202    
 
1992/0609    
	memmove(ur, nur, sizeof(Ureg)); 
1997/0327    
	memmove(ureg, nureg, sizeof(Ureg)); 
1995/0105    
 
1991/0720    
	switch(arg0){ 
	case NCONT: 
1995/0202    
	case NRSTR: 
1992/0616    
		if(!okaddr(nur->pc, 1, 0) || !okaddr(nur->usp, BY2WD, 0)){ 
1997/0327    
		if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){ 
1991/0814    
			pprint("suicide: trap in noted\n"); 
1995/0202    
			qunlock(&up->debug); 
1994/0513    
			pexit("Suicide", 0); 
1996/0802/sys/src/9/pc/trap.c:625,6311997/0327/sys/src/9/pc/trap.c:487,493
1995/0105    
		break; 
1991/0720    
 
1995/0202    
	case NSAVE: 
		if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){ 
1997/0327    
		if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->usp, BY2WD, 0)){ 
1995/0202    
			pprint("suicide: trap in noted\n"); 
			qunlock(&up->debug); 
			pexit("Suicide", 0); 
1996/0802/sys/src/9/pc/trap.c:633,6391997/0327/sys/src/9/pc/trap.c:495,501
1995/0202    
		qunlock(&up->debug); 
		sp = oureg-4*BY2WD-ERRLEN; 
		splhi(); 
		ur->sp = sp; 
1997/0327    
		ureg->sp = sp; 
1995/0202    
		((ulong*)sp)[1] = oureg;	/* arg 1 0(FP) is ureg* */ 
		((ulong*)sp)[0] = 0;		/* arg 0 is pc */ 
		break; 
1996/0802/sys/src/9/pc/trap.c:655,6681997/0327/sys/src/9/pc/trap.c:517,530
1993/1113    
execregs(ulong entry, ulong ssize, ulong nargs) 
{ 
	ulong *sp; 
	Ureg *ur; 
1997/0327    
	Ureg *ureg; 
1993/1113    
 
	sp = (ulong*)(USTKTOP - ssize); 
	*--sp = nargs; 
 
	ur = up->dbgreg; 
	ur->usp = (ulong)sp; 
	ur->pc = entry; 
1997/0327    
	ureg = up->dbgreg; 
	ureg->usp = (ulong)sp; 
	ureg->pc = entry; 
1994/0513    
	return USTKTOP-BY2WD;		/* address of user-level clock */ 
1993/1113    
} 
 
1996/0802/sys/src/9/pc/trap.c:669,6971997/0327/sys/src/9/pc/trap.c:531,559
1993/1113    
ulong 
userpc(void) 
{ 
	Ureg *ur; 
1997/0327    
	Ureg *ureg; 
1993/1113    
 
	ur = (Ureg*)up->dbgreg; 
	return ur->pc; 
1997/0327    
	ureg = (Ureg*)up->dbgreg; 
	return ureg->pc; 
1993/1113    
} 
 
1991/1112    
/* This routine must save the values of registers the user is not permitted to write 
 * from devproc and the restore the saved values before returning 
1997/0327    
 * from devproc and then restore the saved values before returning 
1991/1112    
 */ 
void 
setregisters(Ureg *xp, char *pureg, char *uva, int n) 
1997/0327    
setregisters(Ureg* ureg, char* pureg, char* uva, int n) 
1991/1112    
{ 
	ulong flags; 
	ulong cs; 
	ulong ss; 
 
	flags = xp->flags; 
	cs = xp->cs; 
	ss = xp->ss; 
1997/0327    
	flags = ureg->flags; 
	cs = ureg->cs; 
	ss = ureg->ss; 
1991/1112    
	memmove(pureg, uva, n); 
	xp->flags = (xp->flags & 0xff) | (flags & 0xff00); 
	xp->cs = cs; 
	xp->ss = ss; 
1997/0327    
	ureg->flags = (ureg->flags & 0x00FF) | (flags & 0xFF00); 
	ureg->cs = cs; 
	ureg->ss = ss; 
1993/1113    
} 
 
static void 
1996/0802/sys/src/9/pc/trap.c:698,7081997/0327/sys/src/9/pc/trap.c:560,570
1993/1113    
linkproc(void) 
{ 
	spllo(); 
	(*up->kpfun)(up->kparg); 
1997/0327    
	up->kpfun(up->kparg); 
1993/1113    
} 
 
void 
kprocchild(Proc *p, void (*func)(void*), void *arg) 
1997/0327    
kprocchild(Proc* p, void (*func)(void*), void* arg) 
1993/1113    
{ 
	p->sched.pc = (ulong)linkproc; 
	p->sched.sp = (ulong)p->kstack+KSTACK; 
1996/0802/sys/src/9/pc/trap.c:712,7231997/0327/sys/src/9/pc/trap.c:574,585
1993/1113    
} 
 
void 
forkchild(Proc *p, Ureg *ur) 
1997/0327    
forkchild(Proc *p, Ureg *ureg) 
1993/1113    
{ 
	Ureg *cur; 
1997/0327    
	Ureg *cureg; 
1993/1113    
 
	/* 
	 * We add 2*BY2Wd to the stack because we have to account for 
1997/0327    
	 * Add 2*BY2WD to the stack to account for 
1993/1113    
	 *  - the return PC 
	 *  - trap's argument (ur) 
	 */ 
1996/0802/sys/src/9/pc/trap.c:724,7341997/0327/sys/src/9/pc/trap.c:586,596
1993/1113    
	p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Ureg)+2*BY2WD); 
	p->sched.pc = (ulong)forkret; 
 
	cur = (Ureg*)(p->sched.sp+2*BY2WD); 
	memmove(cur, ur, sizeof(Ureg)); 
	cur->ax = 0;				/* return value of syscall in child */ 
1997/0327    
	cureg = (Ureg*)(p->sched.sp+2*BY2WD); 
	memmove(cureg, ureg, sizeof(Ureg)); 
	cureg->ax = 0;				/* return value of syscall in child */ 
1993/1113    
 
	/* Things from bottom of syscall we never got to execute */ 
1997/0327    
	/* Things from bottom of syscall which were never executed */ 
1993/1113    
	p->psstate = 0; 
	p->insyscall = 0; 
1991/0614    
} 
1996/0802/sys/src/9/pc/trap.c:737,7561997/0327/sys/src/9/pc/trap.c:599,618
1993/1022    
 * a sleeping process 
 */ 
void 
setkernur(Ureg *xp, Proc *p) 
1997/0327    
setkernur(Ureg* ureg, Proc* p) 
1993/1022    
{ 
	xp->pc = p->sched.pc; 
1994/0219    
	xp->sp = p->sched.sp+4; 
1997/0327    
	ureg->pc = p->sched.pc; 
	ureg->sp = p->sched.sp+4; 
1993/1022    
} 
1995/1024    
 
ulong 
dbgpc(Proc *p) 
{ 
	Ureg *ur; 
1997/0327    
	Ureg *ureg; 
1995/1024    
 
	ur = p->dbgreg; 
	if(ur == 0) 
1997/0327    
	ureg = p->dbgreg; 
	if(ureg == 0) 
1995/1024    
		return 0; 
 
	return ur->pc; 
1997/0327    
	return ureg->pc; 
1995/1024    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)