xref: /plan9/sys/src/9/port/devproc.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include	"u.h"
23e12c5d1SDavid du Colombier #include	"../port/lib.h"
33e12c5d1SDavid du Colombier #include	"mem.h"
43e12c5d1SDavid du Colombier #include	"dat.h"
53e12c5d1SDavid du Colombier #include	"fns.h"
63e12c5d1SDavid du Colombier #include	"../port/error.h"
73e12c5d1SDavid du Colombier #include	"ureg.h"
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier #include	"devtab.h"
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier enum{
123e12c5d1SDavid du Colombier 	Qdir,
133e12c5d1SDavid du Colombier 	Qctl,
143e12c5d1SDavid du Colombier 	Qmem,
153e12c5d1SDavid du Colombier 	Qnote,
16*219b2ee8SDavid du Colombier 	Qnoteid,
173e12c5d1SDavid du Colombier 	Qnotepg,
183e12c5d1SDavid du Colombier 	Qproc,
193e12c5d1SDavid du Colombier 	Qsegment,
203e12c5d1SDavid du Colombier 	Qstatus,
213e12c5d1SDavid du Colombier 	Qtext,
22*219b2ee8SDavid du Colombier 	Qwait,
233e12c5d1SDavid du Colombier };
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier #define	STATSIZE	(2*NAMELEN+12+7*12)
263e12c5d1SDavid du Colombier Dirtab procdir[] =
273e12c5d1SDavid du Colombier {
283e12c5d1SDavid du Colombier 	"ctl",		{Qctl},		0,			0000,
293e12c5d1SDavid du Colombier 	"mem",		{Qmem},		0,			0000,
303e12c5d1SDavid du Colombier 	"note",		{Qnote},	0,			0000,
31*219b2ee8SDavid du Colombier 	"noteid",	{Qnoteid},	0,			0666,
323e12c5d1SDavid du Colombier 	"notepg",	{Qnotepg},	0,			0000,
33*219b2ee8SDavid du Colombier 	"proc",		{Qproc},	sizeof(Proc),		0444,
343e12c5d1SDavid du Colombier 	"segment",	{Qsegment},	0,			0444,
353e12c5d1SDavid du Colombier 	"status",	{Qstatus},	STATSIZE,		0444,
363e12c5d1SDavid du Colombier 	"text",		{Qtext},	0,			0000,
37*219b2ee8SDavid du Colombier 	"wait",		{Qwait},	0,			0400,
383e12c5d1SDavid du Colombier };
393e12c5d1SDavid du Colombier 
403e12c5d1SDavid du Colombier /* Segment type from portdat.h */
413e12c5d1SDavid du Colombier char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata" };
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier /*
443e12c5d1SDavid du Colombier  * Qids are, in path:
453e12c5d1SDavid du Colombier  *	 4 bits of file type (qids above)
463e12c5d1SDavid du Colombier  *	23 bits of process slot number + 1
473e12c5d1SDavid du Colombier  *	     in vers,
483e12c5d1SDavid du Colombier  *	32 bits of pid, for consistency checking
493e12c5d1SDavid du Colombier  * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
503e12c5d1SDavid du Colombier  */
513e12c5d1SDavid du Colombier #define	NPROC	(sizeof procdir/sizeof(Dirtab))
523e12c5d1SDavid du Colombier #define	QSHIFT	4	/* location in qid of proc slot # */
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier #define	QID(q)		(((q).path&0x0000000F)>>0)
553e12c5d1SDavid du Colombier #define	SLOT(q)		((((q).path&0x07FFFFFF0)>>QSHIFT)-1)
563e12c5d1SDavid du Colombier #define	PID(q)		((q).vers)
573e12c5d1SDavid du Colombier #define	NOTEID(q)	((q).vers)
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier void	procctlreq(Proc*, char*, int);
603e12c5d1SDavid du Colombier int	procctlmemio(Proc*, ulong, int, void*, int);
613e12c5d1SDavid du Colombier Chan*	proctext(Chan*, Proc*);
623e12c5d1SDavid du Colombier Segment* txt2data(Proc*, Segment*);
633e12c5d1SDavid du Colombier int	procstopped(void*);
643e12c5d1SDavid du Colombier 
653e12c5d1SDavid du Colombier int
663e12c5d1SDavid du Colombier procgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)
673e12c5d1SDavid du Colombier {
683e12c5d1SDavid du Colombier 	Qid qid;
693e12c5d1SDavid du Colombier 	Proc *p;
703e12c5d1SDavid du Colombier 	char buf[NAMELEN];
71*219b2ee8SDavid du Colombier 	ulong pid, path, perm, len;
723e12c5d1SDavid du Colombier 
733e12c5d1SDavid du Colombier 	USED(ntab);
743e12c5d1SDavid du Colombier 	if(c->qid.path == CHDIR){
753e12c5d1SDavid du Colombier 		if(s >= conf.nproc)
763e12c5d1SDavid du Colombier 			return -1;
773e12c5d1SDavid du Colombier 		p = proctab(s);
783e12c5d1SDavid du Colombier 		pid = p->pid;
793e12c5d1SDavid du Colombier 		if(pid == 0)
803e12c5d1SDavid du Colombier 			return 0;
813e12c5d1SDavid du Colombier 		sprint(buf, "%d", pid);
823e12c5d1SDavid du Colombier 		qid = (Qid){CHDIR|((s+1)<<QSHIFT), pid};
833e12c5d1SDavid du Colombier 		devdir(c, qid, buf, 0, p->user, CHDIR|0555, dp);
843e12c5d1SDavid du Colombier 		return 1;
853e12c5d1SDavid du Colombier 	}
863e12c5d1SDavid du Colombier 	if(s >= NPROC)
873e12c5d1SDavid du Colombier 		return -1;
883e12c5d1SDavid du Colombier 	if(tab)
893e12c5d1SDavid du Colombier 		panic("procgen");
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier 	tab = &procdir[s];
923e12c5d1SDavid du Colombier 	path = c->qid.path&~(CHDIR|((1<<QSHIFT)-1));	/* slot component */
933e12c5d1SDavid du Colombier 
943e12c5d1SDavid du Colombier 	p = proctab(SLOT(c->qid));
953e12c5d1SDavid du Colombier 	perm = tab->perm;
963e12c5d1SDavid du Colombier 	if(perm == 0)
973e12c5d1SDavid du Colombier 		perm = p->procmode;
983e12c5d1SDavid du Colombier 
99*219b2ee8SDavid du Colombier 	len = tab->length;
100*219b2ee8SDavid du Colombier 	if(QID(c->qid) == Qwait)
101*219b2ee8SDavid du Colombier 		len = p->nwait * sizeof(Waitmsg);
102*219b2ee8SDavid du Colombier 
1033e12c5d1SDavid du Colombier 	qid = (Qid){path|tab->qid.path, c->qid.vers};
104*219b2ee8SDavid du Colombier 	devdir(c, qid, tab->name, len, p->user, perm, dp);
1053e12c5d1SDavid du Colombier 	return 1;
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier 
1083e12c5d1SDavid du Colombier void
1093e12c5d1SDavid du Colombier procinit(void)
1103e12c5d1SDavid du Colombier {
1113e12c5d1SDavid du Colombier 	if(conf.nproc >= (1<<(16-QSHIFT))-1)
1123e12c5d1SDavid du Colombier 		print("warning: too many procs for devproc\n");
1133e12c5d1SDavid du Colombier }
1143e12c5d1SDavid du Colombier 
1153e12c5d1SDavid du Colombier void
1163e12c5d1SDavid du Colombier procreset(void)
1173e12c5d1SDavid du Colombier {
1183e12c5d1SDavid du Colombier }
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier Chan*
1213e12c5d1SDavid du Colombier procattach(char *spec)
1223e12c5d1SDavid du Colombier {
1233e12c5d1SDavid du Colombier 	return devattach('p', spec);
1243e12c5d1SDavid du Colombier }
1253e12c5d1SDavid du Colombier 
1263e12c5d1SDavid du Colombier Chan*
1273e12c5d1SDavid du Colombier procclone(Chan *c, Chan *nc)
1283e12c5d1SDavid du Colombier {
1293e12c5d1SDavid du Colombier 	return devclone(c, nc);
1303e12c5d1SDavid du Colombier }
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier int
1333e12c5d1SDavid du Colombier procwalk(Chan *c, char *name)
1343e12c5d1SDavid du Colombier {
1353e12c5d1SDavid du Colombier 	if(strcmp(name, "..") == 0) {
1363e12c5d1SDavid du Colombier 		c->qid.path = Qdir|CHDIR;
1373e12c5d1SDavid du Colombier 		return 1;
1383e12c5d1SDavid du Colombier 	}
1393e12c5d1SDavid du Colombier 
1403e12c5d1SDavid du Colombier 	return devwalk(c, name, 0, 0, procgen);
1413e12c5d1SDavid du Colombier }
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier void
1443e12c5d1SDavid du Colombier procstat(Chan *c, char *db)
1453e12c5d1SDavid du Colombier {
1463e12c5d1SDavid du Colombier 	devstat(c, db, 0, 0, procgen);
1473e12c5d1SDavid du Colombier }
1483e12c5d1SDavid du Colombier 
1493e12c5d1SDavid du Colombier Chan *
1503e12c5d1SDavid du Colombier procopen(Chan *c, int omode)
1513e12c5d1SDavid du Colombier {
1523e12c5d1SDavid du Colombier 	Proc *p;
1533e12c5d1SDavid du Colombier 	Pgrp *pg;
1543e12c5d1SDavid du Colombier 	Chan *tc;
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier 	if(c->qid.path & CHDIR)
1573e12c5d1SDavid du Colombier 		return devopen(c, omode, 0, 0, procgen);
1583e12c5d1SDavid du Colombier 
1593e12c5d1SDavid du Colombier 	p = proctab(SLOT(c->qid));
1603e12c5d1SDavid du Colombier 	pg = p->pgrp;
1613e12c5d1SDavid du Colombier 	if(p->pid != PID(c->qid))
1623e12c5d1SDavid du Colombier 		error(Eprocdied);
1633e12c5d1SDavid du Colombier 
1643e12c5d1SDavid du Colombier 	omode = openmode(omode);
1653e12c5d1SDavid du Colombier 
1663e12c5d1SDavid du Colombier 	switch(QID(c->qid)){
1673e12c5d1SDavid du Colombier 	case Qtext:
1683e12c5d1SDavid du Colombier 		tc = proctext(c, p);
1693e12c5d1SDavid du Colombier 		tc->offset = 0;
1703e12c5d1SDavid du Colombier 		return tc;
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier 	case Qctl:
1733e12c5d1SDavid du Colombier 	case Qnote:
174*219b2ee8SDavid du Colombier 	case Qnoteid:
1753e12c5d1SDavid du Colombier 	case Qmem:
1763e12c5d1SDavid du Colombier 	case Qsegment:
1773e12c5d1SDavid du Colombier 	case Qproc:
1783e12c5d1SDavid du Colombier 	case Qstatus:
179*219b2ee8SDavid du Colombier 	case Qwait:
1803e12c5d1SDavid du Colombier 		break;
1813e12c5d1SDavid du Colombier 
1823e12c5d1SDavid du Colombier 	case Qnotepg:
1833e12c5d1SDavid du Colombier 		if(omode!=OWRITE || pg->pgrpid == 1)
1843e12c5d1SDavid du Colombier 			error(Eperm);
1853e12c5d1SDavid du Colombier 		c->pgrpid.path = pg->pgrpid+1;
1863e12c5d1SDavid du Colombier 		c->pgrpid.vers = p->noteid;
1873e12c5d1SDavid du Colombier 		break;
1883e12c5d1SDavid du Colombier 
1893e12c5d1SDavid du Colombier 	default:
1903e12c5d1SDavid du Colombier 		pprint("procopen %lux\n", c->qid);
1913e12c5d1SDavid du Colombier 		error(Egreg);
1923e12c5d1SDavid du Colombier 	}
1933e12c5d1SDavid du Colombier 
1943e12c5d1SDavid du Colombier 	/* Affix pid to qid */
1953e12c5d1SDavid du Colombier 	if(p->state != Dead)
1963e12c5d1SDavid du Colombier 		c->qid.vers = p->pid;
1973e12c5d1SDavid du Colombier 
1983e12c5d1SDavid du Colombier 	return devopen(c, omode, 0, 0, procgen);
1993e12c5d1SDavid du Colombier }
2003e12c5d1SDavid du Colombier 
2013e12c5d1SDavid du Colombier void
2023e12c5d1SDavid du Colombier proccreate(Chan *c, char *name, int omode, ulong perm)
2033e12c5d1SDavid du Colombier {
2043e12c5d1SDavid du Colombier 	USED(c, name, omode, perm);
2053e12c5d1SDavid du Colombier 	error(Eperm);
2063e12c5d1SDavid du Colombier }
2073e12c5d1SDavid du Colombier 
2083e12c5d1SDavid du Colombier void
2093e12c5d1SDavid du Colombier procremove(Chan *c)
2103e12c5d1SDavid du Colombier {
2113e12c5d1SDavid du Colombier 	USED(c);
2123e12c5d1SDavid du Colombier 	error(Eperm);
2133e12c5d1SDavid du Colombier }
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier void
2163e12c5d1SDavid du Colombier procwstat(Chan *c, char *db)
2173e12c5d1SDavid du Colombier {
2183e12c5d1SDavid du Colombier 	Proc *p;
2193e12c5d1SDavid du Colombier 	Dir d;
2203e12c5d1SDavid du Colombier 
2213e12c5d1SDavid du Colombier 	if(c->qid.path&CHDIR)
2223e12c5d1SDavid du Colombier 		error(Eperm);
2233e12c5d1SDavid du Colombier 
2243e12c5d1SDavid du Colombier 	convM2D(db, &d);
2253e12c5d1SDavid du Colombier 	p = proctab(SLOT(c->qid));
2263e12c5d1SDavid du Colombier 	if(p->pid != PID(c->qid))
2273e12c5d1SDavid du Colombier 		error(Eprocdied);
2283e12c5d1SDavid du Colombier 
2293e12c5d1SDavid du Colombier 	if(strcmp(u->p->user, p->user) != 0 && strcmp(u->p->user, eve) != 0)
2303e12c5d1SDavid du Colombier 		error(Eperm);
2313e12c5d1SDavid du Colombier 
2323e12c5d1SDavid du Colombier 	p->procmode = d.mode&0777;
2333e12c5d1SDavid du Colombier }
2343e12c5d1SDavid du Colombier 
2353e12c5d1SDavid du Colombier void
2363e12c5d1SDavid du Colombier procclose(Chan * c)
2373e12c5d1SDavid du Colombier {
2383e12c5d1SDavid du Colombier 	USED(c);
2393e12c5d1SDavid du Colombier }
2403e12c5d1SDavid du Colombier 
2413e12c5d1SDavid du Colombier long
2423e12c5d1SDavid du Colombier procread(Chan *c, void *va, long n, ulong offset)
2433e12c5d1SDavid du Colombier {
2443e12c5d1SDavid du Colombier 	Proc *p;
2453e12c5d1SDavid du Colombier 	Page *pg;
2463e12c5d1SDavid du Colombier 	KMap *k;
2473e12c5d1SDavid du Colombier 	Segment *s;
2483e12c5d1SDavid du Colombier 	int i, j;
2493e12c5d1SDavid du Colombier 	long l;
2503e12c5d1SDavid du Colombier 	User *up;
2513e12c5d1SDavid du Colombier 	Segment *sg;
252*219b2ee8SDavid du Colombier 	Waitq *wq;
253*219b2ee8SDavid du Colombier 	char statbuf[NSEG*32];
254*219b2ee8SDavid du Colombier 	char *a = va, *b, *sps;
2553e12c5d1SDavid du Colombier 
2563e12c5d1SDavid du Colombier 	if(c->qid.path & CHDIR)
2573e12c5d1SDavid du Colombier 		return devdirread(c, a, n, 0, 0, procgen);
2583e12c5d1SDavid du Colombier 
2593e12c5d1SDavid du Colombier 	p = proctab(SLOT(c->qid));
2603e12c5d1SDavid du Colombier 	if(p->pid != PID(c->qid))
2613e12c5d1SDavid du Colombier 		error(Eprocdied);
2623e12c5d1SDavid du Colombier 
2633e12c5d1SDavid du Colombier 	switch(QID(c->qid)){
2643e12c5d1SDavid du Colombier 	case Qmem:
2653e12c5d1SDavid du Colombier 		/* ugly math: USERADDR+BY2PG may be == 0 */
2663e12c5d1SDavid du Colombier 		if(offset >= USERADDR && offset <= USERADDR+BY2PG-1) {
2673e12c5d1SDavid du Colombier 			if(offset+n >= USERADDR+BY2PG-1)
2683e12c5d1SDavid du Colombier 				n = USERADDR+BY2PG - offset;
2693e12c5d1SDavid du Colombier 			pg = p->upage;
2703e12c5d1SDavid du Colombier 			if(pg==0 || p->pid!=PID(c->qid))
2713e12c5d1SDavid du Colombier 				error(Eprocdied);
2723e12c5d1SDavid du Colombier 			k = kmap(pg);
2733e12c5d1SDavid du Colombier 			b = (char*)VA(k);
2743e12c5d1SDavid du Colombier 			memmove(a, b+(offset-USERADDR), n);
2753e12c5d1SDavid du Colombier 			kunmap(k);
2763e12c5d1SDavid du Colombier 			return n;
2773e12c5d1SDavid du Colombier 		}
2783e12c5d1SDavid du Colombier 
2793e12c5d1SDavid du Colombier 		if(offset >= KZERO) {
2803e12c5d1SDavid du Colombier 			/* Protect crypt key memory */
281*219b2ee8SDavid du Colombier 			if(offset < palloc.cmemtop && offset+n > palloc.cmembase)
2823e12c5d1SDavid du Colombier 				error(Eperm);
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier 			/* validate physical kernel addresses */
2853e12c5d1SDavid du Colombier 			if(offset < (ulong)end) {
2863e12c5d1SDavid du Colombier 				if(offset+n > (ulong)end)
2873e12c5d1SDavid du Colombier 					n = (ulong)end - offset;
2883e12c5d1SDavid du Colombier 				memmove(a, (char*)offset, n);
2893e12c5d1SDavid du Colombier 				return n;
2903e12c5d1SDavid du Colombier 			}
2913e12c5d1SDavid du Colombier 			if(offset >= conf.base0 && offset < conf.npage0){
2923e12c5d1SDavid du Colombier 				if(offset+n > conf.npage0)
2933e12c5d1SDavid du Colombier 					n = conf.npage0 - offset;
2943e12c5d1SDavid du Colombier 				memmove(a, (char*)offset, n);
2953e12c5d1SDavid du Colombier 				return n;
2963e12c5d1SDavid du Colombier 			}
2973e12c5d1SDavid du Colombier 			if(offset >= conf.base1 && offset < conf.npage1){
2983e12c5d1SDavid du Colombier 				if(offset+n > conf.npage1)
2993e12c5d1SDavid du Colombier 					n = conf.npage1 - offset;
3003e12c5d1SDavid du Colombier 				memmove(a, (char*)offset, n);
3013e12c5d1SDavid du Colombier 				return n;
3023e12c5d1SDavid du Colombier 			}
3033e12c5d1SDavid du Colombier 		}
3043e12c5d1SDavid du Colombier 
3053e12c5d1SDavid du Colombier 		return procctlmemio(p, offset, n, va, 1);
3063e12c5d1SDavid du Colombier 
3073e12c5d1SDavid du Colombier 	case Qnote:
3083e12c5d1SDavid du Colombier 		qlock(&p->debug);
3093e12c5d1SDavid du Colombier 		if(waserror()){
3103e12c5d1SDavid du Colombier 			qunlock(&p->debug);
3113e12c5d1SDavid du Colombier 			nexterror();
3123e12c5d1SDavid du Colombier 		}
3133e12c5d1SDavid du Colombier 		if(p->pid != PID(c->qid))
3143e12c5d1SDavid du Colombier 			error(Eprocdied);
3153e12c5d1SDavid du Colombier 		k = kmap(p->upage);
3163e12c5d1SDavid du Colombier 		up = (User*)VA(k);
3173e12c5d1SDavid du Colombier 		if(up->p != p){
3183e12c5d1SDavid du Colombier 			kunmap(k);
3193e12c5d1SDavid du Colombier 			pprint("note read u/p mismatch");
3203e12c5d1SDavid du Colombier 			error(Egreg);
3213e12c5d1SDavid du Colombier 		}
3223e12c5d1SDavid du Colombier 		if(n < ERRLEN)
3233e12c5d1SDavid du Colombier 			error(Etoosmall);
3243e12c5d1SDavid du Colombier 		if(up->nnote == 0)
3253e12c5d1SDavid du Colombier 			n = 0;
3263e12c5d1SDavid du Colombier 		else{
3273e12c5d1SDavid du Colombier 			memmove(va, up->note[0].msg, ERRLEN);
3283e12c5d1SDavid du Colombier 			up->nnote--;
3293e12c5d1SDavid du Colombier 			memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
3303e12c5d1SDavid du Colombier 			n = ERRLEN;
3313e12c5d1SDavid du Colombier 		}
3323e12c5d1SDavid du Colombier 		if(up->nnote == 0)
3333e12c5d1SDavid du Colombier 			p->notepending = 0;
3343e12c5d1SDavid du Colombier 		kunmap(k);
3353e12c5d1SDavid du Colombier 		poperror();
3363e12c5d1SDavid du Colombier 		qunlock(&p->debug);
3373e12c5d1SDavid du Colombier 		return n;
3383e12c5d1SDavid du Colombier 
3393e12c5d1SDavid du Colombier 	case Qproc:
3403e12c5d1SDavid du Colombier 		if(offset >= sizeof(Proc))
3413e12c5d1SDavid du Colombier 			return 0;
3423e12c5d1SDavid du Colombier 		if(offset+n > sizeof(Proc))
3433e12c5d1SDavid du Colombier 			n = sizeof(Proc) - offset;
3443e12c5d1SDavid du Colombier 		memmove(a, ((char*)p)+offset, n);
3453e12c5d1SDavid du Colombier 		return n;
3463e12c5d1SDavid du Colombier 
3473e12c5d1SDavid du Colombier 	case Qstatus:
3483e12c5d1SDavid du Colombier 		if(offset >= STATSIZE)
3493e12c5d1SDavid du Colombier 			return 0;
3503e12c5d1SDavid du Colombier 		if(offset+n > STATSIZE)
3513e12c5d1SDavid du Colombier 			n = STATSIZE - offset;
3523e12c5d1SDavid du Colombier 
3533e12c5d1SDavid du Colombier 		sps = p->psstate;
3543e12c5d1SDavid du Colombier 		if(sps == 0)
3553e12c5d1SDavid du Colombier 			sps = statename[p->state];
356bd389b36SDavid du Colombier 		memset(statbuf, ' ', sizeof statbuf);
357bd389b36SDavid du Colombier 		memmove(statbuf+0*NAMELEN, p->text, strlen(p->text));
358bd389b36SDavid du Colombier 		memmove(statbuf+1*NAMELEN, p->user, strlen(p->user));
359bd389b36SDavid du Colombier 		memmove(statbuf+2*NAMELEN, sps, strlen(sps));
360bd389b36SDavid du Colombier 		j = 2*NAMELEN + 12;
3613e12c5d1SDavid du Colombier 
3623e12c5d1SDavid du Colombier 		for(i = 0; i < 6; i++) {
3633e12c5d1SDavid du Colombier 			l = p->time[i];
3643e12c5d1SDavid du Colombier 			if(i == TReal)
3653e12c5d1SDavid du Colombier 				l = MACHP(0)->ticks - l;
3663e12c5d1SDavid du Colombier 			l = TK2MS(l);
3673e12c5d1SDavid du Colombier 			readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
3683e12c5d1SDavid du Colombier 		}
3693e12c5d1SDavid du Colombier 		/* ignore stack, which is mostly non-existent */
3703e12c5d1SDavid du Colombier 		l = 0;
3713e12c5d1SDavid du Colombier 		for(i=1; i<NSEG; i++){
3723e12c5d1SDavid du Colombier 			s = p->seg[i];
3733e12c5d1SDavid du Colombier 			if(s)
3743e12c5d1SDavid du Colombier 				l += s->top - s->base;
3753e12c5d1SDavid du Colombier 		}
3763e12c5d1SDavid du Colombier 		readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE);
3773e12c5d1SDavid du Colombier 		memmove(a, statbuf+offset, n);
3783e12c5d1SDavid du Colombier 		return n;
3793e12c5d1SDavid du Colombier 
3803e12c5d1SDavid du Colombier 	case Qsegment:
3813e12c5d1SDavid du Colombier 		j = 0;
3823e12c5d1SDavid du Colombier 		for(i = 0; i < NSEG; i++)
3833e12c5d1SDavid du Colombier 			if(sg = p->seg[i])
3843e12c5d1SDavid du Colombier 				j += sprint(&statbuf[j], "%-6s %c %.8lux %.8lux %4d\n",
3853e12c5d1SDavid du Colombier 				sname[sg->type&SG_TYPE], sg->type&SG_RONLY ? 'R' : ' ',
3863e12c5d1SDavid du Colombier 				sg->base, sg->top, sg->ref);
3873e12c5d1SDavid du Colombier 		if(offset >= j)
3883e12c5d1SDavid du Colombier 			return 0;
3893e12c5d1SDavid du Colombier 		if(offset+n > j)
3903e12c5d1SDavid du Colombier 			n = j-offset;
3913e12c5d1SDavid du Colombier 		if(n == 0 && offset == 0)
3923e12c5d1SDavid du Colombier 			exhausted("segments");
3933e12c5d1SDavid du Colombier 		memmove(a, &statbuf[offset], n);
3943e12c5d1SDavid du Colombier 		return n;
395*219b2ee8SDavid du Colombier 
396*219b2ee8SDavid du Colombier 	case Qwait:
397*219b2ee8SDavid du Colombier 		if(n < sizeof(Waitmsg))
398*219b2ee8SDavid du Colombier 			error(Etoosmall);
399*219b2ee8SDavid du Colombier 
400*219b2ee8SDavid du Colombier 		if(!canqlock(&p->qwaitr))
401*219b2ee8SDavid du Colombier 			error(Einuse);
402*219b2ee8SDavid du Colombier 
403*219b2ee8SDavid du Colombier 		if(waserror()) {
404*219b2ee8SDavid du Colombier 			qunlock(&p->qwaitr);
405*219b2ee8SDavid du Colombier 			nexterror();
406*219b2ee8SDavid du Colombier 		}
407*219b2ee8SDavid du Colombier 
408*219b2ee8SDavid du Colombier 		lock(&p->exl);
409*219b2ee8SDavid du Colombier 		if(u->p == p && p->nchild == 0 && p->waitq == 0) {
410*219b2ee8SDavid du Colombier 			unlock(&p->exl);
411*219b2ee8SDavid du Colombier 			error(Enochild);
412*219b2ee8SDavid du Colombier 		}
413*219b2ee8SDavid du Colombier 		while(p->waitq == 0) {
414*219b2ee8SDavid du Colombier 			unlock(&p->exl);
415*219b2ee8SDavid du Colombier 			sleep(&p->waitr, haswaitq, p);
416*219b2ee8SDavid du Colombier 			lock(&p->exl);
417*219b2ee8SDavid du Colombier 		}
418*219b2ee8SDavid du Colombier 		wq = p->waitq;
419*219b2ee8SDavid du Colombier 		p->waitq = wq->next;
420*219b2ee8SDavid du Colombier 		p->nwait--;
421*219b2ee8SDavid du Colombier 		unlock(&p->exl);
422*219b2ee8SDavid du Colombier 
423*219b2ee8SDavid du Colombier 		qunlock(&p->qwaitr);
424*219b2ee8SDavid du Colombier 		poperror();
425*219b2ee8SDavid du Colombier 		memmove(a, &wq->w, sizeof(Waitmsg));
426*219b2ee8SDavid du Colombier 		free(wq);
427*219b2ee8SDavid du Colombier 		return sizeof(Waitmsg);
428*219b2ee8SDavid du Colombier 	case Qnoteid:
429*219b2ee8SDavid du Colombier 		return readnum(offset, va, n, p->noteid, NUMSIZE);
4303e12c5d1SDavid du Colombier 	}
4313e12c5d1SDavid du Colombier 	error(Egreg);
4323e12c5d1SDavid du Colombier 	return 0;		/* not reached */
4333e12c5d1SDavid du Colombier }
4343e12c5d1SDavid du Colombier 
4353e12c5d1SDavid du Colombier 
4363e12c5d1SDavid du Colombier long
4373e12c5d1SDavid du Colombier procwrite(Chan *c, void *va, long n, ulong offset)
4383e12c5d1SDavid du Colombier {
439*219b2ee8SDavid du Colombier 	int id;
4403e12c5d1SDavid du Colombier 	User *up;
4413e12c5d1SDavid du Colombier 	KMap *k;
4423e12c5d1SDavid du Colombier 	Ureg *ur;
4433e12c5d1SDavid du Colombier 	User *pxu;
4443e12c5d1SDavid du Colombier 	Page *pg;
4453e12c5d1SDavid du Colombier 	ulong hi;
446*219b2ee8SDavid du Colombier 	char *a, *b;
447*219b2ee8SDavid du Colombier 	char buf[ERRLEN];
448*219b2ee8SDavid du Colombier 	Proc *p, *t, *et;
4493e12c5d1SDavid du Colombier 
4503e12c5d1SDavid du Colombier 	if(c->qid.path & CHDIR)
4513e12c5d1SDavid du Colombier 		error(Eisdir);
4523e12c5d1SDavid du Colombier 
453*219b2ee8SDavid du Colombier 	a = va;
4543e12c5d1SDavid du Colombier 	p = proctab(SLOT(c->qid));
4553e12c5d1SDavid du Colombier 
456*219b2ee8SDavid du Colombier 	/* Use the remembered noteid in the channel
457*219b2ee8SDavid du Colombier 	 * rather than the process pgrpid
458*219b2ee8SDavid du Colombier 	 */
4593e12c5d1SDavid du Colombier 	if(QID(c->qid) == Qnotepg) {
4603e12c5d1SDavid du Colombier 		pgrpnote(NOTEID(c->pgrpid), va, n, NUser);
4613e12c5d1SDavid du Colombier 		return n;
4623e12c5d1SDavid du Colombier 	}
4633e12c5d1SDavid du Colombier 
4643e12c5d1SDavid du Colombier 	qlock(&p->debug);
4653e12c5d1SDavid du Colombier 	if(waserror()){
4663e12c5d1SDavid du Colombier 		qunlock(&p->debug);
4673e12c5d1SDavid du Colombier 		nexterror();
4683e12c5d1SDavid du Colombier 	}
4693e12c5d1SDavid du Colombier 	if(p->pid != PID(c->qid))
4703e12c5d1SDavid du Colombier 		error(Eprocdied);
4713e12c5d1SDavid du Colombier 
4723e12c5d1SDavid du Colombier 	switch(QID(c->qid)){
4733e12c5d1SDavid du Colombier 	case Qmem:
4743e12c5d1SDavid du Colombier 		if(p->state != Stopped)
4753e12c5d1SDavid du Colombier 			error(Ebadctl);
4763e12c5d1SDavid du Colombier 
4773e12c5d1SDavid du Colombier 		if(offset >= USERADDR && offset <= USERADDR+BY2PG-1) {
4783e12c5d1SDavid du Colombier 			pg = p->upage;
4793e12c5d1SDavid du Colombier 			if(pg==0 || p->pid!=PID(c->qid))
4803e12c5d1SDavid du Colombier 				error(Eprocdied);
4813e12c5d1SDavid du Colombier 			k = kmap(pg);
4823e12c5d1SDavid du Colombier 			b = (char*)VA(k);
4833e12c5d1SDavid du Colombier 			pxu = (User*)b;
4843e12c5d1SDavid du Colombier 			hi = offset+n;
4853e12c5d1SDavid du Colombier 			/* Check for floating point registers */
4863e12c5d1SDavid du Colombier 			if(offset >= (ulong)&u->fpsave &&
4873e12c5d1SDavid du Colombier 			   hi <= (ulong)&u->fpsave+sizeof(FPsave)){
4883e12c5d1SDavid du Colombier 				memmove(b+(offset-USERADDR), a, n);
4893e12c5d1SDavid du Colombier 				break;
4903e12c5d1SDavid du Colombier 			}
4913e12c5d1SDavid du Colombier 			/* Check user register set for process at kernel entry */
4923e12c5d1SDavid du Colombier 			ur = pxu->dbgreg;
4933e12c5d1SDavid du Colombier 			if(offset < (ulong)ur || hi > (ulong)ur+sizeof(Ureg)) {
4943e12c5d1SDavid du Colombier 				kunmap(k);
4953e12c5d1SDavid du Colombier 				error(Ebadarg);
4963e12c5d1SDavid du Colombier 			}
4973e12c5d1SDavid du Colombier 			ur = (Ureg*)(b+((ulong)ur-USERADDR));
4983e12c5d1SDavid du Colombier 			setregisters(ur, b+(offset-USERADDR), a, n);
4993e12c5d1SDavid du Colombier 			kunmap(k);
5003e12c5d1SDavid du Colombier 		}
5013e12c5d1SDavid du Colombier 		else	/* Try user memory segments */
5023e12c5d1SDavid du Colombier 			n = procctlmemio(p, offset, n, va, 0);
5033e12c5d1SDavid du Colombier 		break;
5043e12c5d1SDavid du Colombier 
5053e12c5d1SDavid du Colombier 	case Qctl:
5063e12c5d1SDavid du Colombier 		procctlreq(p, va, n);
5073e12c5d1SDavid du Colombier 		break;
5083e12c5d1SDavid du Colombier 
5093e12c5d1SDavid du Colombier 	case Qnote:
5103e12c5d1SDavid du Colombier 		if(p->kp)
5113e12c5d1SDavid du Colombier 			error(Eperm);
5123e12c5d1SDavid du Colombier 		k = kmap(p->upage);
5133e12c5d1SDavid du Colombier 		up = (User*)VA(k);
5143e12c5d1SDavid du Colombier 		if(up->p != p){
5153e12c5d1SDavid du Colombier 			kunmap(k);
5163e12c5d1SDavid du Colombier 			pprint("note write u/p mismatch");
5173e12c5d1SDavid du Colombier 			error(Egreg);
5183e12c5d1SDavid du Colombier 		}
5193e12c5d1SDavid du Colombier 		kunmap(k);
5203e12c5d1SDavid du Colombier 		if(n >= ERRLEN-1)
5213e12c5d1SDavid du Colombier 			error(Etoobig);
5223e12c5d1SDavid du Colombier 		memmove(buf, va, n);
5233e12c5d1SDavid du Colombier 		buf[n] = 0;
5243e12c5d1SDavid du Colombier 		if(!postnote(p, 0, buf, NUser))
5253e12c5d1SDavid du Colombier 			error("note not posted");
5263e12c5d1SDavid du Colombier 		break;
527*219b2ee8SDavid du Colombier 	case Qnoteid:
528*219b2ee8SDavid du Colombier 		id = atoi(a);
529*219b2ee8SDavid du Colombier 		if(id == p->pid) {
530*219b2ee8SDavid du Colombier 			p->noteid = id;
531*219b2ee8SDavid du Colombier 			break;
532*219b2ee8SDavid du Colombier 		}
533*219b2ee8SDavid du Colombier 		t = proctab(0);
534*219b2ee8SDavid du Colombier 		for(et = t+conf.nproc; t < et; t++) {
535*219b2ee8SDavid du Colombier 			if(id == t->noteid) {
536*219b2ee8SDavid du Colombier 				if(strcmp(p->user, t->user) != 0)
537*219b2ee8SDavid du Colombier 					error(Eperm);
538*219b2ee8SDavid du Colombier 				p->noteid = id;
539*219b2ee8SDavid du Colombier 				break;
540*219b2ee8SDavid du Colombier 			}
541*219b2ee8SDavid du Colombier 		}
542*219b2ee8SDavid du Colombier 		if(p->noteid != id)
543*219b2ee8SDavid du Colombier 			error(Ebadarg);
544*219b2ee8SDavid du Colombier 		break;
5453e12c5d1SDavid du Colombier 	default:
5463e12c5d1SDavid du Colombier 		pprint("unknown qid in procwrite\n");
5473e12c5d1SDavid du Colombier 		error(Egreg);
5483e12c5d1SDavid du Colombier 	}
5493e12c5d1SDavid du Colombier 	poperror();
5503e12c5d1SDavid du Colombier 	qunlock(&p->debug);
5513e12c5d1SDavid du Colombier 	return n;
5523e12c5d1SDavid du Colombier }
5533e12c5d1SDavid du Colombier 
5543e12c5d1SDavid du Colombier Chan *
5553e12c5d1SDavid du Colombier proctext(Chan *c, Proc *p)
5563e12c5d1SDavid du Colombier {
5573e12c5d1SDavid du Colombier 	Chan *tc;
5583e12c5d1SDavid du Colombier 	Image *i;
5593e12c5d1SDavid du Colombier 	Segment *s;
5603e12c5d1SDavid du Colombier 
5613e12c5d1SDavid du Colombier 	s = p->seg[TSEG];
5623e12c5d1SDavid du Colombier 	if(s == 0)
5633e12c5d1SDavid du Colombier 		error(Enonexist);
5643e12c5d1SDavid du Colombier 	if(p->state==Dead)
5653e12c5d1SDavid du Colombier 		error(Eprocdied);
5663e12c5d1SDavid du Colombier 
5673e12c5d1SDavid du Colombier 	lock(s);
5683e12c5d1SDavid du Colombier 	i = s->image;
5693e12c5d1SDavid du Colombier 	if(i == 0) {
5703e12c5d1SDavid du Colombier 		unlock(s);
5713e12c5d1SDavid du Colombier 		error(Eprocdied);
5723e12c5d1SDavid du Colombier 	}
5733e12c5d1SDavid du Colombier 	unlock(s);
5743e12c5d1SDavid du Colombier 
5753e12c5d1SDavid du Colombier 	lock(i);
5763e12c5d1SDavid du Colombier 	if(waserror()) {
5773e12c5d1SDavid du Colombier 		unlock(i);
5783e12c5d1SDavid du Colombier 		nexterror();
5793e12c5d1SDavid du Colombier 	}
5803e12c5d1SDavid du Colombier 
5813e12c5d1SDavid du Colombier 	tc = i->c;
5823e12c5d1SDavid du Colombier 	if(tc == 0)
5833e12c5d1SDavid du Colombier 		error(Eprocdied);
5843e12c5d1SDavid du Colombier 
5853e12c5d1SDavid du Colombier 	if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) {
5863e12c5d1SDavid du Colombier 		close(tc);
5873e12c5d1SDavid du Colombier 		error(Eprocdied);
5883e12c5d1SDavid du Colombier 	}
5893e12c5d1SDavid du Colombier 
5903e12c5d1SDavid du Colombier 	if(p->pid != PID(c->qid))
5913e12c5d1SDavid du Colombier 		error(Eprocdied);
5923e12c5d1SDavid du Colombier 
5933e12c5d1SDavid du Colombier 	unlock(i);
5943e12c5d1SDavid du Colombier 	poperror();
5953e12c5d1SDavid du Colombier 
5963e12c5d1SDavid du Colombier 	return tc;
5973e12c5d1SDavid du Colombier }
5983e12c5d1SDavid du Colombier 
5993e12c5d1SDavid du Colombier void
6003e12c5d1SDavid du Colombier procstopwait(Proc *p, int ctl)
6013e12c5d1SDavid du Colombier {
6023e12c5d1SDavid du Colombier 	int pid;
6033e12c5d1SDavid du Colombier 
6043e12c5d1SDavid du Colombier 	if(p->pdbg)
6053e12c5d1SDavid du Colombier 		error(Einuse);
6063e12c5d1SDavid du Colombier 	if(procstopped(p))
6073e12c5d1SDavid du Colombier 		return;
6083e12c5d1SDavid du Colombier 
6093e12c5d1SDavid du Colombier 	if(ctl != 0)
6103e12c5d1SDavid du Colombier 		p->procctl = ctl;
6113e12c5d1SDavid du Colombier 	p->pdbg = u->p;
6123e12c5d1SDavid du Colombier 	pid = p->pid;
6133e12c5d1SDavid du Colombier 	qunlock(&p->debug);
6143e12c5d1SDavid du Colombier 	u->p->psstate = "Stopwait";
6153e12c5d1SDavid du Colombier 	if(waserror()) {
6163e12c5d1SDavid du Colombier 		p->pdbg = 0;
6173e12c5d1SDavid du Colombier 		qlock(&p->debug);
6183e12c5d1SDavid du Colombier 		nexterror();
6193e12c5d1SDavid du Colombier 	}
6203e12c5d1SDavid du Colombier 	sleep(&u->p->sleep, procstopped, p);
6213e12c5d1SDavid du Colombier 	poperror();
6223e12c5d1SDavid du Colombier 	qlock(&p->debug);
6233e12c5d1SDavid du Colombier 	if(p->pid != pid)
6243e12c5d1SDavid du Colombier 		error(Eprocdied);
6253e12c5d1SDavid du Colombier }
6263e12c5d1SDavid du Colombier 
6273e12c5d1SDavid du Colombier void
6283e12c5d1SDavid du Colombier procctlreq(Proc *p, char *va, int n)
6293e12c5d1SDavid du Colombier {
630*219b2ee8SDavid du Colombier 	int i;
631*219b2ee8SDavid du Colombier 	char buf[NAMELEN+1];
6323e12c5d1SDavid du Colombier 
6333e12c5d1SDavid du Colombier 	if(n > NAMELEN)
6343e12c5d1SDavid du Colombier 		n = NAMELEN;
6353e12c5d1SDavid du Colombier 	strncpy(buf, va, n);
636*219b2ee8SDavid du Colombier 	buf[NAMELEN] = '\0';
6373e12c5d1SDavid du Colombier 
6383e12c5d1SDavid du Colombier 	if(strncmp(buf, "stop", 4) == 0)
6393e12c5d1SDavid du Colombier 		procstopwait(p, Proc_stopme);
6403e12c5d1SDavid du Colombier 	else if(strncmp(buf, "kill", 4) == 0) {
641bd389b36SDavid du Colombier 		switch(p->state) {
642bd389b36SDavid du Colombier 		case Broken:
643bd389b36SDavid du Colombier 			unbreak(p);
644bd389b36SDavid du Colombier 			break;
645bd389b36SDavid du Colombier 		case Stopped:
646bd389b36SDavid du Colombier 			postnote(p, 0, "sys: killed", NExit);
647bd389b36SDavid du Colombier 			p->procctl = Proc_exitme;
6483e12c5d1SDavid du Colombier 			ready(p);
649bd389b36SDavid du Colombier 			break;
650bd389b36SDavid du Colombier 		default:
6513e12c5d1SDavid du Colombier 			postnote(p, 0, "sys: killed", NExit);
6523e12c5d1SDavid du Colombier 			p->procctl = Proc_exitme;
6533e12c5d1SDavid du Colombier 		}
6543e12c5d1SDavid du Colombier 	}
6553e12c5d1SDavid du Colombier 	else if(strncmp(buf, "hang", 4) == 0)
6563e12c5d1SDavid du Colombier 		p->hang = 1;
657*219b2ee8SDavid du Colombier 	else if(strncmp(buf, "nohang", 6) == 0)
658*219b2ee8SDavid du Colombier 		p->hang = 0;
6593e12c5d1SDavid du Colombier 	else if(strncmp(buf, "waitstop", 8) == 0)
6603e12c5d1SDavid du Colombier 		procstopwait(p, 0);
6613e12c5d1SDavid du Colombier 	else if(strncmp(buf, "startstop", 9) == 0) {
6623e12c5d1SDavid du Colombier 		if(p->state != Stopped)
6633e12c5d1SDavid du Colombier 			error(Ebadctl);
6643e12c5d1SDavid du Colombier 		p->procctl = Proc_traceme;
6653e12c5d1SDavid du Colombier 		ready(p);
6663e12c5d1SDavid du Colombier 		procstopwait(p, Proc_traceme);
6673e12c5d1SDavid du Colombier 	}
6683e12c5d1SDavid du Colombier 	else if(strncmp(buf, "start", 5) == 0) {
6693e12c5d1SDavid du Colombier 		if(p->state != Stopped)
6703e12c5d1SDavid du Colombier 			error(Ebadctl);
6713e12c5d1SDavid du Colombier 		ready(p);
6723e12c5d1SDavid du Colombier 	}
673*219b2ee8SDavid du Colombier 	else if(strncmp(buf, "pri", 3) == 0){
674*219b2ee8SDavid du Colombier 		if(n < 4)
675*219b2ee8SDavid du Colombier 			error(Ebadctl);
676*219b2ee8SDavid du Colombier 		i = atoi(buf+4);
677*219b2ee8SDavid du Colombier 		if(i < 0)
678*219b2ee8SDavid du Colombier 			i = 0;
679*219b2ee8SDavid du Colombier 		if(i >= Nrq)
680*219b2ee8SDavid du Colombier 			i = Nrq - 1;
681*219b2ee8SDavid du Colombier 		if(i < p->basepri && !iseve())
682*219b2ee8SDavid du Colombier 			error(Eperm);
683*219b2ee8SDavid du Colombier 		p->basepri = i;
684*219b2ee8SDavid du Colombier 	}
6853e12c5d1SDavid du Colombier 	else
6863e12c5d1SDavid du Colombier 		error(Ebadctl);
6873e12c5d1SDavid du Colombier }
6883e12c5d1SDavid du Colombier 
6893e12c5d1SDavid du Colombier int
6903e12c5d1SDavid du Colombier procstopped(void *a)
6913e12c5d1SDavid du Colombier {
6923e12c5d1SDavid du Colombier 	Proc *p = a;
6933e12c5d1SDavid du Colombier 	return p->state == Stopped;
6943e12c5d1SDavid du Colombier }
6953e12c5d1SDavid du Colombier 
6963e12c5d1SDavid du Colombier int
6973e12c5d1SDavid du Colombier procctlmemio(Proc *p, ulong offset, int n, void *va, int read)
6983e12c5d1SDavid du Colombier {
6993e12c5d1SDavid du Colombier 	KMap *k;
7003e12c5d1SDavid du Colombier 	Pte *pte;
7013e12c5d1SDavid du Colombier 	Page *pg;
7023e12c5d1SDavid du Colombier 	Segment *s;
7033e12c5d1SDavid du Colombier 	ulong soff, l;
7043e12c5d1SDavid du Colombier 	char *a = va, *b;
7053e12c5d1SDavid du Colombier 
7063e12c5d1SDavid du Colombier 	for(;;) {
7073e12c5d1SDavid du Colombier 		s = seg(p, offset, 1);
7083e12c5d1SDavid du Colombier 		if(s == 0)
7093e12c5d1SDavid du Colombier 			error(Ebadarg);
7103e12c5d1SDavid du Colombier 
7113e12c5d1SDavid du Colombier 		if(offset+n >= s->top)
7123e12c5d1SDavid du Colombier 			n = s->top-offset;
7133e12c5d1SDavid du Colombier 
714*219b2ee8SDavid du Colombier 		if(read == 0 && (s->type&SG_TYPE) == SG_TEXT)
7153e12c5d1SDavid du Colombier 			s = txt2data(p, s);
7163e12c5d1SDavid du Colombier 
7173e12c5d1SDavid du Colombier 		s->steal++;
7183e12c5d1SDavid du Colombier 		soff = offset-s->base;
7193e12c5d1SDavid du Colombier 		if(waserror()) {
7203e12c5d1SDavid du Colombier 			s->steal--;
7213e12c5d1SDavid du Colombier 			nexterror();
7223e12c5d1SDavid du Colombier 		}
7233e12c5d1SDavid du Colombier 		if(fixfault(s, offset, read, 0) == 0)
7243e12c5d1SDavid du Colombier 			break;
7253e12c5d1SDavid du Colombier 		poperror();
7263e12c5d1SDavid du Colombier 		s->steal--;
7273e12c5d1SDavid du Colombier 	}
7283e12c5d1SDavid du Colombier 	poperror();
7293e12c5d1SDavid du Colombier 	pte = s->map[soff/PTEMAPMEM];
7303e12c5d1SDavid du Colombier 	if(pte == 0)
7313e12c5d1SDavid du Colombier 		panic("procctlmemio");
7323e12c5d1SDavid du Colombier 	pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG];
7333e12c5d1SDavid du Colombier 	if(pagedout(pg))
7343e12c5d1SDavid du Colombier 		panic("procctlmemio1");
7353e12c5d1SDavid du Colombier 
7363e12c5d1SDavid du Colombier 	l = BY2PG - (offset&(BY2PG-1));
7373e12c5d1SDavid du Colombier 	if(n > l)
7383e12c5d1SDavid du Colombier 		n = l;
7393e12c5d1SDavid du Colombier 
7403e12c5d1SDavid du Colombier 	k = kmap(pg);
7413e12c5d1SDavid du Colombier 	b = (char*)VA(k);
7423e12c5d1SDavid du Colombier 	if(read == 1)
7433e12c5d1SDavid du Colombier 		memmove(a, b+(offset&(BY2PG-1)), n);
7443e12c5d1SDavid du Colombier 	else
7453e12c5d1SDavid du Colombier 		memmove(b+(offset&(BY2PG-1)), a, n);
7463e12c5d1SDavid du Colombier 
7473e12c5d1SDavid du Colombier 	kunmap(k);
7483e12c5d1SDavid du Colombier 
7493e12c5d1SDavid du Colombier 	s->steal--;
7503e12c5d1SDavid du Colombier 	qunlock(&s->lk);
7513e12c5d1SDavid du Colombier 
7523e12c5d1SDavid du Colombier 	if(read == 0)
7533e12c5d1SDavid du Colombier 		p->newtlb = 1;
7543e12c5d1SDavid du Colombier 
7553e12c5d1SDavid du Colombier 	return n;
7563e12c5d1SDavid du Colombier }
7573e12c5d1SDavid du Colombier 
7583e12c5d1SDavid du Colombier Segment*
7593e12c5d1SDavid du Colombier txt2data(Proc *p, Segment *s)
7603e12c5d1SDavid du Colombier {
7613e12c5d1SDavid du Colombier 	int i;
7623e12c5d1SDavid du Colombier 	Segment *ps;
7633e12c5d1SDavid du Colombier 
7643e12c5d1SDavid du Colombier 	ps = newseg(SG_DATA, s->base, s->size);
7653e12c5d1SDavid du Colombier 	ps->image = s->image;
7663e12c5d1SDavid du Colombier 	incref(ps->image);
7673e12c5d1SDavid du Colombier 	ps->fstart = s->fstart;
7683e12c5d1SDavid du Colombier 	ps->flen = s->flen;
7693e12c5d1SDavid du Colombier 	ps->flushme = 1;
7703e12c5d1SDavid du Colombier 
7713e12c5d1SDavid du Colombier 	for(i = 0; i < NSEG; i++)
7723e12c5d1SDavid du Colombier 		if(p->seg[i] == s)
7733e12c5d1SDavid du Colombier 			break;
7743e12c5d1SDavid du Colombier 	if(p->seg[i] != s)
7753e12c5d1SDavid du Colombier 		panic("segment gone");
7763e12c5d1SDavid du Colombier 
7773e12c5d1SDavid du Colombier 	qunlock(&s->lk);
7783e12c5d1SDavid du Colombier 	putseg(s);
7793e12c5d1SDavid du Colombier 	qlock(&ps->lk);
7803e12c5d1SDavid du Colombier 	p->seg[i] = ps;
7813e12c5d1SDavid du Colombier 
7823e12c5d1SDavid du Colombier 	return ps;
7833e12c5d1SDavid du Colombier }
784bd389b36SDavid du Colombier 
785bd389b36SDavid du Colombier Segment*
786bd389b36SDavid du Colombier data2txt(Segment *s)
787bd389b36SDavid du Colombier {
788bd389b36SDavid du Colombier 	Segment *ps;
789bd389b36SDavid du Colombier 
790bd389b36SDavid du Colombier 	ps = newseg(SG_TEXT, s->base, s->size);
791bd389b36SDavid du Colombier 	ps->image = s->image;
792bd389b36SDavid du Colombier 	incref(ps->image);
793bd389b36SDavid du Colombier 	ps->fstart = s->fstart;
794bd389b36SDavid du Colombier 	ps->flen = s->flen;
795bd389b36SDavid du Colombier 	ps->flushme = 1;
796bd389b36SDavid du Colombier 
797bd389b36SDavid du Colombier 	return ps;
798bd389b36SDavid du Colombier }
799