~kris/9p

9hist

64e77d4402970c246d0847745b7fe8dfd4d8dc70 — David du Colombier 35 years ago 2e8fd57
Plan 9 from Bell Labs 1991-08-14
7 files changed, 196 insertions(+), 123 deletions(-)

M gnot/dat.h
M gnot/trap.c
M pc/devhard.c
M pc/trap.c
M port/devmnt.c
M power/trap.c
M ss/trap.c
M gnot/dat.h => gnot/dat.h +1 -1
@@ 200,7 200,7 @@ struct Scsi
	uchar	cmdblk[16];
};

#define	NERR	15
#define	NERR	25
#define	NNOTE	5
struct User
{

M gnot/trap.c => gnot/trap.c +11 -3
@@ 199,21 199,29 @@ noted(Ureg *ur, ulong arg0)
	Ureg *nur;

	nur = u->ureg;
	validaddr(nur->pc, 1, 0);
	validaddr(nur->usp, BY2WD, 0);
	if(nur->sr!=u->svsr || nur->vo!=u->svvo){
		pprint("bad noted ureg sr %ux vo %ux\n", nur->sr, nur->vo);
    Die:
		pexit("Suicide", 0);
	}
	lock(&u->p->debug);
	if(!u->notified){
		unlock(&u->p->debug);
		return;
		pprint("call to noted() when not notified\n");
		goto Die;
	}
	u->notified = 0;
	memmove(ur, u->ureg, sizeof(Ureg));
	switch(arg0){
	case NCONT:
		if(waserror()){
			pprint("suicide: trap in noted\n");
			unlock(&u->p->debug);
			goto Die;
		}
		validaddr(nur->pc, 1, 0);
		validaddr(nur->usp, BY2WD, 0);
		poperror();
		splhi();
		unlock(&u->p->debug);
		rfnote(ur);

M pc/devhard.c => pc/devhard.c +89 -78
@@ 10,7 10,6 @@ typedef	struct Drive		Drive;
typedef	struct Ident		Ident;
typedef	struct Controller	Controller;
typedef struct Partition	Partition;
typedef struct Ptable		Ptable;

enum
{


@@ 45,7 44,7 @@ enum
	Qmask=		(3<<(3+3)),

	Maxxfer=	4*1024,		/* maximum transfer size/cmd */
	Npart=		8+1,		/* 8 sub partitions and one for the disk */
	Npart=		8+2,		/* 8 sub partitions, disk, and partiiton */
};
#define PART(x)		((x)&0x3)
#define DRIVE(x)	(((x)>>3)&0x7)


@@ 93,19 92,7 @@ struct Partition
{
	ulong	start;
	ulong	end;
	uchar	name[NAMELEN];
};

struct Ptable 
{
	uchar		magic[4];	/* ascii "disk" */
	uchar		n[4];		/* number of partitions */
	struct
	{
		uchar	start[4];	/* starting block */
		uchar	end[4];		/* ending block */
		uchar	name[NAMELEN];
	} p[1];
	char	name[NAMELEN+1];
};

/*


@@ 159,11 146,9 @@ struct Controller

Controller	*hardc;
Drive		*hard;
Dirtab 		*harddir;
#define NHDIR	2	/* directory entries/drive */

static void	hardintr(Ureg*);
static long	hardxfer(Drive*, int, void*, long, long);
static long	hardxfer(Drive*, Partition*, int, void*, long, long);
static long	hardident(Drive*);
static void	hardsetbuf(Drive*, int);
static void	hardpart(Drive*);


@@ 173,33 158,30 @@ hardgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
{
	Qid qid;
	int drive;
	char *name;
	char name[NAMELEN];
	Drive *dp;
	Partition *pp;
	ulong l;

	qid.vers = 0;
	drive = s/(Npart+1);
	s = s % (Npart+1);
	drive = s/Npart;
	s = s % Npart;
	if(drive >= conf.nhard)
		return -1;
	dp = &hard[drive];

	if(s == 0){
		sprint(name, "hd%dparition", drive);
		qid.path = MKQID(Qpart, drive, 0);
		l = dp->npart * sizeof(Partition);
	} else if(s-1 < p.npart){
		pp = &dp->p[s-1];
	if(s < dp->npart){
		pp = &dp->p[s];
		sprint(name, "hd%d%s", drive, pp->name);
		qid.path = MKQID(Qdata, drive, s-1);
		l = (pp->end - pp->start) * dp->cp->bytes;
		qid.path = MKQID(Qdata, drive, s);
		l = (pp->end - pp->start) * dp->bytes;
	} else
		return 0;

	devdir(c, qid, name, l, 0600, dirp);
	return 1;
}

/*
 *  we assume drives 0 and 1 are on the first controller, 2 and 3 on the
 *  second, etc.


@@ 210,11 192,9 @@ hardreset(void)
	Drive *dp;
	Controller *cp;
	int drive;
	Dirtab *dir;

	hard = ialloc(conf.nhard * sizeof(Drive), 0);
	hardc = ialloc(((conf.nhard+1)/2 + 1) * sizeof(Controller), 0);
	dir = harddir = ialloc(NHDIR * conf.nhard * sizeof(Dirtab), 0);
	
	for(drive = 0; drive < conf.nhard; drive++){
		dp = &hard[drive];


@@ 228,16 208,6 @@ hardreset(void)
			cp->pbase = Pbase + (cp-hardc)*8;	/* BUG!! guessing */
			setvec(Hardvec + (cp-hardc)*8, hardintr); /* BUG!! guessing */
		}
		sprint(harddir[drive*2].name, "hd%ddata", drive);
		dir->length = 0;
		dir->qid.path = Qdata + drive;
		dir->perm = 0600;
		dir++;
		sprint(dir->name, "hd%dstruct", drive);
		dir->length = 8;
		dir->qid.path = Qstruct + drive;
		dir->perm = 0600;
		dir++;
	}
}



@@ 260,14 230,13 @@ hardattach(char *spec)
			dp->bytes = 512;
			hardsetbuf(dp, 1);
			hardident(dp);
			hardpart(dp);
			dp->cyl = dp->id.lcyls;
			dp->heads = dp->id.lheads;
			dp->sectors = dp->id.ls2t;
			dp->bytes = 512;
			dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
			harddir[NHDIR*dp->drive].length = dp->cap;
			dp->online = 1;
			hardpart(dp);
			poperror();
		} else
			dp->online = 0;


@@ 285,19 254,19 @@ hardclone(Chan *c, Chan *nc)
int
hardwalk(Chan *c, char *name)
{
	return devwalk(c, name, harddir, conf.nhard*NHDIR, devgen);
	return devwalk(c, name, 0, 0, hardgen);
}

void
hardstat(Chan *c, char *dp)
{
	devstat(c, dp, harddir, conf.nhard*NHDIR, devgen);
	devstat(c, dp, 0, 0, hardgen);
}

Chan*
hardopen(Chan *c, int omode)
{
	return devopen(c, omode, harddir, conf.nhard*NHDIR, devgen);
	return devopen(c, omode, 0, 0, hardgen);
}

void


@@ 323,43 292,29 @@ hardwstat(Chan *c, char *dp)
	error(Eperm);
}

static void
ul2user(uchar *a, ulong x)
{
	a[0] = x >> 24;
	a[1] = x >> 16;
	a[2] = x >> 8;
	a[3] = x;
}

long
hardread(Chan *c, void *a, long n)
{
	Drive *dp;
	long rv, i;
	uchar *aa = a;
	Partition *pp;

	if(c->qid.path == CHDIR)
		return devdirread(c, a, n, harddir, conf.nhard*NHDIR, devgen);
		return devdirread(c, a, n, 0, 0, hardgen);

	rv = 0;
	dp = &hard[c->qid.path & ~Qmask];
	switch ((int)(c->qid.path & Qmask)) {
	case Qdata:
		for(rv = 0; rv < n; rv += i){
			i = hardxfer(dp, Cread, aa+rv, c->offset+rv, n-rv);
			pp = &dp->p[PART(c->qid.path)];
			i = hardxfer(dp, pp, Cread, aa+rv, c->offset+rv, n-rv);
			if(i <= 0)
				break;
		}
		break;
	case Qstruct:
		if (n < 2*sizeof(ulong))
			error(Ebadarg);
		if (c->offset >= 2*sizeof(ulong))
			return 0;
		rv = 2*sizeof(ulong);
		ul2user((uchar*)a, dp->cap);
		ul2user((uchar*)a+sizeof(ulong), dp->bytes);
	case Qpart:
		break;
	default:
		panic("hardread: bad qid");


@@ 373,19 328,20 @@ hardwrite(Chan *c, void *a, long n)
	Drive *dp;
	long rv, i;
	uchar *aa = a;
	Partition *pp;

	rv = 0;
	dp = &hard[c->qid.path & ~Qmask];
	switch ((int)(c->qid.path & Qmask)) {
	case Qdata:
		for(rv = 0; rv < n; rv += i){
			i = hardxfer(dp, Cwrite, aa+rv, c->offset+rv, n-rv);
			pp = &dp->p[PART(c->qid.path)];
			i = hardxfer(dp, pp, Cwrite, aa+rv, c->offset+rv, n-rv);
			if(i <= 0)
				break;
		}
		break;
	case Qstruct:
		error(Eperm);
	case Qpart:
		break;
	default:
		panic("hardwrite: bad qid");


@@ 425,7 381,7 @@ print("cmdreadywait failed\n");
 *  parts.
 */
static long
hardxfer(Drive *dp, int cmd, void *va, long off, long len)
hardxfer(Drive *dp, Partition *pp, int cmd, void *va, long off, long len)
{
	Controller *cp;
	int err;


@@ 439,6 395,9 @@ hardxfer(Drive *dp, int cmd, void *va, long off, long len)
	if(off % dp->bytes)
		errors("bad offset");	/* BUG - this shouldn't be a problem */

print("hardxfer %ld %ld\n", off, len);
print("hardxfer part %s %ld %ld\n", pp->name, pp->start, pp->end);

	cp = dp->cp;
	qlock(cp);
	if(waserror()){


@@ 450,6 409,9 @@ hardxfer(Drive *dp, int cmd, void *va, long off, long len)
	 *  calculate the physical address of off
	 */
	lsec = off/dp->bytes;
	lsec += pp->start;
	if(lsec >= pp->end)
		errors("xfer past end of partition\n");
	cp->tcyl = lsec/(dp->sectors*dp->heads);
	cp->tsec = (lsec % dp->sectors) + 1;
	cp->thead = (lsec/dp->sectors) % dp->heads;


@@ 458,6 420,9 @@ hardxfer(Drive *dp, int cmd, void *va, long off, long len)
	 *  can't xfer across cylinder boundaries.
	 */
	lsec = (off+len)/dp->bytes;
	lsec += pp->start;
	if(lsec > pp->end)
		errors("xfer past end of partition\n");
	cyl = lsec/(dp->sectors*dp->heads);
	if(cyl == cp->tcyl)
		cp->len = len;


@@ 515,6 480,7 @@ hardsetbuf(Drive *dp, int on)

	cmdreadywait(cp);

	cp->cmd = Csetbuf;
	outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
	outb(cp->pbase+Pdh, (dp->drive<<4));
	outb(cp->pbase+Pcmd, Csetbuf);


@@ 536,6 502,7 @@ hardident(Drive *dp)
	cp = dp->cp;
	qlock(cp);
	if(waserror()){
print("waserror in hardident\n");
		qunlock(cp);
		nexterror();
	}


@@ 566,24 533,64 @@ print("bad disk magic\n");
}

/*
 *  read partition table
 *  read partition table.  The partition table is just ascii strings.
 */
#define MAGIC "plan9 partitions"
static void
hardpart(Drive *dp)
{
	Partition *pp;
	Ptable *pt;
	uchar buf[1024];
	char *line[Npart+1];
	char *field[3];
	char buf[1024];
	ulong n;
	int i;

	pp = &dp->p[0];
	strcpy(pp->name, "disk");
	pp->start = 0;
	pp->end = pp->cap / dp->bytes;
	pp->end = dp->cap / dp->bytes;
	pp++;
	strcpy(pp->name, "partition");
	pp->start = dp->p[0].end - 1;
	pp->end = dp->p[0].end;
	dp->npart = 2;

	qlock(dp->cp);
	hardxfer(dp, Cread, buf, pp->end - 1, dp->bytes);
	
	qunlock(dp->cp);
	if(waserror()){
		print("error in hardpart\n");
		nexterror();
	}

	hardxfer(dp, pp, Cread, buf, (pp->end - 1)*dp->bytes, dp->bytes);
	buf[dp->bytes] = 0;

	n = getfields(buf, line, Npart+1, '\n');
	if(strncmp(line[0], MAGIC, sizeof(MAGIC)-1) != 0){
		print("bad partition table 1\n");
		goto out;
	}
	for(i = 1; i < n; i++){
		pp++;
		if(getfields(line[i], field, 3, 0) != 3){
			print("bad partition field\n");
			goto out;
		}
		if(strlen(field[0]) > NAMELEN){
			print("bad partition name\n");
			goto out;
		}
		strcpy(pp->name, field[0]);
		pp->start = strtoul(field[1], 0, 0);
		pp->end = strtoul(field[2], 0, 0);
		if(pp->start > pp->end || pp->start >= dp->p[0].end){
			print("bad partition limit\n");
			goto out;
		}
print("partition %s from %d to %d\n", pp->name, pp->start, pp->end);
		dp->npart++;
	}
out:
	poperror();
}

/*


@@ 642,8 649,12 @@ hardintr(Ureg *ur)
			wakeup(&cp->r);
		}
		break;
	case Csetbuf:
		cp->cmd = 0;
		wakeup(&cp->r);
		break;
	default:
		print("wierd disk interrupt\n");
		print("weird disk interrupt\n");
		break;
	}
}

M pc/trap.c => pc/trap.c +10 -0
@@ 373,10 373,12 @@ noted(Ureg *ur, ulong arg0)
	|| (nur->flags&0xff00)!=(u->svflags&0xff00)){
		pprint("bad noted ureg cs %ux ss %ux flags %ux\n", nur->cs, nur->ss,
			nur->flags);
    Die:
		pexit("Suicide", 0);
	}
	lock(&u->p->debug);
	if(!u->notified){
		pprint("call to noted() when not notified\n");
		unlock(&u->p->debug);
		return;
	}


@@ 385,6 387,14 @@ noted(Ureg *ur, ulong arg0)
	memmove(ur, u->ureg, sizeof(Ureg));
	switch(arg0){
	case NCONT:
		if(waserror()){
			pprint("suicide: trap in noted\n");
			unlock(&u->p->debug);
			goto Die;
		}
		validaddr(nur->pc, 1, 0);
		validaddr(nur->usp, BY2WD, 0);
		poperror();
		unlock(&u->p->debug);
		return;


M port/devmnt.c => port/devmnt.c +63 -35
@@ 9,7 9,7 @@

#include	"fcall.h"

#define		NTAG	16384	/* 1 <= tag <= NTAG */
#define		NTAG	65536	/*  1 <= tag < NTAG */

typedef struct Mnt	Mnt;
typedef struct Mnthdr	Mnthdr;


@@ 52,8 52,9 @@ struct Mnthdr
{
	Mnthdr	*next;		/* in free list or writers list */
	Mnthdr	*prev;		/* in writers list only */
	short	active;
	short	flushing;	/* a Tflush has been sent */
	char	active;
	char	flushing;	/* a Tflush has been sent */
	short	seq;
	Fcall	thdr;
	Fcall	rhdr;
	Rendez	r;


@@ 66,7 67,8 @@ struct
{
	Lock;
	Mnthdr	*arena;
	Mnthdr	*free;
	Mnthdr	*head;
	Mnthdr	*tail;
}mnthdralloc;

struct


@@ 85,7 87,6 @@ struct

Mnt	*mnt;
void	mntxmit(Mnt*, Mnthdr*);
Ref	mnttag;

Mntbuf*
mballoc(void)


@@ 119,17 120,27 @@ mbfree(Mntbuf *mb)
}

Mnthdr*
mhalloc(void)
mhalloc(Mnt *m)
{
	Mnthdr *mh;
	int seq;

loop:
	lock(&mnthdralloc);
	if(mh = mnthdralloc.free){		/* assign = */
		mnthdralloc.free = mh->next;
		mh->mbr = 0;
		mh->thdr.tag = 1 + (incref(&mnttag) & (NTAG-1));
	if(mh = mnthdralloc.head){		/* assign = */
		mnthdralloc.head = mh->next;
		if(mnthdralloc.head)
			mnthdralloc.head->prev = 0;
		else
			mnthdralloc.tail = 0;
		unlock(&mnthdralloc);
		mh->mbr = 0;
		seq = ++mh->seq;
		if(seq == (1<<7)){
			mh->seq = 1;
			seq = 1;
		}
		mh->thdr.tag = (((mh-mnthdralloc.arena)<<7)|seq) & (NTAG-1);
		return mh;
	}
	unlock(&mnthdralloc);


@@ 150,8 161,13 @@ mhfree(Mnthdr *mh)
	lock(&mnthdralloc);
	mh->active = 0;
	mh->thdr.tag = 0;
	mh->next = mnthdralloc.free;
	mnthdralloc.free = mh;
	mh->next = 0;
	mh->prev = mnthdralloc.tail;
	if(mnthdralloc.tail)
		mnthdralloc.tail->next = mh;
	else
		mnthdralloc.head = mh;
	mnthdralloc.tail = mh;
	unlock(&mnthdralloc);
}



@@ 217,27 233,39 @@ mntreset(void)
	Mnthdr *mh;
	MntQ *mq;

	if(conf.nmnthdr > 512){
		print("conf.nmnthdr is %d set to 512\n", conf.nmnthdr);
		conf.nmnthdr = 512;
	}
	mnt = ialloc(conf.nmntdev*sizeof(Mnt), 0);

	mb = ialloc(conf.nmntbuf*sizeof(Mntbuf), 0);
	for(i=0; i<conf.nmntbuf-1; i++)
		mb[i].next = &mb[i+1];
	mb[i].next = 0;
	mntbufalloc.free = mb;
	for(i=0; i<conf.nmntbuf; i++,mb++)
		mb->next = mb+1;
	--mb;
	mb->next = 0;

	mh = ialloc(conf.nmnthdr*sizeof(Mnthdr), 0);
	for(i=0; i<conf.nmnthdr-1; i++)
		mh[i].next = &mh[i+1];
	mh[i].next = 0;
	mnthdralloc.arena = mh;
	mnthdralloc.free = mh;
	mnthdralloc.head = mh;
	for(i=0; i<conf.nmnthdr; i++,mh++){
		mh->seq = 0;
		mh->next = mh+1;
		mh->prev = mh-1;
	}
	--mh;
	mnthdralloc.tail = mh;
	mh->next = 0;
	mnthdralloc.head->prev = 0;

	mq = ialloc(conf.nmntdev*sizeof(MntQ), 0);
	for(i=0; i<conf.nmntdev-1; i++)
		mq[i].next = &mq[i+1];
	mq[i].next = 0;
	mntqalloc.arena = mq;
	mntqalloc.free = mq;
	for(i=0; i<conf.nmntdev; i++,mq++)
		mq->next = mq+1;
	--mq;
	mq->next = 0;
}

void


@@ 302,7 330,7 @@ mntattach(char *crud)

    out:
	qunlock(&mntqalloc);
	mh = mhalloc();
	mh = mhalloc(m);
	if(waserror()){
		mhfree(mh);
		close(c);


@@ 339,7 367,7 @@ mntclone(Chan *c, Chan *nc)
		}
	}
	m = mntdev(c, 0);
	mh = mhalloc();
	mh = mhalloc(m);
	if(waserror()){
		mhfree(mh);
		nexterror();


@@ 377,7 405,7 @@ mntwalk(Chan *c, char *name)

	found = 1;
	m = mntdev(c, 0);
	mh = mhalloc();
	mh = mhalloc(m);
	mh->thdr.type = Twalk;
	mh->thdr.fid = c->fid;
	strcpy(mh->thdr.name, name);


@@ 400,7 428,7 @@ mntstat(Chan *c, char *dp)
	Mnthdr *mh;

	m = mntdev(c, 0);
	mh = mhalloc();
	mh = mhalloc(m);
	if(waserror()){
		mhfree(mh);
		nexterror();


@@ 424,7 452,7 @@ mntopen(Chan *c, int omode)
	Mnthdr *mh;

	m = mntdev(c, 0);
	mh = mhalloc();
	mh = mhalloc(m);
	if(waserror()){
		mhfree(mh);
		nexterror();


@@ 449,7 477,7 @@ mntcreate(Chan *c, char *name, int omode, ulong perm)
	Mnthdr *mh;

	m = mntdev(c, 0);
	mh = mhalloc();
	mh = mhalloc(m);
	if(waserror()){
		mhfree(mh);
		nexterror();


@@ 477,7 505,7 @@ mntclunk(Chan *c, int t)
	int waserr;

	m = mntdev(c, 0);
	mh = mhalloc();
	mh = mhalloc(m);
	mh->thdr.type = t;
	mh->thdr.fid = c->fid;
	waserr = 0;


@@ 519,7 547,7 @@ mntreadwrite(Chan *c, void *vbuf, long n, int type, ulong offset)
	buf = vbuf;
	count = 0;
	m = mntdev(c, 0);
	mh = mhalloc();
	mh = mhalloc(m);
	if(waserror()){
		mhfree(mh);
		nexterror();


@@ 585,7 613,7 @@ mntwstat(Chan *c, char *dp)
	Mnthdr *mh;

	m = mntdev(c, 0);
	mh = mhalloc();
	mh = mhalloc(m);
	if(waserror()){
		mhfree(mh);
		nexterror();


@@ 626,7 654,7 @@ mntflush(Mnt *m, Mnthdr *omh)	/* queue is unlocked */
		return;
	}

	mh = mhalloc();
	mh = mhalloc(m);
	if(waserror()){
		omh->flushing = 0;
		mhfree(mh);


@@ 814,7 842,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
		if(tag == mh->thdr.tag){	/* it's mine */
			if(mh->rhdr.type != Rerror)
			if(mh->rhdr.type != mh->thdr.type+1){
				print("mail rob: '%s T(%d)%c %d %d'\n", u->p->text,
				print("mail rob: '%s xxT(%d)%c %d %d'\n", u->p->text,
					tag, devchar[m->q->msg->type],
					mh->rhdr.type, mh->thdr.type+1);
				goto FreeRead;


@@ 835,7 863,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
		/*
		 * Hand response to correct recipient
		 */
		if(tag<=0 || tag>NTAG){
		if(tag==0 || tag>=NTAG){
			print("unknown tag %d\n", tag);
	FreeRead:
			mbfree(mh->mbr);


@@ 854,7 882,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
			goto FreeRead;
		if(mh->rhdr.type != Rerror)
		if(mh->rhdr.type != w->thdr.type+1){
			print("mail rob: '%s w(%d)%c %d %d'\n",
			print("mail rob: '%s xxw(%d)%c %d %d'\n",
				u->p->text, tag, devchar[m->q->msg->type],
				mh->rhdr.type, w->thdr.type+1);
			goto FreeRead;

M power/trap.c => power/trap.c +11 -3
@@ 426,21 426,29 @@ noted(Ureg **urp, ulong arg0)
	Ureg *nur;

	nur = u->ureg;
	validaddr(nur->pc, 1, 0);
	validaddr(nur->usp, BY2WD, 0);
	if(nur->status!=u->svstatus){
		pprint("bad noted ureg status %lux\n", nur->status);
    Die:
		pexit("Suicide", 0);
	}
	lock(&u->p->debug);
	if(!u->notified){
		unlock(&u->p->debug);
		return;
		pprint("call to noted() when not notified\n");
		goto Die;
	}
	u->notified = 0;
	memmove(*urp, u->ureg, sizeof(Ureg));
	switch(arg0){
	case NCONT:
		if(waserror()){
			pprint("suicide: trap in noted\n");
			unlock(&u->p->debug);
			goto Die;
		}
		validaddr(nur->pc, 1, 0);
		validaddr(nur->usp, BY2WD, 0);
		poperror();
		splhi();
		unlock(&u->p->debug);
		rfnote(urp);

M ss/trap.c => ss/trap.c +11 -3
@@ 272,21 272,29 @@ noted(Ureg **urp, ulong arg0)
	Ureg *nur;

	nur = u->ureg;
	validaddr(nur->pc, 1, 0);
	validaddr(nur->usp, BY2WD, 0);
	if(nur->psr!=u->svpsr){
		pprint("bad noted ureg psr %lux\n", nur->psr);
    Die:
		pexit("Suicide", 0);
	}
	lock(&u->p->debug);
	if(!u->notified){
		unlock(&u->p->debug);
		return;
		pprint("call to noted() when not notified\n");
		goto Die;
	}
	u->notified = 0;
	memmove(*urp, u->ureg, sizeof(Ureg));
	switch(arg0){
	case NCONT:
		if(waserror()){
			pprint("suicide: trap in noted\n");
			unlock(&u->p->debug);
			goto Die;
		}
		validaddr(nur->pc, 1, 0);
		validaddr(nur->usp, BY2WD, 0);
		poperror();
		splhi();
		unlock(&u->p->debug);
		rfnote(urp);