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

1993/0812/power/mmu.c (diff list | history)

power/mmu.c on 1990/0227
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
 
void 
1993/0501    
mmuswitch(Proc *p) 
1990/0227    
{ 
1991/0705    
	if(p->newtlb) { 
		memset(p->pidonmach, 0, sizeof p->pidonmach); 
		p->newtlb = 0; 
	} 
1993/0501    
	if(p->pidonmach[m->machno] == 0) 
		newtlbpid(p); 
1991/0705    
 
1993/0501    
	putcontext(p->pidonmach[m->machno]); 
1990/0227    
} 
 
1991/0507    
void 
mmurelease(Proc *p) 
{ 
	memset(p->pidonmach, 0, sizeof p->pidonmach); 
} 
 
1990/0227    
/* 
 * Process must be non-interruptible 
 */ 
int 
newtlbpid(Proc *p) 
{ 
1991/0425    
	int i, s; 
1990/0227    
	Proc *sp; 
1991/0425    
	char *h; 
1991/0426    
 
1991/0425    
	s = m->lastpid; 
	if(s >= NTLBPID) 
		s = 1; 
	i = s; 
1991/0501    
	h = m->pidhere; 
	do{ 
		i++; 
		if(i >= NTLBPID) 
			i = 1; 
	}while(h[i] && i != s); 
 
1991/0425    
	if(i == s){ 
1991/0426    
		i++; 
		if(i >= NTLBPID) 
			i = 1; 
1991/0425    
	} 
1991/0501    
	if(h[i]) 
		purgetlb(i); 
1992/1130    
 
1990/0227    
	sp = m->pidproc[i]; 
1991/0501    
	if(sp && sp->pidonmach[m->machno] == i) 
		sp->pidonmach[m->machno] = 0; 
1991/0430    
	m->pidproc[i] = p; 
	p->pidonmach[m->machno] = i; 
1991/0501    
	m->lastpid = i; 
1990/0227    
	return i; 
} 
 
void 
1991/0705    
putmmu(ulong tlbvirt, ulong tlbphys, Page *pg) 
1990/0227    
{ 
	short tp; 
1991/0705    
	char *ctl; 
1990/0227    
 
	splhi(); 
1991/0705    
 
	ctl = &pg->cachectl[m->machno];  
1993/0812    
	if(*ctl == PG_TXTFLUSH) { 
1991/0705    
		dcflush((void*)pg->pa, BY2PG); 
		icflush((void*)pg->pa, BY2PG); 
1993/0806    
		*ctl &= ~PG_TXTFLUSH; 
1991/0705    
	} 
 
1993/0501    
	tp = up->pidonmach[m->machno]; 
1991/0430    
	if(tp == 0) 
1993/0501    
		tp = newtlbpid(up); 
1992/1130    
 
1990/0227    
	tlbvirt |= PTEPID(tp); 
1991/0425    
	putstlb(tlbvirt, tlbphys); 
1990/0227    
	puttlb(tlbvirt, tlbphys); 
	m->pidhere[tp] = 1; 
	spllo(); 
} 
 
void 
purgetlb(int pid) 
{ 
1991/0425    
	Softtlb *entry, *etab; 
1991/0501    
	char *pidhere; 
1991/0430    
	Proc *sp, **pidproc; 
	int i, rpid, mno; 
1991/0501    
	char dead[NTLBPID]; 
1990/0227    
 
1991/0425    
	m->tlbpurge++; 
1991/0501    
	/* 
	 * find all pid entries that are no longer used by processes 
	 */ 
	mno = m->machno; 
	pidproc = m->pidproc; 
	memset(dead, 0, sizeof dead); 
	for(i=1; i<NTLBPID; i++){ 
		sp = pidproc[i]; 
		if(!sp || sp->pidonmach[mno] != i){ 
			pidproc[i] = 0; 
			dead[i] = 1; 
		} 
	} 
	dead[pid] = 1; 
	/* 
	 * clean out all dead pids from the stlb; 
1992/1130    
	 * garbage collect pids with no entries 
1991/0501    
	 */ 
1991/0426    
	memset(m->pidhere, 0, sizeof m->pidhere); 
1991/0501    
	pidhere = m->pidhere; 
1991/0425    
	entry = m->stb; 
	etab = &entry[STLBSIZE]; 
	for(; entry < etab; entry++){ 
		rpid = TLBPID(entry->virt); 
1991/0501    
		if(dead[rpid]) 
1991/0425    
			entry->virt = 0; 
1991/0501    
		else 
			pidhere[rpid] = 1; 
1990/0227    
	} 
1991/0501    
	/* 
	 * clean up the hardware 
	 */ 
1991/0430    
	for(i=TLBROFF; i<NTLB; i++) 
1991/0501    
		if(!pidhere[TLBPID(gettlbvirt(i))]) 
1991/0430    
			puttlbx(i, KZERO | PTEPID(i), 0); 
1990/0227    
} 
 
void 
flushmmu(void) 
{ 
	splhi(); 
1993/0501    
	up->newtlb = 1; 
	mmuswitch(up); 
1990/0227    
	spllo(); 
} 
1990/1211    
 
void 
clearmmucache(void) 
{ 
1991/0425    
} 
 
void 
putstlb(ulong tlbvirt, ulong tlbphys) 
{ 
	Softtlb *entry; 
 
1992/1130    
	/* This hash function is also coded into utlbmiss in l.s */ 
1991/0425    
	entry = &m->stb[((tlbvirt<<1) ^ (tlbvirt>>12)) & (STLBSIZE-1)]; 
	entry->phys = tlbphys; 
	entry->virt = tlbvirt; 
	if(tlbphys == 0) 
		entry->virt = 0; 
1990/1211    
} 


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