xref: /plan9-contrib/sys/src/9k/port/fault.c (revision 094d68186d4cdde21fdab9786d6c843a03693e4e)
19ef1f84bSDavid du Colombier #include	"u.h"
29ef1f84bSDavid du Colombier #include	"../port/lib.h"
39ef1f84bSDavid du Colombier #include	"mem.h"
49ef1f84bSDavid du Colombier #include	"dat.h"
59ef1f84bSDavid du Colombier #include	"fns.h"
69ef1f84bSDavid du Colombier #include	"../port/error.h"
79ef1f84bSDavid du Colombier 
89ef1f84bSDavid du Colombier int
fault(uintptr addr,int read)99ef1f84bSDavid du Colombier fault(uintptr addr, int read)
109ef1f84bSDavid du Colombier {
119ef1f84bSDavid du Colombier 	Segment *s;
129ef1f84bSDavid du Colombier 	char *sps;
13*094d6818SDavid du Colombier 	int i, color;
149ef1f84bSDavid du Colombier 
15406c76faSDavid du Colombier 	if(up == nil)
16406c76faSDavid du Colombier 		panic("fault: nil up");
179ef1f84bSDavid du Colombier 	if(up->nlocks)
18406c76faSDavid du Colombier 		print("fault: addr %#p: nlocks %d\n", addr, up->nlocks);
199ef1f84bSDavid du Colombier 
209ef1f84bSDavid du Colombier 	sps = up->psstate;
219ef1f84bSDavid du Colombier 	up->psstate = "Fault";
229ef1f84bSDavid du Colombier 	spllo();
239ef1f84bSDavid du Colombier 
249ef1f84bSDavid du Colombier 	m->pfault++;
25*094d6818SDavid du Colombier 	for(i = 0;; i++) {
269ef1f84bSDavid du Colombier 		s = seg(up, addr, 1);		/* leaves s->lk qlocked if seg != nil */
274498a243SDavid du Colombier 		if(s == nil) {
289ef1f84bSDavid du Colombier 			up->psstate = sps;
299ef1f84bSDavid du Colombier 			return -1;
309ef1f84bSDavid du Colombier 		}
319ef1f84bSDavid du Colombier 
329ef1f84bSDavid du Colombier 		if(!read && (s->type&SG_RONLY)) {
339ef1f84bSDavid du Colombier 			qunlock(&s->lk);
349ef1f84bSDavid du Colombier 			up->psstate = sps;
359ef1f84bSDavid du Colombier 			return -1;
369ef1f84bSDavid du Colombier 		}
379ef1f84bSDavid du Colombier 
38*094d6818SDavid du Colombier 		color = s->color;
39*094d6818SDavid du Colombier 		if(i > 3)
40*094d6818SDavid du Colombier 			color = -1;
41*094d6818SDavid du Colombier 		if(fixfault(s, addr, read, 1, color) == 0)	/* qunlocks s->lk */
429ef1f84bSDavid du Colombier 			break;
439ef1f84bSDavid du Colombier 
449ef1f84bSDavid du Colombier 		/*
459ef1f84bSDavid du Colombier 		 * See the comment in newpage that describes
469ef1f84bSDavid du Colombier 		 * how to get here.
479ef1f84bSDavid du Colombier 		 */
489ef1f84bSDavid du Colombier 	}
499ef1f84bSDavid du Colombier 
509ef1f84bSDavid du Colombier 	up->psstate = sps;
519ef1f84bSDavid du Colombier 	return 0;
529ef1f84bSDavid du Colombier }
539ef1f84bSDavid du Colombier 
549ef1f84bSDavid du Colombier static void
faulterror(char * s,Chan * c,int freemem)559ef1f84bSDavid du Colombier faulterror(char *s, Chan *c, int freemem)
569ef1f84bSDavid du Colombier {
579ef1f84bSDavid du Colombier 	char buf[ERRMAX];
589ef1f84bSDavid du Colombier 
599ef1f84bSDavid du Colombier 	if(c && c->path){
609ef1f84bSDavid du Colombier 		snprint(buf, sizeof buf, "%s accessing %s: %s", s, c->path->s, up->errstr);
619ef1f84bSDavid du Colombier 		s = buf;
629ef1f84bSDavid du Colombier 	}
639ef1f84bSDavid du Colombier 	if(up->nerrlab) {
649ef1f84bSDavid du Colombier 		postnote(up, 1, s, NDebug);
659ef1f84bSDavid du Colombier 		error(s);
669ef1f84bSDavid du Colombier 	}
679ef1f84bSDavid du Colombier 	pexit(s, freemem);
689ef1f84bSDavid du Colombier }
699ef1f84bSDavid du Colombier 
70406c76faSDavid du Colombier void	(*checkaddr)(ulong, Segment *, Page *);
71406c76faSDavid du Colombier ulong	addr2check;
72406c76faSDavid du Colombier 
739ef1f84bSDavid du Colombier int
fixfault(Segment * s,uintptr addr,int read,int dommuput,int color)74*094d6818SDavid du Colombier fixfault(Segment *s, uintptr addr, int read, int dommuput, int color)
759ef1f84bSDavid du Colombier {
769ef1f84bSDavid du Colombier 	int type;
779ef1f84bSDavid du Colombier 	int ref;
789ef1f84bSDavid du Colombier 	Pte **p, *etp;
799ef1f84bSDavid du Colombier 	Page **pg, *lkp, *new;
809ef1f84bSDavid du Colombier 	Page *(*fn)(Segment*, uintptr);
819ef1f84bSDavid du Colombier 	uintptr mmuphys, pgsize, soff;
829ef1f84bSDavid du Colombier 
8357fe3081SDavid du Colombier 	pgsize = segpgsize(s);
849ef1f84bSDavid du Colombier 	addr &= ~(pgsize-1);
859ef1f84bSDavid du Colombier 	soff = addr-s->base;
869ef1f84bSDavid du Colombier 	p = &s->map[soff/s->ptemapmem];
874498a243SDavid du Colombier 	if(*p == nil)
889ef1f84bSDavid du Colombier 		*p = ptealloc();
899ef1f84bSDavid du Colombier 
909ef1f84bSDavid du Colombier 	etp = *p;
919ef1f84bSDavid du Colombier 	pg = &etp->pages[(soff&(s->ptemapmem-1))>>s->lg2pgsize];
929ef1f84bSDavid du Colombier 	type = s->type&SG_TYPE;
939ef1f84bSDavid du Colombier 
949ef1f84bSDavid du Colombier 	if(pg < etp->first)
959ef1f84bSDavid du Colombier 		etp->first = pg;
969ef1f84bSDavid du Colombier 	if(pg > etp->last)
979ef1f84bSDavid du Colombier 		etp->last = pg;
989ef1f84bSDavid du Colombier 
999ef1f84bSDavid du Colombier 	mmuphys = 0;
1009ef1f84bSDavid du Colombier 	switch(type) {
1019ef1f84bSDavid du Colombier 	default:
1029ef1f84bSDavid du Colombier 		panic("fault");
1039ef1f84bSDavid du Colombier 		break;
1049ef1f84bSDavid du Colombier 
1059ef1f84bSDavid du Colombier 	case SG_TEXT: 			/* Demand load */
1069ef1f84bSDavid du Colombier 		if(pagedout(*pg))
107*094d6818SDavid du Colombier 			pio(s, addr, soff, pg, color);
1089ef1f84bSDavid du Colombier 
1099ef1f84bSDavid du Colombier 		mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID;
1109ef1f84bSDavid du Colombier 		(*pg)->modref = PG_REF;
1119ef1f84bSDavid du Colombier 		break;
1129ef1f84bSDavid du Colombier 
1139ef1f84bSDavid du Colombier 	case SG_BSS:
1149ef1f84bSDavid du Colombier 	case SG_SHARED:			/* Zero fill on demand */
1159ef1f84bSDavid du Colombier 	case SG_STACK:
1164498a243SDavid du Colombier 		if(*pg == nil) {
117*094d6818SDavid du Colombier 			new = newpage(1, s, addr, s->lg2pgsize, color, 1);
1189ef1f84bSDavid du Colombier 			if(new == nil)
1199ef1f84bSDavid du Colombier 				return -1;
1209ef1f84bSDavid du Colombier 
1219ef1f84bSDavid du Colombier 			*pg = new;
1229ef1f84bSDavid du Colombier 		}
1239ef1f84bSDavid du Colombier 		goto common;
1249ef1f84bSDavid du Colombier 
1259ef1f84bSDavid du Colombier 	case SG_DATA:
1269ef1f84bSDavid du Colombier 	common:			/* Demand load/pagein/copy on write */
1279ef1f84bSDavid du Colombier 		if(pagedout(*pg))
128*094d6818SDavid du Colombier 			pio(s, addr, soff, pg, color);
1299ef1f84bSDavid du Colombier 
1309ef1f84bSDavid du Colombier 		/*
1319ef1f84bSDavid du Colombier 		 *  It's only possible to copy on write if
1329ef1f84bSDavid du Colombier 		 *  we're the only user of the segment.
1339ef1f84bSDavid du Colombier 		 */
1349ef1f84bSDavid du Colombier 		if(read && sys->copymode == 0 && s->ref == 1) {
1359ef1f84bSDavid du Colombier 			mmuphys = PPN((*pg)->pa)|PTERONLY|PTEVALID;
1369ef1f84bSDavid du Colombier 			(*pg)->modref |= PG_REF;
1379ef1f84bSDavid du Colombier 			break;
1389ef1f84bSDavid du Colombier 		}
1399ef1f84bSDavid du Colombier 
1409ef1f84bSDavid du Colombier 		lkp = *pg;
1419ef1f84bSDavid du Colombier 		lock(lkp);
1429ef1f84bSDavid du Colombier 
1439ef1f84bSDavid du Colombier 		ref = lkp->ref;
1449ef1f84bSDavid du Colombier 		if(ref <= 0)
1459ef1f84bSDavid du Colombier 			panic("fault: page->ref %d <= 0", ref);
1469ef1f84bSDavid du Colombier 
1479ef1f84bSDavid du Colombier 		if(ref == 1 && lkp->image != nil){
1489ef1f84bSDavid du Colombier 			duppage(lkp);
1499ef1f84bSDavid du Colombier 			ref = lkp->ref;
1509ef1f84bSDavid du Colombier 		}
1519ef1f84bSDavid du Colombier 		unlock(lkp);
1529ef1f84bSDavid du Colombier 
1539ef1f84bSDavid du Colombier 		if(ref > 1) {
154*094d6818SDavid du Colombier 			new = newpage(0, s, addr, s->lg2pgsize, color, 1);
1559ef1f84bSDavid du Colombier 			if(new == nil)
1569ef1f84bSDavid du Colombier 				return -1;
1579ef1f84bSDavid du Colombier 			*pg = new;
1589ef1f84bSDavid du Colombier 			copypage(lkp, *pg);
1599ef1f84bSDavid du Colombier 			putpage(lkp);
1609ef1f84bSDavid du Colombier 		}
1619ef1f84bSDavid du Colombier 		mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID;
1629ef1f84bSDavid du Colombier 		(*pg)->modref = PG_MOD|PG_REF;
1639ef1f84bSDavid du Colombier 		break;
1649ef1f84bSDavid du Colombier 
1659ef1f84bSDavid du Colombier 	case SG_PHYSICAL:
1664498a243SDavid du Colombier 		if(*pg == nil) {
1679ef1f84bSDavid du Colombier 			fn = s->pseg->pgalloc;
1689ef1f84bSDavid du Colombier 			if(fn)
1699ef1f84bSDavid du Colombier 				*pg = (*fn)(s, addr);
1709ef1f84bSDavid du Colombier 			else {
1719ef1f84bSDavid du Colombier 				new = smalloc(sizeof(Page));
1729ef1f84bSDavid du Colombier 				new->va = addr;
1739ef1f84bSDavid du Colombier 				new->pa = s->pseg->pa+(addr-s->base);
1749ef1f84bSDavid du Colombier 				new->ref = 1;
1759ef1f84bSDavid du Colombier 				new->lg2size = s->pseg->lg2pgsize;
1769ef1f84bSDavid du Colombier 				if(new->lg2size == 0)
1779ef1f84bSDavid du Colombier 					new->lg2size = PGSHFT;	/* TO DO */
1789ef1f84bSDavid du Colombier 				*pg = new;
1799ef1f84bSDavid du Colombier 			}
1809ef1f84bSDavid du Colombier 		}
1819ef1f84bSDavid du Colombier 
182406c76faSDavid du Colombier 		if (checkaddr && addr == addr2check)
183406c76faSDavid du Colombier 			(*checkaddr)(addr, s, *pg);
1841247705eSDavid du Colombier 		mmuphys = PPN((*pg)->pa) | PTEVALID;
1851247705eSDavid du Colombier 		if((s->pseg->attr & SG_RONLY) == 0)
1861247705eSDavid du Colombier 			mmuphys |= PTEWRITE;
1871247705eSDavid du Colombier 		if((s->pseg->attr & SG_CACHED) == 0)
1881247705eSDavid du Colombier 			mmuphys |= PTEUNCACHED;
1899ef1f84bSDavid du Colombier 		(*pg)->modref = PG_MOD|PG_REF;
1909ef1f84bSDavid du Colombier 		break;
1919ef1f84bSDavid du Colombier 	}
1929ef1f84bSDavid du Colombier 	qunlock(&s->lk);
1939ef1f84bSDavid du Colombier 
1949ef1f84bSDavid du Colombier 	if(dommuput)
1959ef1f84bSDavid du Colombier 		mmuput(addr, mmuphys, *pg);
1969ef1f84bSDavid du Colombier 
1979ef1f84bSDavid du Colombier 	return 0;
1989ef1f84bSDavid du Colombier }
1999ef1f84bSDavid du Colombier 
2009ef1f84bSDavid du Colombier void
pio(Segment * s,uintptr addr,uintptr soff,Page ** p,int color)201*094d6818SDavid du Colombier pio(Segment *s, uintptr addr, uintptr soff, Page **p, int color)
2029ef1f84bSDavid du Colombier {
2039ef1f84bSDavid du Colombier 	Page *new;
2049ef1f84bSDavid du Colombier 	KMap *k;
2059ef1f84bSDavid du Colombier 	Chan *c;
2069ef1f84bSDavid du Colombier 	int n, ask;
2079ef1f84bSDavid du Colombier 	char *kaddr;
2089ef1f84bSDavid du Colombier 	ulong daddr;
2099ef1f84bSDavid du Colombier 	Page *loadrec;
2109ef1f84bSDavid du Colombier 	uintptr pgsize;
2119ef1f84bSDavid du Colombier 
21257fe3081SDavid du Colombier 	pgsize = segpgsize(s);
2139ef1f84bSDavid du Colombier 	loadrec = *p;
2149ef1f84bSDavid du Colombier 	if(!pagedout(*p) || loadrec != nil)
2159ef1f84bSDavid du Colombier 		return;
2169ef1f84bSDavid du Colombier 	/* demand load from a text/data image */
2179ef1f84bSDavid du Colombier 	daddr = s->fstart+soff;
2189ef1f84bSDavid du Colombier 	new = lookpage(s->image, daddr);
2199ef1f84bSDavid du Colombier 	if(new != nil) {
2209ef1f84bSDavid du Colombier 		*p = new;
2219ef1f84bSDavid du Colombier 		return;
2229ef1f84bSDavid du Colombier 	}
2239ef1f84bSDavid du Colombier 
2249ef1f84bSDavid du Colombier 	c = s->image->c;
2259ef1f84bSDavid du Colombier 	ask = s->flen-soff;
2269ef1f84bSDavid du Colombier 	if(ask > pgsize)
2279ef1f84bSDavid du Colombier 		ask = pgsize;
2289ef1f84bSDavid du Colombier 	qunlock(&s->lk);
2299ef1f84bSDavid du Colombier 
230*094d6818SDavid du Colombier 	new = newpage(0, s, addr, s->lg2pgsize, color, 0);
2319ef1f84bSDavid du Colombier 	if(new == nil)
2329ef1f84bSDavid du Colombier 		panic("pio");	/* can't happen, s wasn't locked */
2339ef1f84bSDavid du Colombier 
2349ef1f84bSDavid du Colombier 	k = kmap(new);
2359ef1f84bSDavid du Colombier 	kaddr = (char*)VA(k);
2369ef1f84bSDavid du Colombier 
2379ef1f84bSDavid du Colombier 	while(waserror()) {
2389ef1f84bSDavid du Colombier 		if(strcmp(up->errstr, Eintr) == 0)
2399ef1f84bSDavid du Colombier 			continue;
2409ef1f84bSDavid du Colombier 		kunmap(k);
2419ef1f84bSDavid du Colombier 		putpage(new);
2429ef1f84bSDavid du Colombier 		faulterror(Eioload, c, 0);
2439ef1f84bSDavid du Colombier 	}
2449ef1f84bSDavid du Colombier 
2459ef1f84bSDavid du Colombier 	n = c->dev->read(c, kaddr, ask, daddr);
2469ef1f84bSDavid du Colombier 	if(n != ask)
2479ef1f84bSDavid du Colombier 		faulterror(Eioload, c, 0);
2489ef1f84bSDavid du Colombier 	if(ask < pgsize)
2499ef1f84bSDavid du Colombier 		memset(kaddr+ask, 0, pgsize-ask);
2509ef1f84bSDavid du Colombier 
2519ef1f84bSDavid du Colombier 	poperror();
2529ef1f84bSDavid du Colombier 	kunmap(k);
2539ef1f84bSDavid du Colombier 
2549ef1f84bSDavid du Colombier 	qlock(&s->lk);
2559ef1f84bSDavid du Colombier 	/*
2569ef1f84bSDavid du Colombier 	 *  race, another proc may have read the page in while
2579ef1f84bSDavid du Colombier 	 *  s->lk was unlocked
2589ef1f84bSDavid du Colombier 	 */
2599ef1f84bSDavid du Colombier 	if(*p == nil) {
2609ef1f84bSDavid du Colombier 		new->daddr = daddr;
2619ef1f84bSDavid du Colombier 		cachepage(new, s->image);
2629ef1f84bSDavid du Colombier 		*p = new;
2639ef1f84bSDavid du Colombier 	}
2649ef1f84bSDavid du Colombier 	else
2659ef1f84bSDavid du Colombier 		putpage(new);
2669ef1f84bSDavid du Colombier 
2679ef1f84bSDavid du Colombier 	if(s->flushme)
2680d74731bSDavid du Colombier 		mmucachectl(*p, PG_TXTFLUSH);
2699ef1f84bSDavid du Colombier }
2709ef1f84bSDavid du Colombier 
2719ef1f84bSDavid du Colombier /*
2729ef1f84bSDavid du Colombier  * Called only in a system call
2739ef1f84bSDavid du Colombier  */
2749ef1f84bSDavid du Colombier int
okaddr(uintptr addr,long len,int write)2759ef1f84bSDavid du Colombier okaddr(uintptr addr, long len, int write)
2769ef1f84bSDavid du Colombier {
2779ef1f84bSDavid du Colombier 	Segment *s;
2789ef1f84bSDavid du Colombier 
2799c621cc8SDavid du Colombier 	/* second test is paranoia only needed on 64-bit systems */
2809c621cc8SDavid du Colombier 	if(len >= 0 && addr+len >= addr)
2819c621cc8SDavid du Colombier 		while ((s = seg(up, addr, 0)) != nil &&
2829c621cc8SDavid du Colombier 		    (!write || !(s->type&SG_RONLY))) {
2839c621cc8SDavid du Colombier 			if(addr+len <= s->top)
2849c621cc8SDavid du Colombier 				return 1;
2859ef1f84bSDavid du Colombier 			len -= s->top - addr;
2869ef1f84bSDavid du Colombier 			addr = s->top;
2879ef1f84bSDavid du Colombier 		}
2889ef1f84bSDavid du Colombier 	return 0;
2899ef1f84bSDavid du Colombier }
2909ef1f84bSDavid du Colombier 
2919ef1f84bSDavid du Colombier void*
validaddr(void * addr,long len,int write)2929ef1f84bSDavid du Colombier validaddr(void* addr, long len, int write)
2939ef1f84bSDavid du Colombier {
2949ef1f84bSDavid du Colombier 	if(!okaddr(PTR2UINT(addr), len, write)){
2959ef1f84bSDavid du Colombier 		pprint("suicide: invalid address %#p/%ld in sys call pc=%#p\n",
2969ef1f84bSDavid du Colombier 			addr, len, userpc(nil));
2979ef1f84bSDavid du Colombier 		pexit("Suicide", 0);
2989ef1f84bSDavid du Colombier 	}
2999ef1f84bSDavid du Colombier 
3009ef1f84bSDavid du Colombier 	return UINT2PTR(addr);
3019ef1f84bSDavid du Colombier }
3029ef1f84bSDavid du Colombier 
3039ef1f84bSDavid du Colombier /*
3049ef1f84bSDavid du Colombier  * &s[0] is known to be a valid address.
3059ef1f84bSDavid du Colombier  */
3069ef1f84bSDavid du Colombier void*
vmemchr(void * s,int c,int n)3079ef1f84bSDavid du Colombier vmemchr(void *s, int c, int n)
3089ef1f84bSDavid du Colombier {
3099ef1f84bSDavid du Colombier 	int r;
3109ef1f84bSDavid du Colombier 	uintptr a;
3119ef1f84bSDavid du Colombier 	void *t;
3129ef1f84bSDavid du Colombier 
3139ef1f84bSDavid du Colombier 	a = PTR2UINT(s);
3149ef1f84bSDavid du Colombier 	while(ROUNDUP(a, PGSZ) != ROUNDUP(a+n-1, PGSZ)){
3159ef1f84bSDavid du Colombier 		/* spans pages; handle this page */
3169ef1f84bSDavid du Colombier 		r = PGSZ - (a & (PGSZ-1));
3179ef1f84bSDavid du Colombier 		t = memchr(UINT2PTR(a), c, r);
3189ef1f84bSDavid du Colombier 		if(t)
3199ef1f84bSDavid du Colombier 			return t;
3209ef1f84bSDavid du Colombier 		a += r;
3219ef1f84bSDavid du Colombier 		n -= r;
322fe56f827SDavid du Colombier 		if(!iskaddr(a))
3239ef1f84bSDavid du Colombier 			validaddr(UINT2PTR(a), 1, 0);
3249ef1f84bSDavid du Colombier 	}
3259ef1f84bSDavid du Colombier 
3269ef1f84bSDavid du Colombier 	/* fits in one page */
3279ef1f84bSDavid du Colombier 	return memchr(UINT2PTR(a), c, n);
3289ef1f84bSDavid du Colombier }
3299ef1f84bSDavid du Colombier 
3309ef1f84bSDavid du Colombier Segment*
seg(Proc * p,uintptr addr,int dolock)3319ef1f84bSDavid du Colombier seg(Proc *p, uintptr addr, int dolock)
3329ef1f84bSDavid du Colombier {
3339ef1f84bSDavid du Colombier 	Segment **s, **et, *n;
3349ef1f84bSDavid du Colombier 
3359ef1f84bSDavid du Colombier 	et = &p->seg[NSEG];
3369ef1f84bSDavid du Colombier 	for(s = p->seg; s < et; s++) {
3379ef1f84bSDavid du Colombier 		n = *s;
3384498a243SDavid du Colombier 		if(n == nil)
3399ef1f84bSDavid du Colombier 			continue;
3409ef1f84bSDavid du Colombier 		if(addr >= n->base && addr < n->top) {
3419ef1f84bSDavid du Colombier 			if(dolock == 0)
3429ef1f84bSDavid du Colombier 				return n;
3439ef1f84bSDavid du Colombier 
3449ef1f84bSDavid du Colombier 			qlock(&n->lk);
3459ef1f84bSDavid du Colombier 			if(addr >= n->base && addr < n->top)
3469ef1f84bSDavid du Colombier 				return n;
3479ef1f84bSDavid du Colombier 			qunlock(&n->lk);
3489ef1f84bSDavid du Colombier 		}
3499ef1f84bSDavid du Colombier 	}
3509ef1f84bSDavid du Colombier 
3519ef1f84bSDavid du Colombier 	return 0;
3529ef1f84bSDavid du Colombier }
3531f646f47SDavid du Colombier 
3541f646f47SDavid du Colombier extern void checkmmu(uintptr, uintmem);
3551f646f47SDavid du Colombier void
checkpages(void)3561f646f47SDavid du Colombier checkpages(void)
3571f646f47SDavid du Colombier {
3581f646f47SDavid du Colombier 	int checked;
3591f646f47SDavid du Colombier 	uintptr addr, off;
3601f646f47SDavid du Colombier 	Pte *p;
3611f646f47SDavid du Colombier 	Page *pg;
3621f646f47SDavid du Colombier 	Segment **sp, **ep, *s;
3631f646f47SDavid du Colombier 	uint pgsize;
3641f646f47SDavid du Colombier 
3651f646f47SDavid du Colombier 	if(up == nil)
3661f646f47SDavid du Colombier 		return;
3671f646f47SDavid du Colombier 
3681f646f47SDavid du Colombier 	checked = 0;
3691f646f47SDavid du Colombier 	for(sp=up->seg, ep=&up->seg[NSEG]; sp<ep; sp++){
3701f646f47SDavid du Colombier 		s = *sp;
3711f646f47SDavid du Colombier 		if(s == nil)
3721f646f47SDavid du Colombier 			continue;
3731f646f47SDavid du Colombier 		qlock(&s->lk);
37457fe3081SDavid du Colombier 		pgsize = segpgsize(s);
3751f646f47SDavid du Colombier 		for(addr=s->base; addr<s->top; addr+=pgsize){
3761f646f47SDavid du Colombier 			off = addr - s->base;
3771f646f47SDavid du Colombier 			p = s->map[off/s->ptemapmem];
3781f646f47SDavid du Colombier 			if(p == nil)
3791f646f47SDavid du Colombier 				continue;
3801f646f47SDavid du Colombier 			pg = p->pages[(off&(s->ptemapmem-1))/pgsize];
3811f646f47SDavid du Colombier 			if(pg == nil || pagedout(pg))
3821f646f47SDavid du Colombier 				continue;
3831f646f47SDavid du Colombier 			checkmmu(addr, pg->pa);
3841f646f47SDavid du Colombier 			checked++;
3851f646f47SDavid du Colombier 		}
3861f646f47SDavid du Colombier 		qunlock(&s->lk);
3871f646f47SDavid du Colombier 	}
3881f646f47SDavid du Colombier        print("%d %s: checked %d page table entries\n", up->pid, up->text, checked);
3891f646f47SDavid du Colombier }
390