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

1990/0617/gnot/fault.c (diff list | history)

1990/03091/sys/src/9/gnot/fault.c:83,881990/0312/sys/src/9/gnot/fault.c:83,89 (short | long)
1990/03091    
		read = (f->ssw&READ) && !(f->ssw&RM); 
	else 
		read = f->ssw&(FB|FC); 
1990/0312    
/* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/ 
1990/03091    
 
	s = seg(u->p, addr); 
	if(s == 0){ 
1990/03091/sys/src/9/gnot/fault.c:272,2801990/0312/sys/src/9/gnot/fault.c:273,282
1990/03091    
	Seg *s; 
 
	if((long)len < 0) 
		panic("validaddr len %lux\n", len); 
1990/0312    
		goto Err; 
1990/03091    
	s = seg(u->p, addr); 
	if(s==0 || addr+len>s->maxva || (write && (s->o->flag&OWRPERM)==0)){ 
1990/0312    
    Err: 
1990/03091    
		pprint("invalid address in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); 
		postnote(u->p, 1, "bad address", NDebug); 
		error(0, Ebadarg); 
1990/0312/sys/src/9/gnot/fault.c:89,1001990/0315/sys/src/9/gnot/fault.c:89,100 (short | long)
1990/03091    
	if(s == 0){ 
		if(addr>USTKTOP){ 
	    cant: 
			u->p->state = MMUing; 
			if(user){ 
				pprint("user %s error addr=0x%lux\n", read? "read" : "write", badvaddr); 
				pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->sr, ur->pc, ur->sp); 
				pexit("Suicide", 0); 
			} 
1990/0315    
			u->p->state = MMUing; 
1990/03091    
			dumpregs(ur); 
			panic("fault"); 
			exit(); 
1990/0315/sys/src/9/gnot/fault.c:51,611990/06021/sys/src/9/gnot/fault.c:51,62 (short | long)
1990/03091    
	Orig *o; 
	char *l; 
	Page *pg; 
1990/06021    
	KMap *k, *k1; 
1990/03091    
	int zeroed = 0, head = 1; 
	int i, user, read, insyscall; 
 
	if(u == 0) 
		panic("fault"); 
1990/06021    
		panic("fault u==0 pc=%lux", ur->pc); 
1990/03091    
	insyscall = u->p->insyscall; 
	u->p->insyscall = 1; 
	if(f->ssw & DF) 
1990/0315/sys/src/9/gnot/fault.c:149,1571990/06021/sys/src/9/gnot/fault.c:150,160
1990/03091    
			if(n > BY2PG) 
				n = BY2PG; 
			pg = newpage(1, o, addr); 
1990/06021    
			k = kmap(pg); 
1990/03091    
			qlock(o->chan); 
			if(waserror()){ 
				print("demand load i/o error %d\n", u->error.code); 
1990/06021    
				kunmap(k); 
1990/03091    
				qunlock(o->chan); 
				pg->o = 0; 
				pg->ref--; 
1990/0315/sys/src/9/gnot/fault.c:158,1721990/06021/sys/src/9/gnot/fault.c:161,176
1990/03091    
				goto cant; 
			} 
			o->chan->offset = (addr-o->va) + o->minca; 
			l = (char*)(pg->pa|KZERO); 
1990/06021    
			l = (char*)k->va; 
1990/03091    
			if((*devtab[o->chan->type].read)(o->chan, l, n) != n) 
				error(0, Eioload); 
			qunlock(o->chan); 
			poperror(); 
			/* BUG: if was first page of bss, move to data */ 
			if(n<BY2PG) 
				memset(l+n, 0, BY2PG-n); 
			lock(o); 
1990/06021    
			kunmap(k); 
			poperror(); 
1990/03091    
			opte = &o->pte[(addr-s->minva)>>PGSHIFT];	/* could move */ 
			pte = opte; 
			if(pte->page == 0){ 
1990/0315/sys/src/9/gnot/fault.c:231,2371990/06021/sys/src/9/gnot/fault.c:235,245
1990/03091    
			opte->page = 0; 
		}else{		/* copy page */ 
			pte->page = newpage(1, o, addr); 
			memcpy((void*)(pte->page->pa|KZERO), (void*)(pg->pa|KZERO), BY2PG); 
1990/06021    
			k = kmap(pte->page); 
			k1 = kmap(pg); 
			memcpy((void*)k->va, (void*)k1->va, BY2PG); 
			kunmap(k); 
			kunmap(k1); 
1990/03091    
			if(pg->ref <= 1) 
				panic("pg->ref <= 1"); 
			pg->ref--; 
1990/06021/sys/src/9/gnot/fault.c:55,621990/0603/sys/src/9/gnot/fault.c:55,64 (short | long)
1990/03091    
	int zeroed = 0, head = 1; 
	int i, user, read, insyscall; 
 
	if(u == 0) 
1990/0603    
	if(u == 0){ 
		dumpregs(ur); 
1990/06021    
		panic("fault u==0 pc=%lux", ur->pc); 
1990/0603    
	} 
1990/03091    
	insyscall = u->p->insyscall; 
	u->p->insyscall = 1; 
	if(f->ssw & DF) 
1990/0603/sys/src/9/gnot/fault.c:163,1691990/0614/sys/src/9/gnot/fault.c:163,169 (short | long)
1990/03091    
				goto cant; 
			} 
			o->chan->offset = (addr-o->va) + o->minca; 
1990/06021    
			l = (char*)k->va; 
1990/0614    
			l = (char*)VA(k); 
1990/03091    
			if((*devtab[o->chan->type].read)(o->chan, l, n) != n) 
				error(0, Eioload); 
			qunlock(o->chan); 
1990/0603/sys/src/9/gnot/fault.c:239,2451990/0614/sys/src/9/gnot/fault.c:239,245
1990/03091    
			pte->page = newpage(1, o, addr); 
1990/06021    
			k = kmap(pte->page); 
			k1 = kmap(pg); 
			memcpy((void*)k->va, (void*)k1->va, BY2PG); 
1990/0614    
			memcpy((void*)VA(k), (void*)VA(k1), BY2PG); 
1990/06021    
			kunmap(k); 
			kunmap(k1); 
1990/03091    
			if(pg->ref <= 1) 
1990/0614/sys/src/9/gnot/fault.c:280,2981990/0617/sys/src/9/gnot/fault.c:280,305 (short | long)
1990/03091    
void 
validaddr(ulong addr, ulong len, int write) 
{ 
	Seg *s; 
1990/0617    
	Seg *s, *ns; 
1990/03091    
 
	if((long)len < 0) 
1990/0312    
		goto Err; 
1990/03091    
	s = seg(u->p, addr); 
	if(s==0 || addr+len>s->maxva || (write && (s->o->flag&OWRPERM)==0)){ 
1990/0617    
	if((long)len < 0){ 
1990/0312    
    Err: 
1990/03091    
		pprint("invalid address in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); 
		postnote(u->p, 1, "bad address", NDebug); 
		error(0, Ebadarg); 
	} 
1990/0617    
    Again: 
	s = seg(u->p, addr); 
	if(s==0) 
		goto Err; 
	if(write && (s->o->flag&OWRPERM)==0) 
		goto Err; 
	if(addr+len > s->maxva){ 
		len -= s->maxva - addr; 
		addr = s->maxva; 
		goto Again; 
	} 
1990/03091    
} 
                 
/* 
 * &s[0] is known to be a valid address. 
 */ 
1990/0617/sys/src/9/gnot/fault.c:185,1931990/0724/sys/src/9/gnot/fault.c:185,193 (short | long)
1990/03091    
		} 
	} 
	/* 
	 * Copy on reference 
1990/0724    
	 * Copy on write 
1990/03091    
	 */ 
	if((o->flag & OWRPERM) 
1990/0724    
	if((o->flag & OWRPERM) && !read 
1990/03091    
	&& ((head && ((o->flag&OPURE) || o->nproc>1)) 
	    || (!head && pte->page->ref>1))){ 
 
1990/0724/sys/src/9/gnot/fault.c:108,1161990/0802/sys/src/9/gnot/fault.c:108,122 (short | long)
1990/03091    
		/* grow stack */ 
		o = s->o; 
		n = o->npte; 
1990/0802    
		lock(o); 
		if(waserror()){ 
			unlock(o); 
			pprint("can't allocate stack page\n"); 
			goto cant; 
		} 
1990/03091    
		growpte(o, (s->maxva-addr)>>PGSHIFT); 
1990/0802    
		poperror(); 
1990/03091    
		/* stacks grown down, sigh */ 
		lock(o); 
		memcpy(o->pte+(o->npte-n), o->pte, n*sizeof(PTE)); 
		memset(o->pte, 0, (o->npte-n)*sizeof(PTE)); 
		unlock(o); 
1990/0802/sys/src/9/gnot/fault.c:79,841990/08101/sys/src/9/gnot/fault.c:79,85 (short | long)
1990/03091    
			panic("prefetch pagefault"); 
	}else 
		panic("prefetch format"); 
1990/08101    
	addr &= VAMASK; 
1990/03091    
	badvaddr = addr; 
	addr &= ~(BY2PG-1); 
	user = !(ur->sr&SUPER); 
1990/0802/sys/src/9/gnot/fault.c:99,1051990/08101/sys/src/9/gnot/fault.c:100,106
1990/03091    
			} 
1990/0315    
			u->p->state = MMUing; 
1990/03091    
			dumpregs(ur); 
			panic("fault"); 
1990/08101    
			panic("fault: 0x%lux", badvaddr); 
1990/03091    
			exit(); 
		} 
		s = &u->p->seg[SSEG]; 
1990/08101/sys/src/9/gnot/fault.c:109,1171990/0814/sys/src/9/gnot/fault.c:109,115 (short | long)
1990/03091    
		/* grow stack */ 
		o = s->o; 
		n = o->npte; 
1990/0802    
		lock(o); 
		if(waserror()){ 
			unlock(o); 
			pprint("can't allocate stack page\n"); 
			goto cant; 
		} 
1990/08101/sys/src/9/gnot/fault.c:118,1231990/0814/sys/src/9/gnot/fault.c:116,122
1990/03091    
		growpte(o, (s->maxva-addr)>>PGSHIFT); 
1990/0802    
		poperror(); 
1990/03091    
		/* stacks grown down, sigh */ 
1990/0814    
		lock(o); 
1990/03091    
		memcpy(o->pte+(o->npte-n), o->pte, n*sizeof(PTE)); 
		memset(o->pte, 0, (o->npte-n)*sizeof(PTE)); 
		unlock(o); 
1990/0814/sys/src/9/gnot/fault.c:104,1101990/0821/sys/src/9/gnot/fault.c:104,110 (short | long)
1990/03091    
			exit(); 
		} 
		s = &u->p->seg[SSEG]; 
		if(s->o==0 || addr<s->maxva-4*1024*1024 || addr>=s->maxva) 
1990/0821    
		if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva) 
1990/03091    
			goto cant; 
		/* grow stack */ 
		o = s->o; 
1990/0814/sys/src/9/gnot/fault.c:296,3031990/0821/sys/src/9/gnot/fault.c:296,306
1990/03091    
	} 
1990/0617    
    Again: 
	s = seg(u->p, addr); 
	if(s==0) 
		goto Err; 
1990/0821    
	if(s==0){ 
		s = &u->p->seg[SSEG]; 
		if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva) 
			goto Err; 
	} 
1990/0617    
	if(write && (s->o->flag&OWRPERM)==0) 
		goto Err; 
	if(addr+len > s->maxva){ 
1990/0821/sys/src/9/gnot/fault.c:173,1791990/0918/sys/src/9/gnot/fault.c:173,178 (short | long)
1990/03091    
			if((*devtab[o->chan->type].read)(o->chan, l, n) != n) 
				error(0, Eioload); 
			qunlock(o->chan); 
			/* BUG: if was first page of bss, move to data */ 
			if(n<BY2PG) 
				memset(l+n, 0, BY2PG-n); 
			lock(o); 
1990/0918/sys/src/9/gnot/fault.c:166,1711990/1110/sys/src/9/gnot/fault.c:166,173 (short | long)
1990/03091    
				qunlock(o->chan); 
				pg->o = 0; 
				pg->ref--; 
1990/1110    
				if(user) 
					pexit("Interrupt", 0); 
1990/03091    
				goto cant; 
			} 
			o->chan->offset = (addr-o->va) + o->minca; 
1990/0918/sys/src/9/gnot/fault.c:290,2961990/1110/sys/src/9/gnot/fault.c:292,298
1990/0617    
	if((long)len < 0){ 
1990/0312    
    Err: 
1990/03091    
		pprint("invalid address in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); 
		postnote(u->p, 1, "bad address", NDebug); 
1990/1110    
		postnote(u->p, 1, "sys: bad address", NDebug); 
1990/03091    
		error(0, Ebadarg); 
	} 
1990/0617    
    Again: 
1990/1110/sys/src/9/gnot/fault.c:166,1741990/1113/sys/src/9/gnot/fault.c:166,172 (short | long)
1990/03091    
				qunlock(o->chan); 
				pg->o = 0; 
				pg->ref--; 
1990/1110    
				if(user) 
					pexit("Interrupt", 0); 
1990/03091    
				goto cant; 
1990/1113    
				pexit("load i/o error", 0); 
1990/03091    
			} 
			o->chan->offset = (addr-o->va) + o->minca; 
1990/0614    
			l = (char*)VA(k); 
1990/1113/sys/src/9/gnot/fault.c:161,1671990/11211/sys/src/9/gnot/fault.c:161,167 (short | long)
1990/06021    
			k = kmap(pg); 
1990/03091    
			qlock(o->chan); 
			if(waserror()){ 
				print("demand load i/o error %d\n", u->error.code); 
1990/11211    
				print("demand load i/o error %s\n", u->error); 
1990/06021    
				kunmap(k); 
1990/03091    
				qunlock(o->chan); 
				pg->o = 0; 
1990/1113/sys/src/9/gnot/fault.c:171,1771990/11211/sys/src/9/gnot/fault.c:171,177
1990/03091    
			o->chan->offset = (addr-o->va) + o->minca; 
1990/0614    
			l = (char*)VA(k); 
1990/03091    
			if((*devtab[o->chan->type].read)(o->chan, l, n) != n) 
				error(0, Eioload); 
1990/11211    
				error(Eioload); 
1990/03091    
			qunlock(o->chan); 
			if(n<BY2PG) 
				memset(l+n, 0, BY2PG-n); 
1990/1113/sys/src/9/gnot/fault.c:291,2971990/11211/sys/src/9/gnot/fault.c:291,297
1990/0312    
    Err: 
1990/03091    
		pprint("invalid address in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); 
1990/1110    
		postnote(u->p, 1, "sys: bad address", NDebug); 
1990/03091    
		error(0, Ebadarg); 
1990/11211    
		error(Ebadarg); 
1990/03091    
	} 
1990/0617    
    Again: 
	s = seg(u->p, addr); 
1990/11211/sys/src/9/gnot/fault.c:61,661990/1126/sys/src/9/gnot/fault.c:61,67 (short | long)
1990/0603    
	} 
1990/03091    
	insyscall = u->p->insyscall; 
	u->p->insyscall = 1; 
1990/1126    
	addr = 0;	/* set */ 
1990/03091    
	if(f->ssw & DF) 
		addr = f->addr; 
	else if(FORMAT(ur) == 0xA){ 
1990/1126/sys/src/9/gnot/fault.c:162,1681990/1202/sys/src/9/gnot/fault.c:162,167 (short | long)
1990/06021    
			k = kmap(pg); 
1990/03091    
			qlock(o->chan); 
			if(waserror()){ 
1990/11211    
				print("demand load i/o error %s\n", u->error); 
1990/06021    
				kunmap(k); 
1990/03091    
				qunlock(o->chan); 
				pg->o = 0; 
1990/1202/sys/src/9/gnot/fault.c:1,3471990/1212/sys/src/9/gnot/fault.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:21:44 2005
1990/03091    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"ureg.h" 
#include	"errno.h" 
                 
#define	FORMAT(ur)	((((ur)->vo)>>12)&0xF) 
#define	OFFSET(ur)	(((ur)->vo)&0xFFF) 
                 
                 
struct FFrame 
{ 
	ushort	ireg0;			/* internal register */ 
	ushort	ssw;			/* special status word */ 
	ushort	ipsc;			/* instr. pipe stage c */ 
	ushort	ipsb;			/* instr. pipe stage b */ 
	ulong	addr;			/* data cycle fault address */ 
	ushort	ireg1;			/* internal register */ 
	ushort	ireg2;			/* internal register */ 
	ulong	dob;			/* data output buffer */ 
	ushort	ireg3[4];		/* more stuff */ 
	ulong	baddr;			/* stage b address */ 
	ushort	ireg4[26];		/* more more stuff */ 
}; 
                 
/* 
 * SSW bits 
 */ 
#define	RW	0x0040		/* read/write for data cycle */ 
#define	FC	0x8000		/* fault on stage C of instruction pipe */ 
#define	FB	0x4000		/* fault on stage B of instruction pipe */ 
#define	RC	0x2000		/* rerun flag for stage C of instruction pipe */ 
#define	RB	0x1000		/* rerun flag for stage B of instruction pipe */ 
#define	DF	0x0100		/* fault/rerun flag for data cycle */ 
#define	RM	0x0080		/* read-modify-write on data cycle */ 
#define	READ	0x0040 
#define	WRITE	0x0000 
#define	SIZ	0x0030		/* size code for data cycle */ 
#define	FC2	0x0004		/* address space for data cycle */ 
#define	FC1	0x0002 
#define	FC0	0x0001 
                 
void 
fault(Ureg *ur, FFrame *f) 
{ 
	ulong addr, mmuvirt, mmuphys, n, badvaddr; 
	Seg *s; 
	PTE *opte, *pte, *npte; 
	Orig *o; 
	char *l; 
	Page *pg; 
1990/06021    
	KMap *k, *k1; 
1990/03091    
	int zeroed = 0, head = 1; 
	int i, user, read, insyscall; 
                 
1990/0603    
	if(u == 0){ 
		dumpregs(ur); 
1990/06021    
		panic("fault u==0 pc=%lux", ur->pc); 
1990/0603    
	} 
1990/03091    
	insyscall = u->p->insyscall; 
	u->p->insyscall = 1; 
1990/1126    
	addr = 0;	/* set */ 
1990/03091    
	if(f->ssw & DF) 
		addr = f->addr; 
	else if(FORMAT(ur) == 0xA){ 
		if(f->ssw & FC) 
			addr = ur->pc+2; 
		else if(f->ssw & FB) 
			addr = ur->pc+4; 
		else 
			panic("prefetch pagefault"); 
	}else if(FORMAT(ur) == 0xB){ 
		if(f->ssw & FC) 
			addr = f->baddr-2; 
		else if(f->ssw & FB) 
			addr = f->baddr; 
		else 
			panic("prefetch pagefault"); 
	}else 
		panic("prefetch format"); 
1990/08101    
	addr &= VAMASK; 
1990/03091    
	badvaddr = addr; 
	addr &= ~(BY2PG-1); 
	user = !(ur->sr&SUPER); 
	if(f->ssw & DF) 
		read = (f->ssw&READ) && !(f->ssw&RM); 
	else 
		read = f->ssw&(FB|FC); 
1990/0312    
/* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/ 
1990/03091    
                 
	s = seg(u->p, addr); 
	if(s == 0){ 
		if(addr>USTKTOP){ 
	    cant: 
			if(user){ 
				pprint("user %s error addr=0x%lux\n", read? "read" : "write", badvaddr); 
				pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->sr, ur->pc, ur->sp); 
				pexit("Suicide", 0); 
			} 
1990/0315    
			u->p->state = MMUing; 
1990/03091    
			dumpregs(ur); 
1990/08101    
			panic("fault: 0x%lux", badvaddr); 
1990/03091    
			exit(); 
		} 
		s = &u->p->seg[SSEG]; 
1990/0821    
		if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva) 
1990/03091    
			goto cant; 
		/* grow stack */ 
		o = s->o; 
		n = o->npte; 
1990/0802    
		if(waserror()){ 
			pprint("can't allocate stack page\n"); 
			goto cant; 
		} 
1990/03091    
		growpte(o, (s->maxva-addr)>>PGSHIFT); 
1990/0802    
		poperror(); 
1990/03091    
		/* stacks grown down, sigh */ 
1990/0814    
		lock(o); 
1990/03091    
		memcpy(o->pte+(o->npte-n), o->pte, n*sizeof(PTE)); 
		memset(o->pte, 0, (o->npte-n)*sizeof(PTE)); 
		unlock(o); 
		s->minva = addr; 
		o->va = addr; 
	}else 
		o = s->o; 
	if(!read && (o->flag&OWRPERM)==0) 
		goto cant; 
	lock(o); 
	opte = &o->pte[(addr-o->va)>>PGSHIFT]; 
	pte = opte; 
	if(s->mod){ 
		while(pte = pte->nextmod)	/* assign = */ 
			if(pte->proc == u->p){ 
				if(pte->page==0 || pte->page->va!=addr) 
					panic("bad page %lux", pte->page); 
				head = 0; 
				break; 
			} 
		if(pte == 0) 
			pte = opte; 
	} 
	if(pte->page == 0){ 
		if(o->chan==0 || addr>(o->va+(o->maxca-o->minca))){ 
			/* 
			 * Zero fill page.  If we are really doing a copy-on-write 
			 * (e.g. into shared bss) we'll move the page later. 
			 */ 
			pte->page = newpage(0, o, addr); 
			o->npage++; 
			zeroed = 1; 
		}else{ 
			/* 
			 * Demand load.  Release o because it could take a while. 
			 */ 
			unlock(o); 
			n = (o->va+(o->maxca-o->minca)) - addr; 
			if(n > BY2PG) 
				n = BY2PG; 
			pg = newpage(1, o, addr); 
1990/06021    
			k = kmap(pg); 
1990/03091    
			qlock(o->chan); 
			if(waserror()){ 
1990/06021    
				kunmap(k); 
1990/03091    
				qunlock(o->chan); 
				pg->o = 0; 
				pg->ref--; 
1990/1113    
				pexit("load i/o error", 0); 
1990/03091    
			} 
			o->chan->offset = (addr-o->va) + o->minca; 
1990/0614    
			l = (char*)VA(k); 
1990/03091    
			if((*devtab[o->chan->type].read)(o->chan, l, n) != n) 
1990/11211    
				error(Eioload); 
1990/03091    
			qunlock(o->chan); 
			if(n<BY2PG) 
				memset(l+n, 0, BY2PG-n); 
			lock(o); 
1990/06021    
			kunmap(k); 
			poperror(); 
1990/03091    
			opte = &o->pte[(addr-s->minva)>>PGSHIFT];	/* could move */ 
			pte = opte; 
			if(pte->page == 0){ 
				pte->page = pg; 
				o->npage++; 
			}else{		/* someone beat us to it */ 
				pg->o = 0; 
				pg->ref--; 
			} 
		} 
	} 
	/* 
1990/0724    
	 * Copy on write 
1990/03091    
	 */ 
1990/0724    
	if((o->flag & OWRPERM) && !read 
1990/03091    
	&& ((head && ((o->flag&OPURE) || o->nproc>1)) 
	    || (!head && pte->page->ref>1))){ 
                 
		/* 
		 * Look for the easy way out: are we the last non-modified? 
		 */ 
		if(head && !(o->flag&OPURE)){ 
			npte = opte; 
			for(i=0; npte; i++) 
				npte = npte->nextmod; 
			if(i == o->nproc) 
				goto easy; 
		} 
		if(head){ 
			/* 
			 * Add to mod list 
			 */ 
			pte = newmod(); 
			pte->proc = u->p; 
			pte->page = opte->page; 
			pte->page->ref++; 
			o->npage++; 
			/* 
			 * Link into opte mod list (same va) 
			 */ 
			pte->nextmod = opte->nextmod; 
			opte->nextmod = pte; 
			/* 
			 * Link into proc mod list (increasing va) 
			 */ 
			npte = s->mod; 
			if(npte == 0){ 
				s->mod = pte; 
				pte->nextva = 0; 
			}else{ 
				while(npte->nextva && npte->nextva->page->va<addr) 
					npte = npte->nextva; 
				pte->nextva = npte->nextva; 
				npte->nextva = pte; 
			} 
			head = 0; 
		} 
		pg = pte->page; 
		if(zeroed){	/* move page */ 
			pg->ref--; 
			o->npage--; 
			opte->page = 0; 
		}else{		/* copy page */ 
			pte->page = newpage(1, o, addr); 
1990/06021    
			k = kmap(pte->page); 
			k1 = kmap(pg); 
1990/0614    
			memcpy((void*)VA(k), (void*)VA(k1), BY2PG); 
1990/06021    
			kunmap(k); 
			kunmap(k1); 
1990/03091    
			if(pg->ref <= 1) 
				panic("pg->ref <= 1"); 
			pg->ref--; 
		} 
    easy: 
		mmuphys = 0; 
	}else{ 
		mmuphys = PTERONLY; 
		if(o->flag & OWRPERM) 
			if(o->flag & OPURE){ 
				if(!head && pte->page->ref==1) 
					mmuphys = 0; 
			}else 
				if((head && o->nproc==1) 
	  			  || (!head && pte->page->ref==1)) 
					mmuphys = 0; 
	} 
	mmuvirt = addr; 
	mmuphys |= PPN(pte->page->pa) | PTEVALID; 
	usepage(pte->page, 1); 
	if(pte->page->va != addr) 
		panic("wrong addr in tail %lux %lux", pte->page->va, addr); 
	if(pte->proc && pte->proc != u->p){ 
		print("wrong proc in tail %d %s\n", head, u->p->text); 
		print("u->p %lux pte->proc %lux\n", u->p, pte->proc); 
		panic("addr %lux seg %d wrong proc in tail", addr, s-u->p->seg); 
	} 
	unlock(o); 
	putmmu(mmuvirt, mmuphys); 
	u->p->insyscall = insyscall; 
} 
                 
/* 
 * Called only in a system call 
 */ 
void 
validaddr(ulong addr, ulong len, int write) 
{ 
1990/0617    
	Seg *s, *ns; 
1990/03091    
                 
1990/0617    
	if((long)len < 0){ 
1990/0312    
    Err: 
1990/03091    
		pprint("invalid address in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); 
1990/1110    
		postnote(u->p, 1, "sys: bad address", NDebug); 
1990/11211    
		error(Ebadarg); 
1990/03091    
	} 
1990/0617    
    Again: 
	s = seg(u->p, addr); 
1990/0821    
	if(s==0){ 
		s = &u->p->seg[SSEG]; 
		if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva) 
			goto Err; 
	} 
1990/0617    
	if(write && (s->o->flag&OWRPERM)==0) 
		goto Err; 
	if(addr+len > s->maxva){ 
		len -= s->maxva - addr; 
		addr = s->maxva; 
		goto Again; 
	} 
1990/03091    
} 
/* 
 * &s[0] is known to be a valid address. 
 */ 
void* 
vmemchr(void *s, int c, int n) 
{ 
	int m; 
	char *t; 
	ulong a; 
                 
	a = (ulong)s; 
	m = BY2PG - (a & (BY2PG-1)); 
	if(m < n){ 
		t = vmemchr(s, c, m); 
		if(t) 
			return t; 
		if(!(a & KZERO)) 
			validaddr(a+m, 1, 0); 
		return vmemchr((void*)(a+m), c, n-m); 
	} 
	/* 
	 * All in one page 
	 */ 
	return memchr(s, c, n); 
} 
                 
Seg* 
seg(Proc *p, ulong addr) 
{ 
	int i; 
	Seg *s; 
                 
	for(i=0,s=p->seg; i<NSEG; i++,s++) 
		if(s->o && s->minva<=addr && addr<s->maxva) 
			return s; 
	return 0; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)