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
83e12c5d1SDavid du Colombier int
fault(ulong addr,int read)93e12c5d1SDavid du Colombier fault(ulong addr, int read)
103e12c5d1SDavid du Colombier {
113e12c5d1SDavid du Colombier Segment *s;
123e12c5d1SDavid du Colombier char *sps;
133e12c5d1SDavid du Colombier
14b8a11165SDavid du Colombier if(up == nil)
15b8a11165SDavid du Colombier panic("fault: nil up");
16b8a11165SDavid du Colombier if(up->nlocks.ref)
1723173ec1SDavid du Colombier print("fault: addr %#p: nlocks %ld\n", addr, up->nlocks.ref);
18e288d156SDavid du Colombier
197dd7cddfSDavid du Colombier sps = up->psstate;
207dd7cddfSDavid du Colombier up->psstate = "Fault";
213e12c5d1SDavid du Colombier spllo();
223e12c5d1SDavid du Colombier
233e12c5d1SDavid du Colombier m->pfault++;
24*0400b647SDavid du Colombier for(;;) {
257dd7cddfSDavid du Colombier s = seg(up, addr, 1); /* leaves s->lk qlocked if seg != nil */
263e12c5d1SDavid du Colombier if(s == 0) {
277dd7cddfSDavid du Colombier up->psstate = sps;
283e12c5d1SDavid du Colombier return -1;
293e12c5d1SDavid du Colombier }
303e12c5d1SDavid du Colombier
313e12c5d1SDavid du Colombier if(!read && (s->type&SG_RONLY)) {
323e12c5d1SDavid du Colombier qunlock(&s->lk);
337dd7cddfSDavid du Colombier up->psstate = sps;
343e12c5d1SDavid du Colombier return -1;
353e12c5d1SDavid du Colombier }
363e12c5d1SDavid du Colombier
37afa28516SDavid du Colombier if(fixfault(s, addr, read, 1) == 0) /* qunlocks s->lk */
383e12c5d1SDavid du Colombier break;
393e12c5d1SDavid du Colombier }
403e12c5d1SDavid du Colombier
417dd7cddfSDavid du Colombier up->psstate = sps;
423e12c5d1SDavid du Colombier return 0;
433e12c5d1SDavid du Colombier }
443e12c5d1SDavid du Colombier
457dd7cddfSDavid du Colombier static void
faulterror(char * s,Chan * c,int freemem)469a747e4fSDavid du Colombier faulterror(char *s, Chan *c, int freemem)
477dd7cddfSDavid du Colombier {
489a747e4fSDavid du Colombier char buf[ERRMAX];
499a747e4fSDavid du Colombier
504afe124fSDavid du Colombier if(c && c->path){
514afe124fSDavid du Colombier snprint(buf, sizeof buf, "%s accessing %s: %s", s, c->path->s, up->errstr);
529a747e4fSDavid du Colombier s = buf;
539a747e4fSDavid du Colombier }
547dd7cddfSDavid du Colombier if(up->nerrlab) {
557dd7cddfSDavid du Colombier postnote(up, 1, s, NDebug);
567dd7cddfSDavid du Colombier error(s);
577dd7cddfSDavid du Colombier }
587dd7cddfSDavid du Colombier pexit(s, freemem);
597dd7cddfSDavid du Colombier }
607dd7cddfSDavid du Colombier
61ea58ad6fSDavid du Colombier void (*checkaddr)(ulong, Segment *, Page *);
62ea58ad6fSDavid du Colombier ulong addr2check;
63ea58ad6fSDavid du Colombier
643e12c5d1SDavid du Colombier int
fixfault(Segment * s,ulong addr,int read,int doputmmu)653e12c5d1SDavid du Colombier fixfault(Segment *s, ulong addr, int read, int doputmmu)
663e12c5d1SDavid du Colombier {
67219b2ee8SDavid du Colombier int type;
687dd7cddfSDavid du Colombier int ref;
69219b2ee8SDavid du Colombier Pte **p, *etp;
709a747e4fSDavid du Colombier ulong mmuphys=0, soff;
713e12c5d1SDavid du Colombier Page **pg, *lkp, *new;
72219b2ee8SDavid du Colombier Page *(*fn)(Segment*, ulong);
733e12c5d1SDavid du Colombier
743e12c5d1SDavid du Colombier addr &= ~(BY2PG-1);
753e12c5d1SDavid du Colombier soff = addr-s->base;
763e12c5d1SDavid du Colombier p = &s->map[soff/PTEMAPMEM];
773e12c5d1SDavid du Colombier if(*p == 0)
783e12c5d1SDavid du Colombier *p = ptealloc();
793e12c5d1SDavid du Colombier
803e12c5d1SDavid du Colombier etp = *p;
813e12c5d1SDavid du Colombier pg = &etp->pages[(soff&(PTEMAPMEM-1))/BY2PG];
823e12c5d1SDavid du Colombier type = s->type&SG_TYPE;
833e12c5d1SDavid du Colombier
843e12c5d1SDavid du Colombier if(pg < etp->first)
853e12c5d1SDavid du Colombier etp->first = pg;
863e12c5d1SDavid du Colombier if(pg > etp->last)
873e12c5d1SDavid du Colombier etp->last = pg;
883e12c5d1SDavid du Colombier
893e12c5d1SDavid du Colombier switch(type) {
903e12c5d1SDavid du Colombier default:
913e12c5d1SDavid du Colombier panic("fault");
923e12c5d1SDavid du Colombier break;
933e12c5d1SDavid du Colombier
947dd7cddfSDavid du Colombier case SG_TEXT: /* Demand load */
957dd7cddfSDavid du Colombier if(pagedout(*pg))
963e12c5d1SDavid du Colombier pio(s, addr, soff, pg);
973e12c5d1SDavid du Colombier
983e12c5d1SDavid du Colombier mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID;
993e12c5d1SDavid du Colombier (*pg)->modref = PG_REF;
1003e12c5d1SDavid du Colombier break;
1013e12c5d1SDavid du Colombier
1023e12c5d1SDavid du Colombier case SG_BSS:
1033e12c5d1SDavid du Colombier case SG_SHARED: /* Zero fill on demand */
1043e12c5d1SDavid du Colombier case SG_STACK:
1053e12c5d1SDavid du Colombier if(*pg == 0) {
1063e12c5d1SDavid du Colombier new = newpage(1, &s, addr);
1073e12c5d1SDavid du Colombier if(s == 0)
1083e12c5d1SDavid du Colombier return -1;
1093e12c5d1SDavid du Colombier
1103e12c5d1SDavid du Colombier *pg = new;
1113e12c5d1SDavid du Colombier }
1127dd7cddfSDavid du Colombier goto common;
1133e12c5d1SDavid du Colombier
1147dd7cddfSDavid du Colombier case SG_DATA:
1157dd7cddfSDavid du Colombier common: /* Demand load/pagein/copy on write */
1163e12c5d1SDavid du Colombier if(pagedout(*pg))
1173e12c5d1SDavid du Colombier pio(s, addr, soff, pg);
1183e12c5d1SDavid du Colombier
11980ee5cbfSDavid du Colombier /*
12080ee5cbfSDavid du Colombier * It's only possible to copy on write if
12180ee5cbfSDavid du Colombier * we're the only user of the segment.
12280ee5cbfSDavid du Colombier */
12380ee5cbfSDavid du Colombier if(read && conf.copymode == 0 && s->ref == 1) {
1243e12c5d1SDavid du Colombier mmuphys = PPN((*pg)->pa)|PTERONLY|PTEVALID;
1253e12c5d1SDavid du Colombier (*pg)->modref |= PG_REF;
1263e12c5d1SDavid du Colombier break;
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier
1293e12c5d1SDavid du Colombier lkp = *pg;
1303e12c5d1SDavid du Colombier lock(lkp);
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier if(lkp->image == &swapimage)
1337dd7cddfSDavid du Colombier ref = lkp->ref + swapcount(lkp->daddr);
1347dd7cddfSDavid du Colombier else
1357dd7cddfSDavid du Colombier ref = lkp->ref;
136afa28516SDavid du Colombier if(ref == 1 && lkp->image){
137afa28516SDavid du Colombier /* save a copy of the original for the image cache */
138afa28516SDavid du Colombier duppage(lkp);
139afa28516SDavid du Colombier ref = lkp->ref;
140afa28516SDavid du Colombier }
1413e12c5d1SDavid du Colombier unlock(lkp);
142afa28516SDavid du Colombier if(ref > 1){
1433e12c5d1SDavid du Colombier new = newpage(0, &s, addr);
1443e12c5d1SDavid du Colombier if(s == 0)
1453e12c5d1SDavid du Colombier return -1;
1463e12c5d1SDavid du Colombier *pg = new;
1473e12c5d1SDavid du Colombier copypage(lkp, *pg);
1483e12c5d1SDavid du Colombier putpage(lkp);
1493e12c5d1SDavid du Colombier }
1503e12c5d1SDavid du Colombier mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID;
1513e12c5d1SDavid du Colombier (*pg)->modref = PG_MOD|PG_REF;
1523e12c5d1SDavid du Colombier break;
1533e12c5d1SDavid du Colombier
1543e12c5d1SDavid du Colombier case SG_PHYSICAL:
155219b2ee8SDavid du Colombier if(*pg == 0) {
156219b2ee8SDavid du Colombier fn = s->pseg->pgalloc;
157219b2ee8SDavid du Colombier if(fn)
158219b2ee8SDavid du Colombier *pg = (*fn)(s, addr);
159219b2ee8SDavid du Colombier else {
160219b2ee8SDavid du Colombier new = smalloc(sizeof(Page));
161219b2ee8SDavid du Colombier new->va = addr;
162219b2ee8SDavid du Colombier new->pa = s->pseg->pa+(addr-s->base);
163219b2ee8SDavid du Colombier new->ref = 1;
164219b2ee8SDavid du Colombier *pg = new;
165219b2ee8SDavid du Colombier }
166219b2ee8SDavid du Colombier }
1673e12c5d1SDavid du Colombier
168ea58ad6fSDavid du Colombier if (checkaddr && addr == addr2check)
169ea58ad6fSDavid du Colombier (*checkaddr)(addr, s, *pg);
1703e12c5d1SDavid du Colombier mmuphys = PPN((*pg)->pa) |PTEWRITE|PTEUNCACHED|PTEVALID;
1713e12c5d1SDavid du Colombier (*pg)->modref = PG_MOD|PG_REF;
1723e12c5d1SDavid du Colombier break;
1733e12c5d1SDavid du Colombier }
1743e12c5d1SDavid du Colombier qunlock(&s->lk);
1753e12c5d1SDavid du Colombier
1763e12c5d1SDavid du Colombier if(doputmmu)
1773e12c5d1SDavid du Colombier putmmu(addr, mmuphys, *pg);
1783e12c5d1SDavid du Colombier
1793e12c5d1SDavid du Colombier return 0;
1803e12c5d1SDavid du Colombier }
1813e12c5d1SDavid du Colombier
1823e12c5d1SDavid du Colombier void
pio(Segment * s,ulong addr,ulong soff,Page ** p)1833e12c5d1SDavid du Colombier pio(Segment *s, ulong addr, ulong soff, Page **p)
1843e12c5d1SDavid du Colombier {
1853e12c5d1SDavid du Colombier Page *new;
1863e12c5d1SDavid du Colombier KMap *k;
1873e12c5d1SDavid du Colombier Chan *c;
1883e12c5d1SDavid du Colombier int n, ask;
1893e12c5d1SDavid du Colombier char *kaddr;
1903e12c5d1SDavid du Colombier ulong daddr;
1913e12c5d1SDavid du Colombier Page *loadrec;
1923e12c5d1SDavid du Colombier
1937dd7cddfSDavid du Colombier retry:
1943e12c5d1SDavid du Colombier loadrec = *p;
1957dd7cddfSDavid du Colombier if(loadrec == 0) { /* from a text/data image */
1967dd7cddfSDavid du Colombier daddr = s->fstart+soff;
1973e12c5d1SDavid du Colombier new = lookpage(s->image, daddr);
1987dd7cddfSDavid du Colombier if(new != nil) {
1993e12c5d1SDavid du Colombier *p = new;
2003e12c5d1SDavid du Colombier return;
2013e12c5d1SDavid du Colombier }
202d1be6b08SDavid du Colombier
203d1be6b08SDavid du Colombier c = s->image->c;
204d1be6b08SDavid du Colombier ask = s->flen-soff;
205d1be6b08SDavid du Colombier if(ask > BY2PG)
206d1be6b08SDavid du Colombier ask = BY2PG;
2077dd7cddfSDavid du Colombier }
2087dd7cddfSDavid du Colombier else { /* from a swap image */
2097dd7cddfSDavid du Colombier daddr = swapaddr(loadrec);
2107dd7cddfSDavid du Colombier new = lookpage(&swapimage, daddr);
2117dd7cddfSDavid du Colombier if(new != nil) {
2127dd7cddfSDavid du Colombier putswap(loadrec);
2137dd7cddfSDavid du Colombier *p = new;
2147dd7cddfSDavid du Colombier return;
2157dd7cddfSDavid du Colombier }
216d1be6b08SDavid du Colombier
217d1be6b08SDavid du Colombier c = swapimage.c;
218d1be6b08SDavid du Colombier ask = BY2PG;
2197dd7cddfSDavid du Colombier }
2203e12c5d1SDavid du Colombier qunlock(&s->lk);
2213e12c5d1SDavid du Colombier
2223e12c5d1SDavid du Colombier new = newpage(0, 0, addr);
2233e12c5d1SDavid du Colombier k = kmap(new);
2243e12c5d1SDavid du Colombier kaddr = (char*)VA(k);
2253e12c5d1SDavid du Colombier
2263e12c5d1SDavid du Colombier while(waserror()) {
2279a747e4fSDavid du Colombier if(strcmp(up->errstr, Eintr) == 0)
2283e12c5d1SDavid du Colombier continue;
2293e12c5d1SDavid du Colombier kunmap(k);
2303e12c5d1SDavid du Colombier putpage(new);
231d1be6b08SDavid du Colombier faulterror(Eioload, c, 0);
2323e12c5d1SDavid du Colombier }
2333e12c5d1SDavid du Colombier
2347dd7cddfSDavid du Colombier n = devtab[c->type]->read(c, kaddr, ask, daddr);
2357dd7cddfSDavid du Colombier if(n != ask)
2369a747e4fSDavid du Colombier faulterror(Eioload, c, 0);
2373e12c5d1SDavid du Colombier if(ask < BY2PG)
2383e12c5d1SDavid du Colombier memset(kaddr+ask, 0, BY2PG-ask);
2393e12c5d1SDavid du Colombier
2403e12c5d1SDavid du Colombier poperror();
2413e12c5d1SDavid du Colombier kunmap(k);
2423e12c5d1SDavid du Colombier qlock(&s->lk);
243d1be6b08SDavid du Colombier if(loadrec == 0) { /* This is demand load */
2447dd7cddfSDavid du Colombier /*
2457dd7cddfSDavid du Colombier * race, another proc may have gotten here first while
2467dd7cddfSDavid du Colombier * s->lk was unlocked
2477dd7cddfSDavid du Colombier */
2487dd7cddfSDavid du Colombier if(*p == 0) {
2493e12c5d1SDavid du Colombier new->daddr = daddr;
2503e12c5d1SDavid du Colombier cachepage(new, s->image);
2513e12c5d1SDavid du Colombier *p = new;
2523e12c5d1SDavid du Colombier }
2533e12c5d1SDavid du Colombier else
2543e12c5d1SDavid du Colombier putpage(new);
2553e12c5d1SDavid du Colombier }
2563e12c5d1SDavid du Colombier else { /* This is paged out */
2577dd7cddfSDavid du Colombier /*
2587dd7cddfSDavid du Colombier * race, another proc may have gotten here first
2597dd7cddfSDavid du Colombier * (and the pager may have run on that page) while
2607dd7cddfSDavid du Colombier * s->lk was unlocked
2617dd7cddfSDavid du Colombier */
2627dd7cddfSDavid du Colombier if(*p != loadrec){
2637dd7cddfSDavid du Colombier if(!pagedout(*p)){
2647dd7cddfSDavid du Colombier /* another process did it for me */
2653e12c5d1SDavid du Colombier putpage(new);
2667dd7cddfSDavid du Colombier goto done;
2677dd7cddfSDavid du Colombier } else {
2687dd7cddfSDavid du Colombier /* another process and the pager got in */
2697dd7cddfSDavid du Colombier putpage(new);
2707dd7cddfSDavid du Colombier goto retry;
2713e12c5d1SDavid du Colombier }
2723e12c5d1SDavid du Colombier }
2733e12c5d1SDavid du Colombier
2747dd7cddfSDavid du Colombier new->daddr = daddr;
2757dd7cddfSDavid du Colombier cachepage(new, &swapimage);
2767dd7cddfSDavid du Colombier *p = new;
2777dd7cddfSDavid du Colombier putswap(loadrec);
2783e12c5d1SDavid du Colombier }
2797dd7cddfSDavid du Colombier
2807dd7cddfSDavid du Colombier done:
2817dd7cddfSDavid du Colombier if(s->flushme)
2827dd7cddfSDavid du Colombier memset((*p)->cachectl, PG_TXTFLUSH, sizeof((*p)->cachectl));
2833e12c5d1SDavid du Colombier }
2843e12c5d1SDavid du Colombier
2853e12c5d1SDavid du Colombier /*
2863e12c5d1SDavid du Colombier * Called only in a system call
2873e12c5d1SDavid du Colombier */
2883e12c5d1SDavid du Colombier int
okaddr(ulong addr,ulong len,int write)2893e12c5d1SDavid du Colombier okaddr(ulong addr, ulong len, int write)
2903e12c5d1SDavid du Colombier {
2913e12c5d1SDavid du Colombier Segment *s;
2923e12c5d1SDavid du Colombier
2933e12c5d1SDavid du Colombier if((long)len >= 0) {
2943e12c5d1SDavid du Colombier for(;;) {
2957dd7cddfSDavid du Colombier s = seg(up, addr, 0);
2963e12c5d1SDavid du Colombier if(s == 0 || (write && (s->type&SG_RONLY)))
2973e12c5d1SDavid du Colombier break;
2983e12c5d1SDavid du Colombier
2993e12c5d1SDavid du Colombier if(addr+len > s->top) {
3003e12c5d1SDavid du Colombier len -= s->top - addr;
3013e12c5d1SDavid du Colombier addr = s->top;
3023e12c5d1SDavid du Colombier continue;
3033e12c5d1SDavid du Colombier }
3043e12c5d1SDavid du Colombier return 1;
3053e12c5d1SDavid du Colombier }
3063e12c5d1SDavid du Colombier }
307567483c8SDavid du Colombier pprint("suicide: invalid address %#lux/%lud in sys call pc=%#lux\n", addr, len, userpc());
3083e12c5d1SDavid du Colombier return 0;
3093e12c5d1SDavid du Colombier }
3103e12c5d1SDavid du Colombier
3113e12c5d1SDavid du Colombier void
validaddr(ulong addr,ulong len,int write)3123e12c5d1SDavid du Colombier validaddr(ulong addr, ulong len, int write)
3133e12c5d1SDavid du Colombier {
314d1be6b08SDavid du Colombier if(!okaddr(addr, len, write)){
315d1be6b08SDavid du Colombier postnote(up, 1, "sys: bad address in syscall", NDebug);
316d1be6b08SDavid du Colombier error(Ebadarg);
317d1be6b08SDavid du Colombier }
3183e12c5d1SDavid du Colombier }
3193e12c5d1SDavid du Colombier
3203e12c5d1SDavid du Colombier /*
3213e12c5d1SDavid du Colombier * &s[0] is known to be a valid address.
3223e12c5d1SDavid du Colombier */
3233e12c5d1SDavid du Colombier void*
vmemchr(void * s,int c,int n)3243e12c5d1SDavid du Colombier vmemchr(void *s, int c, int n)
3253e12c5d1SDavid du Colombier {
3263e12c5d1SDavid du Colombier int m;
3273e12c5d1SDavid du Colombier ulong a;
3283ff48bf5SDavid du Colombier void *t;
3293e12c5d1SDavid du Colombier
3303e12c5d1SDavid du Colombier a = (ulong)s;
3313ff48bf5SDavid du Colombier while(PGROUND(a) != PGROUND(a+n-1)){
3323ff48bf5SDavid du Colombier /* spans pages; handle this page */
3333e12c5d1SDavid du Colombier m = BY2PG - (a & (BY2PG-1));
3343ff48bf5SDavid du Colombier t = memchr((void*)a, c, m);
3353e12c5d1SDavid du Colombier if(t)
3363e12c5d1SDavid du Colombier return t;
3373ff48bf5SDavid du Colombier a += m;
3389a747e4fSDavid du Colombier n -= m;
3394de34a7eSDavid du Colombier if(a < KZERO)
3403ff48bf5SDavid du Colombier validaddr(a, 1, 0);
3413e12c5d1SDavid du Colombier }
3423ff48bf5SDavid du Colombier
3433ff48bf5SDavid du Colombier /* fits in one page */
3443ff48bf5SDavid du Colombier return memchr((void*)a, c, n);
3453e12c5d1SDavid du Colombier }
3463e12c5d1SDavid du Colombier
3473e12c5d1SDavid du Colombier Segment*
seg(Proc * p,ulong addr,int dolock)3483e12c5d1SDavid du Colombier seg(Proc *p, ulong addr, int dolock)
3493e12c5d1SDavid du Colombier {
3503e12c5d1SDavid du Colombier Segment **s, **et, *n;
3513e12c5d1SDavid du Colombier
3523e12c5d1SDavid du Colombier et = &p->seg[NSEG];
3537dd7cddfSDavid du Colombier for(s = p->seg; s < et; s++) {
3547dd7cddfSDavid du Colombier n = *s;
3557dd7cddfSDavid du Colombier if(n == 0)
3567dd7cddfSDavid du Colombier continue;
3573e12c5d1SDavid du Colombier if(addr >= n->base && addr < n->top) {
3583e12c5d1SDavid du Colombier if(dolock == 0)
3593e12c5d1SDavid du Colombier return n;
3603e12c5d1SDavid du Colombier
3613e12c5d1SDavid du Colombier qlock(&n->lk);
3623e12c5d1SDavid du Colombier if(addr >= n->base && addr < n->top)
3633e12c5d1SDavid du Colombier return n;
3643e12c5d1SDavid du Colombier qunlock(&n->lk);
3653e12c5d1SDavid du Colombier }
3663e12c5d1SDavid du Colombier }
3673e12c5d1SDavid du Colombier
3683e12c5d1SDavid du Colombier return 0;
3693e12c5d1SDavid du Colombier }
370d717568cSDavid du Colombier
371d717568cSDavid du Colombier extern void checkmmu(ulong, ulong);
372d717568cSDavid du Colombier void
checkpages(void)373d717568cSDavid du Colombier checkpages(void)
374d717568cSDavid du Colombier {
375d717568cSDavid du Colombier int checked;
376d717568cSDavid du Colombier ulong addr, off;
377d717568cSDavid du Colombier Pte *p;
378d717568cSDavid du Colombier Page *pg;
379d717568cSDavid du Colombier Segment **sp, **ep, *s;
380d717568cSDavid du Colombier
381d717568cSDavid du Colombier if(up == nil)
382d717568cSDavid du Colombier return;
383d717568cSDavid du Colombier
384d717568cSDavid du Colombier checked = 0;
385d717568cSDavid du Colombier for(sp=up->seg, ep=&up->seg[NSEG]; sp<ep; sp++){
386d717568cSDavid du Colombier s = *sp;
387d717568cSDavid du Colombier if(s == nil)
388d717568cSDavid du Colombier continue;
389d717568cSDavid du Colombier qlock(&s->lk);
390d717568cSDavid du Colombier for(addr=s->base; addr<s->top; addr+=BY2PG){
391d717568cSDavid du Colombier off = addr - s->base;
392d717568cSDavid du Colombier p = s->map[off/PTEMAPMEM];
393d717568cSDavid du Colombier if(p == 0)
394d717568cSDavid du Colombier continue;
395d717568cSDavid du Colombier pg = p->pages[(off&(PTEMAPMEM-1))/BY2PG];
396d717568cSDavid du Colombier if(pg == 0 || pagedout(pg))
397d717568cSDavid du Colombier continue;
398d717568cSDavid du Colombier checkmmu(addr, pg->pa);
399d717568cSDavid du Colombier checked++;
400d717568cSDavid du Colombier }
401d717568cSDavid du Colombier qunlock(&s->lk);
402d717568cSDavid du Colombier }
403d717568cSDavid du Colombier print("%ld %s: checked %d page table entries\n", up->pid, up->text, checked);
404d717568cSDavid du Colombier }
405