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

1990/1212/port/fault.c (diff list | history)

1990/1202/sys/src/9/port/fault.c:6,161990/1212/sys/src/9/port/fault.c:6,15 (short | long | prev | next)
Created.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
#include	"ureg.h" 
#include	"errno.h" 
 
void 
fault(Ureg *ur, int user, int code) 
1990/1212    
int 
fault(ulong addr, int read) 
1990/0227    
{ 
	ulong addr, mmuvirt, mmuphys, n; 
	extern char *excname[]; 
1990/1212    
	ulong mmuvirt, mmuphys, n; 
1990/0227    
	Seg *s; 
	PTE *opte, *pte, *npte; 
	Orig *o; 
1990/1202/sys/src/9/port/fault.c:18,511990/1212/sys/src/9/port/fault.c:17,37
1990/0227    
	Page *pg; 
	int zeroed = 0, head = 1; 
	int i; 
1990/1212    
	KMap *k, *k1; 
1990/0227    
 
	addr = ur->badvaddr; 
	addr &= ~(BY2PG-1); 
                 
	s = seg(u->p, addr); 
	if(s == 0){ 
		if(addr>USTKTOP){ 
	    cant: 
			if(user){ 
				pprint("user %s badvaddr=0x%lux\n", excname[code], ur->badvaddr); 
				pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp); 
				pexit("Suicide", 0); 
			} 
			print("kernel %s badvaddr=0x%lux\n", excname[code], ur->badvaddr); 
			print("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp); 
			u->p->state = MMUing; 
			dumpregs(ur); 
			panic("fault"); 
		} 
1990/1212    
		if(addr>USTKTOP) 
			return -1; 
1990/0227    
		s = &u->p->seg[SSEG]; 
1990/0821    
		if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva) 
1990/0227    
			goto cant; 
1990/1212    
			return -1; 
1990/0227    
		/* grow stack */ 
		o = s->o; 
		n = o->npte; 
1990/0802    
		if(waserror()){ 
			pprint("can't allocate stack page\n"); 
			goto cant; 
1990/1212    
			return -1; 
1990/0802    
		} 
1990/0227    
		growpte(o, (s->maxva-addr)>>PGSHIFT); 
1990/0802    
		poperror(); 
1990/1202/sys/src/9/port/fault.c:58,651990/1212/sys/src/9/port/fault.c:44,51
1990/0227    
		o->va = addr; 
	}else 
		o = s->o; 
	if((code==CTLBM || code==CTLBS) && (o->flag&OWRPERM)==0) 
		goto cant; 
1990/1212    
	if(!read && (o->flag&OWRPERM)==0) 
		return -1; 
1990/0227    
	lock(o); 
	opte = &o->pte[(addr-o->va)>>PGSHIFT]; 
	pte = opte; 
1990/1202/sys/src/9/port/fault.c:92,991990/1212/sys/src/9/port/fault.c:78,87
1990/0227    
			if(n > BY2PG) 
				n = BY2PG; 
			pg = newpage(1, o, addr); 
1990/1212    
			k = kmap(pg); 
1990/0227    
			qlock(o->chan); 
			if(waserror()){ 
1990/1212    
				kunmap(k); 
1990/0227    
				qunlock(o->chan); 
				pg->o = 0; 
				pg->ref--; 
1990/1202/sys/src/9/port/fault.c:100,1141990/1212/sys/src/9/port/fault.c:88,102
1990/1113    
				pexit("load i/o error", 0); 
1990/0227    
			} 
			o->chan->offset = (addr-o->va) + o->minca; 
			l = (char*)(pg->pa|KZERO); 
1990/1212    
			l = (char*)VA(k); 
1990/0227    
			if((*devtab[o->chan->type].read)(o->chan, l, n) != n) 
1990/11211    
				error(Eioload); 
1990/0227    
			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/1212    
			kunmap(k); 
			poperror(); 
1990/0227    
			opte = &o->pte[(addr-s->minva)>>PGSHIFT];	/* could move */ 
			pte = opte; 
			if(pte->page == 0){ 
1990/1202/sys/src/9/port/fault.c:121,1291990/1212/sys/src/9/port/fault.c:109,117
1990/0227    
		} 
	} 
	/* 
	 * Copy on reference 
1990/1212    
	 * Copy on reference (conf.copymode==1) or write (conf.copymode==0) 
1990/0227    
	 */ 
	if((o->flag & OWRPERM) 
1990/1212    
	if((o->flag & OWRPERM) && (conf.copymode || !read) 
1990/0227    
	&& ((head && ((o->flag&OPURE) || o->nproc>1)) 
	    || (!head && pte->page->ref>1))){ 
 
1990/1202/sys/src/9/port/fault.c:173,1791990/1212/sys/src/9/port/fault.c:161,171
1990/0227    
			opte->page = 0; 
		}else{		/* copy page */ 
			pte->page = newpage(1, o, addr); 
			memcpy((void*)(pte->page->pa|KZERO), (void*)(pg->pa|KZERO), BY2PG); 
1990/1212    
			k = kmap(pte->page); 
			k1 = kmap(pg); 
			memcpy((void*)VA(k), (void*)VA(k1), BY2PG); 
			kunmap(k); 
			kunmap(k1); 
1990/0227    
			if(pg->ref <= 1) 
				panic("pg->ref <= 1"); 
			pg->ref--; 
1990/1202/sys/src/9/port/fault.c:181,1871990/1212/sys/src/9/port/fault.c:173,179
1990/0227    
    easy: 
		mmuphys = PTEWRITE; 
	}else{ 
		mmuphys = 0; 
1990/1212    
		mmuphys = PTERONLY; 
1990/0227    
		if(o->flag & OWRPERM) 
			if(o->flag & OPURE){ 
				if(!head && pte->page->ref==1) 
1990/1202/sys/src/9/port/fault.c:192,1981990/1212/sys/src/9/port/fault.c:184,190
1990/0227    
					mmuphys = PTEWRITE; 
	} 
	mmuvirt = addr; 
	mmuphys |= pte->page->pa | PTEVALID; 
1990/1212    
	mmuphys |= PPN(pte->page->pa) | PTEVALID; 
1990/0227    
	usepage(pte->page, 1); 
	if(pte->page->va != addr) 
		panic("wrong addr in tail %lux %lux", pte->page->va, addr); 
1990/1202/sys/src/9/port/fault.c:203,2081990/1212/sys/src/9/port/fault.c:195,201
1990/0227    
	} 
	unlock(o); 
	putmmu(mmuvirt, mmuphys); 
1990/1212    
	return 0; 
1990/0227    
} 
 
/* 
1990/1202/sys/src/9/port/fault.c:232,2461990/1212/sys/src/9/port/fault.c:225,230
1990/0617    
		len -= s->maxva - addr; 
		addr = s->maxva; 
		goto Again; 
1990/0227    
	} 
} 
                 
void 
evenaddr(ulong addr) 
{ 
	if(addr & 3){ 
1990/1110    
		postnote(u->p, 1, "sys: odd address", NDebug); 
1990/11211    
		error(Ebadarg); 
1990/0227    
	} 
} 
 


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