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

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

pc/trap.c on 1991/0613
1991/0613    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1991/0613    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
1991/0703    
#include	"ureg.h" 
1992/0111    
#include	"../port/error.h" 
1991/0613    
 
1991/0720    
void	noted(Ureg*, ulong); 
 
1997/0327    
static void debugbpt(Ureg*, void*); 
static void fault386(Ureg*, void*); 
static void syscall(Ureg*, void*); 
1991/0731    
 
1997/0327    
static Lock irqctllock; 
static Irqctl *irqctl[256]; 
1991/0709    
 
1991/0703    
void 
1997/0327    
intrenable(int v, void (*f)(Ureg*, void*), void* a, int tbdf) 
1991/0613    
{ 
1997/0327    
	Irq * irq; 
	Irqctl *ctl; 
1991/0614    
 
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    
} 
 
1997/0405    
static void 
nmienable(void) 
{ 
	int x; 
 
	/* 
	 * Hack: should be locked with NVRAM access. 
	 */ 
	outb(0x70, 0x80); 
	outb(0x70, 0); 
 
	x = inb(0x61); 
	outb(0x61, 0x08|x); 
	outb(0x61, x & ~0x08); 
} 
 
1991/1112    
void 
1991/0703    
trapinit(void) 
{ 
1997/0327    
	int v, pri; 
	ulong vaddr; 
	Segdesc *idt; 
1991/0614    
 
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    
 
1997/0327    
	intrenable(VectorBPT, debugbpt, 0, BUSUNKNOWN); 
	intrenable(VectorPF, fault386, 0, BUSUNKNOWN); 
	intrenable(VectorSYSCALL, syscall, 0, BUSUNKNOWN); 
1997/0405    
 
	nmienable(); 
1991/0703    
} 
 
1994/0722    
char *excname[] = { 
	[0]	"divide error", 
	[1]	"debug exception", 
1997/0327    
	[2]	"nonmaskable interrupt", 
1994/0722    
	[3]	"breakpoint", 
	[4]	"overflow", 
	[5]	"bounds check", 
	[6]	"invalid opcode", 
	[7]	"coprocessor not available", 
	[8]	"double fault", 
1997/0327    
	[9]	"coprocessor segment overrun", 
1994/0722    
	[10]	"invalid TSS", 
	[11]	"segment not present", 
	[12]	"stack exception", 
	[13]	"general protection violation", 
	[14]	"page fault", 
	[15]	"15 (reserved)", 
	[16]	"coprocessor error", 
1994/1029    
	[17]	"alignment check", 
1997/0327    
	[18]	"machine check", 
1991/1113    
}; 
 
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 
1993/1115    
 *  directly vectoring the handler.  However, this avoids a lot of code duplication 
1994/0715    
 *  and possible bugs.  trap is called splhi(). 
1991/0614    
 */ 
1991/0710    
void 
1997/0327    
trap(Ureg* ureg) 
1991/0614    
{ 
1991/1112    
	int v, user; 
1991/1113    
	char buf[ERRLEN]; 
1997/0327    
	Irqctl *ctl; 
	Irq *irq; 
1991/0703    
 
1997/0327    
	user = (ureg->cs & 0xFFFF) == UESEL; 
1991/1112    
	if(user) 
1997/0327    
		up->dbgreg = ureg; 
1991/1112    
 
1997/0327    
	v = ureg->trap; 
	if(ctl = irqctl[v]){ 
		if(ctl->isintr) 
			m->intr++; 
		if(ctl->isr) 
			ctl->isr(v); 
1991/1113    
 
1997/0327    
		for(irq = ctl->irq; irq; irq = irq->next) 
			irq->f(ureg, irq->a); 
1993/0224    
 
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{ 
1997/0405    
		if(v == 2){ 
			if(m->machno != 0) 
				for(;;); 
			nmienable(); 
		} 
1997/0327    
		dumpregs(ureg); 
		if(v < nelem(excname)) 
			panic("%s", excname[v]); 
		panic("unknown trap/intr: %d\n", v); 
	} 
1991/0801    
 
1994/0715    
	/* 
	 *  check user since syscall does its own notifying 
	 */ 
1993/0915    
	splhi(); 
1997/0327    
	if(v != VectorSYSCALL && user && (up->procctl || up->nnote)) 
		notify(ureg); 
1991/0806    
} 
 
/* 
1991/0718    
 *  dump registers 
 */ 
void 
1997/0327    
dumpregs2(Ureg* ureg) 
1991/0718    
{ 
1997/0327    
	ureg->cs &= 0xFFFF; 
	ureg->ds &= 0xFFFF; 
	ureg->es &= 0xFFFF; 
	ureg->fs &= 0xFFFF; 
	ureg->gs &= 0xFFFF; 
1993/1115    
 
1993/0915    
	if(up) 
1997/0327    
		print("cpu%d: registers for %s %d\n", m->machno, up->text, up->pid); 
1991/0718    
	else 
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 
1997/0327    
dumpregs(Ureg* ureg) 
1993/0915    
{ 
1994/0813    
	extern ulong etext; 
1997/0327    
	ulong mca[2], mct[2]; 
1993/1113    
 
1997/0327    
	dumpregs2(ureg); 
1994/0813    
 
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 
1991/0720    
dumpstack(void) 
{ 
1992/0804    
	ulong l, v, i; 
1997/0327    
	uchar *p; 
1992/0804    
	extern ulong etext; 
 
1993/0915    
	if(up == 0) 
1992/0804    
		return; 
 
	i = 0; 
1994/0816    
	for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){ 
1992/0804    
		v = *(ulong*)l; 
		if(KTZERO < v && v < (ulong)&etext){ 
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; 
			print("\n"); 
		} 
	} 
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; 
		} 
1997/1011    
		if(mmukmapsync(addr) == 0){	 
			dumpregs(ureg); 
			panic("fault: 0x%lux\n", addr); 
		} 
1997/0327    
	} 
	up->insyscall = insyscall; 
} 
 
1991/0718    
/* 
1991/0710    
 *  system calls 
 */ 
1991/0731    
#include "../port/systab.h" 
1991/0720    
 
1992/0103    
/* 
1994/0715    
 *  syscall is called splhi() 
1992/0103    
 */ 
1997/0327    
static void 
syscall(Ureg* ureg, void*) 
1991/0710    
{ 
1991/0720    
	ulong	sp; 
	long	ret; 
	int	i; 
 
1997/0327    
	m->syscall++; 
1993/0915    
	up->insyscall = 1; 
1997/0327    
	up->pc = ureg->pc; 
	up->dbgreg = ureg; 
1993/1225    
 
1997/0327    
	if((ureg->cs)&0xffff == KESEL) 
1991/0720    
		panic("recursive system call"); 
1991/0718    
 
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 
1994/0715    
		 *  same registers as the parent. 
		 *  this must be atomic relative to this CPU, hence 
		 *  the spl's. 
1992/0805    
		 */ 
1993/0915    
		if(up->fpstate == FPactive){ 
			fpsave(&up->fpsave); 
			up->fpstate = FPinactive; 
1992/0805    
		} 
	} 
1994/0715    
	spllo(); 
 
1997/0327    
	sp = ureg->usp; 
1993/0915    
	up->nerrlab = 0; 
1991/0720    
	ret = -1; 
	if(!waserror()){ 
1994/0407    
		if(up->scallnr >= nsyscall){ 
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); 
		} 
1992/0625    
 
1991/0720    
		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(1+MAXSYSARG)*BY2WD)) 
			validaddr(sp, (1+MAXSYSARG)*BY2WD, 0); 
1992/0625    
 
1993/0915    
		up->s = *((Sargs*)(sp+1*BY2WD)); 
		up->psstate = sysctab[up->scallnr]; 
1992/0625    
 
1997/0327    
		ret = systab[up->scallnr](up->s.args); 
1991/0720    
		poperror(); 
	} 
1993/0915    
	if(up->nerrlab){ 
		print("bad errstack [%d]: %d extra\n", up->scallnr, up->nerrlab); 
1991/0720    
		for(i = 0; i < NERR; i++) 
1993/0915    
			print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc); 
1991/0720    
		panic("error stack"); 
	} 
1991/1114    
 
1993/0915    
	up->insyscall = 0; 
	up->psstate = 0; 
1992/0609    
 
	/* 
	 *  Put return value in frame.  On the safari 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. 
	 */ 
1997/0327    
	ureg->ax = ret; 
1992/0609    
 
1993/0915    
	if(up->scallnr == NOTED) 
1997/0327    
		noted(ureg, *(ulong*)(sp+BY2WD)); 
1995/0105    
	splhi(); 
1991/1114    
 
1993/0915    
	if(up->scallnr!=RFORK && (up->procctl || up->nnote)) 
1997/0327    
		notify(ureg); 
1995/0115    
 
1991/0710    
} 
 
1991/0720    
/* 
 *  Call user, if necessary, with note. 
 *  Pass user the Ureg struct and the note on his stack. 
 */ 
1992/0108    
int 
1997/0327    
notify(Ureg* ureg) 
1991/0710    
{ 
1995/0202    
	int l; 
1991/1114    
	ulong s, sp; 
1991/1218    
	Note *n; 
1991/0720    
 
1993/0915    
	if(up->procctl) 
1993/1013    
		procctl(up); 
1993/0915    
	if(up->nnote == 0) 
1992/0108    
		return 0; 
1991/1114    
 
	s = spllo(); 
1993/0915    
	qlock(&up->debug); 
	up->notepending = 0; 
	n = &up->note[0]; 
1991/1218    
	if(strncmp(n->msg, "sys:", 4) == 0){ 
		l = strlen(n->msg); 
		if(l > ERRLEN-15)	/* " pc=0x12345678\0" */ 
			l = ERRLEN-15; 
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)){ 
1992/0714    
		if(n->flag == NDebug) 
1991/1218    
			pprint("suicide: %s\n", n->msg); 
1996/0626    
		qunlock(&up->debug); 
1991/1218    
		pexit(n->msg, n->flag!=NDebug); 
1991/0720    
	} 
1995/0202    
 
	if(up->notified) { 
		qunlock(&up->debug); 
		splhi(); 
		return 0; 
1991/0720    
	} 
1995/0202    
		 
	if(!up->notify){ 
		qunlock(&up->debug); 
		pexit(n->msg, n->flag!=NDebug); 
	} 
1997/0327    
	sp = ureg->usp; 
1995/0202    
	sp -= sizeof(Ureg); 
 
	if(!okaddr((ulong)up->notify, 1, 0) 
1995/02021    
	|| !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)){ 
1995/0202    
		pprint("suicide: bad address in notify\n"); 
		qunlock(&up->debug); 
		pexit("Suicide", 0); 
	} 
 
	up->ureg = (void*)sp; 
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; 
	memmove((char*)sp, up->note[0].msg, ERRLEN); 
	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 */ 
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)); 
	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note)); 
 
1993/0915    
	qunlock(&up->debug); 
1991/1114    
	splx(s); 
1995/0202    
	return 1; 
1991/0710    
} 
 
1991/0720    
/* 
 *   Return user to state before notify() 
 */ 
1991/0710    
void 
1997/0327    
noted(Ureg* ureg, ulong arg0) 
1991/0710    
{ 
1997/0327    
	Ureg *nureg; 
1995/0202    
	ulong oureg, sp; 
1991/0720    
 
1993/0915    
	qlock(&up->debug); 
1995/0202    
	if(arg0!=NRSTR && !up->notified) { 
1993/0915    
		qunlock(&up->debug); 
1994/0513    
		pprint("call to noted() when not notified\n"); 
1995/0105    
		pexit("Suicide", 0); 
1991/0720    
	} 
1993/0915    
	up->notified = 0; 
1994/0513    
 
1997/0327    
	nureg = up->ureg;		/* pointer to user returned Ureg struct */ 
1995/0202    
 
	/* sanity clause */ 
1997/0327    
	oureg = (ulong)nureg; 
1995/02021    
	if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){ 
1997/0520    
		pprint("bad ureg in noted or call to noted when not notified\n"); 
1994/0513    
		qunlock(&up->debug); 
1995/0202    
		pexit("Suicide", 0); 
1994/0513    
	} 
 
1997/0520    
	/* 
	 * Check the segment selectors are all valid, otherwise 
	 * a fault will be taken on attempting to return to the 
	 * user process. 
1997/1003    
	 * Take care with the comparisons as different processor 
	 * generations push segment descriptors in different ways. 
1997/0520    
	 */ 
1997/1003    
	if((nureg->cs & 0xFFFF) != UESEL || (nureg->ss & 0xFFFF) != UDSEL 
	  || (nureg->ds & 0xFFFF) != UDSEL || (nureg->es & 0xFFFF) != UDSEL 
	  || (nureg->fs & 0xFFFF) != UDSEL || (nureg->gs & 0xFFFF) != UDSEL){ 
		pprint("bad segment selector in noted\n"); 
1997/0520    
		qunlock(&up->debug); 
		pexit("Suicide", 0); 
	} 
1995/0202    
 
	/* don't let user change system flags */ 
1997/0327    
	nureg->flags = (ureg->flags & ~0xCD5) | (nureg->flags & 0xCD5); 
1995/0202    
 
1997/0327    
	memmove(ureg, nureg, sizeof(Ureg)); 
1995/0105    
 
1991/0720    
	switch(arg0){ 
	case NCONT: 
1995/0202    
	case NRSTR: 
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); 
1991/0814    
		} 
1995/0202    
		up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD)); 
		qunlock(&up->debug); 
1995/0105    
		break; 
1991/0720    
 
1995/0202    
	case NSAVE: 
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); 
		} 
		qunlock(&up->debug); 
		sp = oureg-4*BY2WD-ERRLEN; 
		splhi(); 
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; 
 
1991/0720    
	default: 
		pprint("unknown noted arg 0x%lux\n", arg0); 
1993/0915    
		up->lastnote.flag = NDebug; 
1991/0720    
		/* fall through */ 
		 
	case NDFLT: 
1993/0915    
		if(up->lastnote.flag == NDebug) 
			pprint("suicide: %s\n", up->lastnote.msg); 
1995/0202    
		qunlock(&up->debug); 
1993/0915    
		pexit(up->lastnote.msg, up->lastnote.flag!=NDebug); 
1991/0720    
	} 
1991/1112    
} 
 
1993/1113    
long 
execregs(ulong entry, ulong ssize, ulong nargs) 
{ 
	ulong *sp; 
1997/0327    
	Ureg *ureg; 
1993/1113    
 
	sp = (ulong*)(USTKTOP - ssize); 
	*--sp = nargs; 
 
1997/0327    
	ureg = up->dbgreg; 
	ureg->usp = (ulong)sp; 
	ureg->pc = entry; 
1994/0513    
	return USTKTOP-BY2WD;		/* address of user-level clock */ 
1993/1113    
} 
 
ulong 
userpc(void) 
{ 
1997/0327    
	Ureg *ureg; 
1993/1113    
 
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 
1997/0327    
 * from devproc and then restore the saved values before returning 
1991/1112    
 */ 
void 
1997/0327    
setregisters(Ureg* ureg, char* pureg, char* uva, int n) 
1991/1112    
{ 
	ulong flags; 
	ulong cs; 
	ulong ss; 
 
1997/0327    
	flags = ureg->flags; 
	cs = ureg->cs; 
	ss = ureg->ss; 
1991/1112    
	memmove(pureg, uva, n); 
1997/0327    
	ureg->flags = (ureg->flags & 0x00FF) | (flags & 0xFF00); 
	ureg->cs = cs; 
	ureg->ss = ss; 
1993/1113    
} 
 
static void 
linkproc(void) 
{ 
	spllo(); 
1997/0327    
	up->kpfun(up->kparg); 
1993/1113    
} 
 
void 
1997/0327    
kprocchild(Proc* p, void (*func)(void*), void* arg) 
1993/1113    
{ 
	p->sched.pc = (ulong)linkproc; 
	p->sched.sp = (ulong)p->kstack+KSTACK; 
 
	p->kpfun = func; 
	p->kparg = arg; 
} 
 
void 
1997/0327    
forkchild(Proc *p, Ureg *ureg) 
1993/1113    
{ 
1997/0327    
	Ureg *cureg; 
1993/1113    
 
	/* 
1997/0327    
	 * Add 2*BY2WD to the stack to account for 
1993/1113    
	 *  - the return PC 
	 *  - trap's argument (ur) 
	 */ 
	p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Ureg)+2*BY2WD); 
	p->sched.pc = (ulong)forkret; 
 
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    
 
1997/0327    
	/* Things from bottom of syscall which were never executed */ 
1993/1113    
	p->psstate = 0; 
	p->insyscall = 0; 
1991/0614    
} 
1993/1022    
 
/* Give enough context in the ureg to produce a kernel stack for 
 * a sleeping process 
 */ 
void 
1997/0327    
setkernur(Ureg* ureg, Proc* p) 
1993/1022    
{ 
1997/0327    
	ureg->pc = p->sched.pc; 
	ureg->sp = p->sched.sp+4; 
1993/1022    
} 
1995/1024    
 
ulong 
dbgpc(Proc *p) 
{ 
1997/0327    
	Ureg *ureg; 
1995/1024    
 
1997/0327    
	ureg = p->dbgreg; 
	if(ureg == 0) 
1995/1024    
		return 0; 
 
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)