xref: /plan9-contrib/sys/src/9/loongson/mmu.c (revision a81c3ea0c7f009a3088ab7fe55ea9013d9d77a74)
1*a81c3ea0SDavid du Colombier #include "u.h"
2*a81c3ea0SDavid du Colombier #include "../port/lib.h"
3*a81c3ea0SDavid du Colombier #include "mem.h"
4*a81c3ea0SDavid du Colombier #include "dat.h"
5*a81c3ea0SDavid du Colombier #include "fns.h"
6*a81c3ea0SDavid du Colombier #include "ureg.h"
7*a81c3ea0SDavid du Colombier 
8*a81c3ea0SDavid du Colombier #define TLBINVAL(x, pid)	puttlbx(x, KZERO|((x)<<(PGSHIFT+1))|(pid), 0, 0, PGSZ)
9*a81c3ea0SDavid du Colombier 
10*a81c3ea0SDavid du Colombier enum {
11*a81c3ea0SDavid du Colombier 	Debugswitch	= 0,
12*a81c3ea0SDavid du Colombier 	Debughash	= 0,
13*a81c3ea0SDavid du Colombier };
14*a81c3ea0SDavid du Colombier 
15*a81c3ea0SDavid du Colombier static ulong ktime[8];		/* only for first 8 cpus */
16*a81c3ea0SDavid du Colombier 
17*a81c3ea0SDavid du Colombier void
tlbinit(void)18*a81c3ea0SDavid du Colombier tlbinit(void)
19*a81c3ea0SDavid du Colombier {
20*a81c3ea0SDavid du Colombier 	int i;
21*a81c3ea0SDavid du Colombier 
22*a81c3ea0SDavid du Colombier 	for(i=0; i<NTLB; i++)
23*a81c3ea0SDavid du Colombier 		TLBINVAL(i, 0);
24*a81c3ea0SDavid du Colombier }
25*a81c3ea0SDavid du Colombier 
26*a81c3ea0SDavid du Colombier Lock	kmaplock;
27*a81c3ea0SDavid du Colombier KMap	kpte[KPTESIZE];
28*a81c3ea0SDavid du Colombier KMap*	kmapfree;
29*a81c3ea0SDavid du Colombier 
30*a81c3ea0SDavid du Colombier static int minfree = KPTESIZE;
31*a81c3ea0SDavid du Colombier static int lastfree;
32*a81c3ea0SDavid du Colombier static int tlbroff = TLBROFF;
33*a81c3ea0SDavid du Colombier 
34*a81c3ea0SDavid du Colombier void
kmapinit(void)35*a81c3ea0SDavid du Colombier kmapinit(void)
36*a81c3ea0SDavid du Colombier {
37*a81c3ea0SDavid du Colombier 	KMap *k, *klast;
38*a81c3ea0SDavid du Colombier 
39*a81c3ea0SDavid du Colombier 	lock(&kmaplock);
40*a81c3ea0SDavid du Colombier 	kmapfree = kpte;
41*a81c3ea0SDavid du Colombier 	klast = &kpte[KPTESIZE-1];
42*a81c3ea0SDavid du Colombier 	for(k=kpte; k<klast; k++)
43*a81c3ea0SDavid du Colombier 		k->next = k+1;
44*a81c3ea0SDavid du Colombier 	k->next = 0;
45*a81c3ea0SDavid du Colombier 	unlock(&kmaplock);
46*a81c3ea0SDavid du Colombier 
47*a81c3ea0SDavid du Colombier 	m->ktlbnext = KTLBOFF;
48*a81c3ea0SDavid du Colombier }
49*a81c3ea0SDavid du Colombier 
50*a81c3ea0SDavid du Colombier void
kmapinval(void)51*a81c3ea0SDavid du Colombier kmapinval(void)
52*a81c3ea0SDavid du Colombier {
53*a81c3ea0SDavid du Colombier 	int mno, i, curpid;
54*a81c3ea0SDavid du Colombier 	KMap *k, *next;
55*a81c3ea0SDavid du Colombier 	uchar *ktlbx;
56*a81c3ea0SDavid du Colombier 
57*a81c3ea0SDavid du Colombier 	if(m->machno < nelem(ktime))
58*a81c3ea0SDavid du Colombier 		ktime[m->machno] = MACHP(0)->ticks;
59*a81c3ea0SDavid du Colombier 	if(m->kactive == 0)
60*a81c3ea0SDavid du Colombier 		return;
61*a81c3ea0SDavid du Colombier 
62*a81c3ea0SDavid du Colombier 	curpid = PTEPID(TLBPID(tlbvirt()));
63*a81c3ea0SDavid du Colombier 	ktlbx = m->ktlbx;
64*a81c3ea0SDavid du Colombier 	for(i = 0; i < NTLB; i++, ktlbx++){
65*a81c3ea0SDavid du Colombier 		if(*ktlbx == 0)
66*a81c3ea0SDavid du Colombier 			continue;
67*a81c3ea0SDavid du Colombier 		TLBINVAL(i, curpid);
68*a81c3ea0SDavid du Colombier 		*ktlbx = 0;
69*a81c3ea0SDavid du Colombier 	}
70*a81c3ea0SDavid du Colombier 
71*a81c3ea0SDavid du Colombier 	mno = m->machno;
72*a81c3ea0SDavid du Colombier 	for(k = m->kactive; k; k = next) {
73*a81c3ea0SDavid du Colombier 		next = k->konmach[mno];
74*a81c3ea0SDavid du Colombier 		kunmap(k);
75*a81c3ea0SDavid du Colombier 	}
76*a81c3ea0SDavid du Colombier 
77*a81c3ea0SDavid du Colombier 	m->kactive = 0;
78*a81c3ea0SDavid du Colombier 	m->ktlbnext = KTLBOFF;
79*a81c3ea0SDavid du Colombier }
80*a81c3ea0SDavid du Colombier 
81*a81c3ea0SDavid du Colombier static int
putktlb(KMap * k)82*a81c3ea0SDavid du Colombier putktlb(KMap *k)
83*a81c3ea0SDavid du Colombier {
84*a81c3ea0SDavid du Colombier 	int x;
85*a81c3ea0SDavid du Colombier 	ulong virt;
86*a81c3ea0SDavid du Colombier 	ulong tlbent[3];
87*a81c3ea0SDavid du Colombier 
88*a81c3ea0SDavid du Colombier 	virt = k->virt & ~BY2PG | TLBPID(tlbvirt());
89*a81c3ea0SDavid du Colombier 	x = gettlbp(virt, tlbent);
90*a81c3ea0SDavid du Colombier 	if (!m->paststartup)
91*a81c3ea0SDavid du Colombier 		if (up) {			/* startup just ended? */
92*a81c3ea0SDavid du Colombier 			tlbroff = KTLBOFF;
93*a81c3ea0SDavid du Colombier 			setwired(tlbroff);
94*a81c3ea0SDavid du Colombier 			m->paststartup = 1;
95*a81c3ea0SDavid du Colombier 		} else if (x < 0) {		/* no such entry? use next */
96*a81c3ea0SDavid du Colombier 			x = m->ktlbnext++;
97*a81c3ea0SDavid du Colombier 			if(m->ktlbnext >= tlbroff)
98*a81c3ea0SDavid du Colombier 				m->ktlbnext = KTLBOFF;
99*a81c3ea0SDavid du Colombier 		}
100*a81c3ea0SDavid du Colombier 	if (x < 0)		/* no entry for va? overwrite random one */
101*a81c3ea0SDavid du Colombier 		x = puttlb(virt, k->phys0, k->phys1);
102*a81c3ea0SDavid du Colombier 	else
103*a81c3ea0SDavid du Colombier 		puttlbx(x, virt, k->phys0, k->phys1, PGSZ);
104*a81c3ea0SDavid du Colombier 	m->ktlbx[x] = 1;
105*a81c3ea0SDavid du Colombier 	return x;
106*a81c3ea0SDavid du Colombier }
107*a81c3ea0SDavid du Colombier 
108*a81c3ea0SDavid du Colombier /*
109*a81c3ea0SDavid du Colombier  *  Arrange that the KMap'd virtual address will hit the same
110*a81c3ea0SDavid du Colombier  *  primary cache line as pg->va by making bits 14...12 of the
111*a81c3ea0SDavid du Colombier  *  tag the same as virtual address.  These bits are the index
112*a81c3ea0SDavid du Colombier  *  into the primary cache and are checked whenever accessing
113*a81c3ea0SDavid du Colombier  *  the secondary cache through the primary.  Violation causes
114*a81c3ea0SDavid du Colombier  *  a VCE trap.
115*a81c3ea0SDavid du Colombier  */
116*a81c3ea0SDavid du Colombier KMap *
kmap(Page * pg)117*a81c3ea0SDavid du Colombier kmap(Page *pg)
118*a81c3ea0SDavid du Colombier {
119*a81c3ea0SDavid du Colombier 	int s, printed = 0;
120*a81c3ea0SDavid du Colombier 	ulong pte, virt;
121*a81c3ea0SDavid du Colombier 	KMap *k;
122*a81c3ea0SDavid du Colombier 
123*a81c3ea0SDavid du Colombier 	s = splhi();
124*a81c3ea0SDavid du Colombier 	lock(&kmaplock);
125*a81c3ea0SDavid du Colombier 
126*a81c3ea0SDavid du Colombier 	if(kmapfree == 0) {
127*a81c3ea0SDavid du Colombier retry:
128*a81c3ea0SDavid du Colombier 		unlock(&kmaplock);
129*a81c3ea0SDavid du Colombier 		kmapinval();		/* try and free some */
130*a81c3ea0SDavid du Colombier 		lock(&kmaplock);
131*a81c3ea0SDavid du Colombier 		if(kmapfree == 0){
132*a81c3ea0SDavid du Colombier 			unlock(&kmaplock);
133*a81c3ea0SDavid du Colombier 			splx(s);
134*a81c3ea0SDavid du Colombier 			if(printed++ == 0){
135*a81c3ea0SDavid du Colombier 			/* using iprint here we get mixed up with other prints */
136*a81c3ea0SDavid du Colombier 				print("%d KMAP RETRY %#lux ktime %ld %ld %ld %ld %ld %ld %ld %ld\n",
137*a81c3ea0SDavid du Colombier 					m->machno, getcallerpc(&pg),
138*a81c3ea0SDavid du Colombier 					ktime[0], ktime[1], ktime[2], ktime[3],
139*a81c3ea0SDavid du Colombier 					ktime[4], ktime[5], ktime[6], ktime[7]);
140*a81c3ea0SDavid du Colombier 				delay(200);
141*a81c3ea0SDavid du Colombier 			}
142*a81c3ea0SDavid du Colombier 			splhi();
143*a81c3ea0SDavid du Colombier 			lock(&kmaplock);
144*a81c3ea0SDavid du Colombier 			goto retry;
145*a81c3ea0SDavid du Colombier 		}
146*a81c3ea0SDavid du Colombier 	}
147*a81c3ea0SDavid du Colombier 
148*a81c3ea0SDavid du Colombier 	k = kmapfree;
149*a81c3ea0SDavid du Colombier 	kmapfree = k->next;
150*a81c3ea0SDavid du Colombier 
151*a81c3ea0SDavid du Colombier 	k->pg = pg;
152*a81c3ea0SDavid du Colombier 	/*
153*a81c3ea0SDavid du Colombier 	 * One for the allocation,
154*a81c3ea0SDavid du Colombier 	 * One for kactive
155*a81c3ea0SDavid du Colombier 	 */
156*a81c3ea0SDavid du Colombier 	k->pc = getcallerpc(&pg);
157*a81c3ea0SDavid du Colombier 	k->ref = 2;
158*a81c3ea0SDavid du Colombier 	k->konmach[m->machno] = m->kactive;
159*a81c3ea0SDavid du Colombier 	m->kactive = k;
160*a81c3ea0SDavid du Colombier 
161*a81c3ea0SDavid du Colombier 	virt = pg->va;
162*a81c3ea0SDavid du Colombier 	/* bits 13..12 form the cache virtual index */
163*a81c3ea0SDavid du Colombier 	virt &= PIDX;
164*a81c3ea0SDavid du Colombier 	virt |= KMAPADDR | ((k-kpte)<<KMAPSHIFT);
165*a81c3ea0SDavid du Colombier 
166*a81c3ea0SDavid du Colombier 	k->virt = virt;
167*a81c3ea0SDavid du Colombier 	pte = PPN(pg->pa)|PTECACHABILITY|PTEGLOBL|PTEWRITE|PTEVALID;
168*a81c3ea0SDavid du Colombier 	if(virt & BY2PG) {
169*a81c3ea0SDavid du Colombier 		k->phys0 = PTEGLOBL | PTECACHABILITY;
170*a81c3ea0SDavid du Colombier 		k->phys1 = pte;
171*a81c3ea0SDavid du Colombier 	}
172*a81c3ea0SDavid du Colombier 	else {
173*a81c3ea0SDavid du Colombier 		k->phys0 = pte;
174*a81c3ea0SDavid du Colombier 		k->phys1 = PTEGLOBL | PTECACHABILITY;
175*a81c3ea0SDavid du Colombier 	}
176*a81c3ea0SDavid du Colombier 
177*a81c3ea0SDavid du Colombier 	putktlb(k);
178*a81c3ea0SDavid du Colombier 	unlock(&kmaplock);
179*a81c3ea0SDavid du Colombier 
180*a81c3ea0SDavid du Colombier 	splx(s);
181*a81c3ea0SDavid du Colombier 	return k;
182*a81c3ea0SDavid du Colombier }
183*a81c3ea0SDavid du Colombier 
184*a81c3ea0SDavid du Colombier void
kunmap(KMap * k)185*a81c3ea0SDavid du Colombier kunmap(KMap *k)
186*a81c3ea0SDavid du Colombier {
187*a81c3ea0SDavid du Colombier 	int s;
188*a81c3ea0SDavid du Colombier 
189*a81c3ea0SDavid du Colombier 	s = splhi();
190*a81c3ea0SDavid du Colombier 	if(decref(k) == 0) {
191*a81c3ea0SDavid du Colombier 		k->virt = 0;
192*a81c3ea0SDavid du Colombier 		k->phys0 = 0;
193*a81c3ea0SDavid du Colombier 		k->phys1 = 0;
194*a81c3ea0SDavid du Colombier 		k->pg = 0;
195*a81c3ea0SDavid du Colombier 
196*a81c3ea0SDavid du Colombier 		lock(&kmaplock);
197*a81c3ea0SDavid du Colombier 		k->next = kmapfree;
198*a81c3ea0SDavid du Colombier 		kmapfree = k;
199*a81c3ea0SDavid du Colombier //nfree();
200*a81c3ea0SDavid du Colombier 		unlock(&kmaplock);
201*a81c3ea0SDavid du Colombier 	}
202*a81c3ea0SDavid du Colombier 	splx(s);
203*a81c3ea0SDavid du Colombier }
204*a81c3ea0SDavid du Colombier 
205*a81c3ea0SDavid du Colombier void
kfault(Ureg * ur)206*a81c3ea0SDavid du Colombier kfault(Ureg *ur)			/* called from trap() */
207*a81c3ea0SDavid du Colombier {
208*a81c3ea0SDavid du Colombier 	ulong index, addr;
209*a81c3ea0SDavid du Colombier 	KMap *k, *f;
210*a81c3ea0SDavid du Colombier 
211*a81c3ea0SDavid du Colombier 	addr = ur->badvaddr;
212*a81c3ea0SDavid du Colombier 	index = (addr & ~KSEGM) >> KMAPSHIFT;
213*a81c3ea0SDavid du Colombier 	if(index >= KPTESIZE)
214*a81c3ea0SDavid du Colombier 		panic("kmapfault: %#lux", addr);
215*a81c3ea0SDavid du Colombier 
216*a81c3ea0SDavid du Colombier 	k = &kpte[index];
217*a81c3ea0SDavid du Colombier 	if(k->virt == 0)
218*a81c3ea0SDavid du Colombier 		panic("kmapfault: unmapped %#lux", addr);
219*a81c3ea0SDavid du Colombier 
220*a81c3ea0SDavid du Colombier 	for(f = m->kactive; f; f = f->konmach[m->machno])
221*a81c3ea0SDavid du Colombier 		if(f == k)
222*a81c3ea0SDavid du Colombier 			break;
223*a81c3ea0SDavid du Colombier 	if(f == 0) {
224*a81c3ea0SDavid du Colombier 		incref(k);
225*a81c3ea0SDavid du Colombier 		k->konmach[m->machno] = m->kactive;
226*a81c3ea0SDavid du Colombier 		m->kactive = k;
227*a81c3ea0SDavid du Colombier 	}
228*a81c3ea0SDavid du Colombier 	putktlb(k);
229*a81c3ea0SDavid du Colombier }
230*a81c3ea0SDavid du Colombier 
231*a81c3ea0SDavid du Colombier struct
232*a81c3ea0SDavid du Colombier {
233*a81c3ea0SDavid du Colombier 	ulong	va;
234*a81c3ea0SDavid du Colombier 	ulong	pl;
235*a81c3ea0SDavid du Colombier 	ulong	ph;
236*a81c3ea0SDavid du Colombier } wired[NWTLB+1];		/* +1 to avoid zero size if NWTLB==0 */
237*a81c3ea0SDavid du Colombier 
238*a81c3ea0SDavid du Colombier void
machwire(void)239*a81c3ea0SDavid du Colombier machwire(void)
240*a81c3ea0SDavid du Colombier {
241*a81c3ea0SDavid du Colombier 	int i;
242*a81c3ea0SDavid du Colombier 
243*a81c3ea0SDavid du Colombier 	//if(m->machno == 0)
244*a81c3ea0SDavid du Colombier 	//	return;
245*a81c3ea0SDavid du Colombier 	for(i = 0; i < NWTLB; i++)
246*a81c3ea0SDavid du Colombier 		if(wired[i].va)
247*a81c3ea0SDavid du Colombier 			puttlbx(i+WTLBOFF, wired[i].va, wired[i].pl,
248*a81c3ea0SDavid du Colombier 				wired[i].ph, PGSZ);
249*a81c3ea0SDavid du Colombier }
250*a81c3ea0SDavid du Colombier 
251*a81c3ea0SDavid du Colombier /*
252*a81c3ea0SDavid du Colombier  * Process must be splhi
253*a81c3ea0SDavid du Colombier  */
254*a81c3ea0SDavid du Colombier int
newtlbpid(Proc * p)255*a81c3ea0SDavid du Colombier newtlbpid(Proc *p)
256*a81c3ea0SDavid du Colombier {
257*a81c3ea0SDavid du Colombier 	int i, s;
258*a81c3ea0SDavid du Colombier 	Proc **h;
259*a81c3ea0SDavid du Colombier 
260*a81c3ea0SDavid du Colombier 	i = m->lastpid;
261*a81c3ea0SDavid du Colombier 	h = m->pidproc;
262*a81c3ea0SDavid du Colombier 	for(s = 0; s < NTLBPID; s++) {
263*a81c3ea0SDavid du Colombier 		i++;
264*a81c3ea0SDavid du Colombier 		if(i >= NTLBPID)
265*a81c3ea0SDavid du Colombier 			i = 1;
266*a81c3ea0SDavid du Colombier 		if(h[i] == 0)
267*a81c3ea0SDavid du Colombier 			break;
268*a81c3ea0SDavid du Colombier 	}
269*a81c3ea0SDavid du Colombier 
270*a81c3ea0SDavid du Colombier 	if(h[i])
271*a81c3ea0SDavid du Colombier 		purgetlb(i);
272*a81c3ea0SDavid du Colombier 	if(h[i] != 0)
273*a81c3ea0SDavid du Colombier 		panic("newtlb");
274*a81c3ea0SDavid du Colombier 
275*a81c3ea0SDavid du Colombier 	m->pidproc[i] = p;
276*a81c3ea0SDavid du Colombier 	p->pidonmach[m->machno] = i;
277*a81c3ea0SDavid du Colombier 	m->lastpid = i;
278*a81c3ea0SDavid du Colombier 
279*a81c3ea0SDavid du Colombier 	return i;
280*a81c3ea0SDavid du Colombier }
281*a81c3ea0SDavid du Colombier 
282*a81c3ea0SDavid du Colombier void
mmuswitch(Proc * p)283*a81c3ea0SDavid du Colombier mmuswitch(Proc *p)
284*a81c3ea0SDavid du Colombier {
285*a81c3ea0SDavid du Colombier 	int tp;
286*a81c3ea0SDavid du Colombier 	static char lasttext[32];
287*a81c3ea0SDavid du Colombier 
288*a81c3ea0SDavid du Colombier 	if(Debugswitch && !p->kp){
289*a81c3ea0SDavid du Colombier 		if(strncmp(lasttext, p->text, sizeof lasttext) != 0)
290*a81c3ea0SDavid du Colombier 			iprint("[%s]", p->text);
291*a81c3ea0SDavid du Colombier 		strncpy(lasttext, p->text, sizeof lasttext);
292*a81c3ea0SDavid du Colombier 	}
293*a81c3ea0SDavid du Colombier 
294*a81c3ea0SDavid du Colombier 	if(p->newtlb) {
295*a81c3ea0SDavid du Colombier 		memset(p->pidonmach, 0, sizeof p->pidonmach);
296*a81c3ea0SDavid du Colombier 		p->newtlb = 0;
297*a81c3ea0SDavid du Colombier 	}
298*a81c3ea0SDavid du Colombier 	tp = p->pidonmach[m->machno];
299*a81c3ea0SDavid du Colombier 	if(tp == 0)
300*a81c3ea0SDavid du Colombier 		tp = newtlbpid(p);
301*a81c3ea0SDavid du Colombier 	puttlbx(0, KZERO|PTEPID(tp), 0, 0, PGSZ);
302*a81c3ea0SDavid du Colombier }
303*a81c3ea0SDavid du Colombier 
304*a81c3ea0SDavid du Colombier void
mmurelease(Proc * p)305*a81c3ea0SDavid du Colombier mmurelease(Proc *p)
306*a81c3ea0SDavid du Colombier {
307*a81c3ea0SDavid du Colombier 	memset(p->pidonmach, 0, sizeof p->pidonmach);
308*a81c3ea0SDavid du Colombier }
309*a81c3ea0SDavid du Colombier 
310*a81c3ea0SDavid du Colombier void
putmmu(ulong tlbvirt,ulong tlbphys,Page * pg)311*a81c3ea0SDavid du Colombier putmmu(ulong tlbvirt, ulong tlbphys, Page *pg)
312*a81c3ea0SDavid du Colombier {
313*a81c3ea0SDavid du Colombier 	short tp;
314*a81c3ea0SDavid du Colombier 	char *ctl;
315*a81c3ea0SDavid du Colombier 	Softtlb *entry;
316*a81c3ea0SDavid du Colombier 	int s;
317*a81c3ea0SDavid du Colombier 
318*a81c3ea0SDavid du Colombier 	s = splhi();
319*a81c3ea0SDavid du Colombier 	tp = up->pidonmach[m->machno];
320*a81c3ea0SDavid du Colombier 	if(tp == 0)
321*a81c3ea0SDavid du Colombier 		tp = newtlbpid(up);
322*a81c3ea0SDavid du Colombier 
323*a81c3ea0SDavid du Colombier 	tlbvirt |= PTEPID(tp);
324*a81c3ea0SDavid du Colombier 	if((tlbphys & PTEALGMASK) != PTEUNCACHED) {
325*a81c3ea0SDavid du Colombier 		tlbphys &= ~PTEALGMASK;
326*a81c3ea0SDavid du Colombier 		tlbphys |= PTECACHABILITY;
327*a81c3ea0SDavid du Colombier 	}
328*a81c3ea0SDavid du Colombier 
329*a81c3ea0SDavid du Colombier 	entry = putstlb(tlbvirt, tlbphys);
330*a81c3ea0SDavid du Colombier 	puttlb(entry->virt, entry->phys0, entry->phys1);
331*a81c3ea0SDavid du Colombier 
332*a81c3ea0SDavid du Colombier 	ctl = &pg->cachectl[m->machno];
333*a81c3ea0SDavid du Colombier 	switch(*ctl) {
334*a81c3ea0SDavid du Colombier 	case PG_TXTFLUSH:
335*a81c3ea0SDavid du Colombier 		icflush((void*)pg->va, BY2PG);
336*a81c3ea0SDavid du Colombier 		*ctl = PG_NOFLUSH;
337*a81c3ea0SDavid du Colombier 		break;
338*a81c3ea0SDavid du Colombier 	case PG_DATFLUSH:
339*a81c3ea0SDavid du Colombier 		dcflush((void*)pg->va, BY2PG);
340*a81c3ea0SDavid du Colombier 		*ctl = PG_NOFLUSH;
341*a81c3ea0SDavid du Colombier 		break;
342*a81c3ea0SDavid du Colombier 	case PG_NEWCOL:
343*a81c3ea0SDavid du Colombier 		cleancache();		/* Too expensive */
344*a81c3ea0SDavid du Colombier 		*ctl = PG_NOFLUSH;
345*a81c3ea0SDavid du Colombier 		break;
346*a81c3ea0SDavid du Colombier 	}
347*a81c3ea0SDavid du Colombier 	splx(s);
348*a81c3ea0SDavid du Colombier }
349*a81c3ea0SDavid du Colombier 
350*a81c3ea0SDavid du Colombier void
purgetlb(int pid)351*a81c3ea0SDavid du Colombier purgetlb(int pid)
352*a81c3ea0SDavid du Colombier {
353*a81c3ea0SDavid du Colombier 	int i, mno;
354*a81c3ea0SDavid du Colombier 	Proc *sp, **pidproc;
355*a81c3ea0SDavid du Colombier 	Softtlb *entry, *etab;
356*a81c3ea0SDavid du Colombier 
357*a81c3ea0SDavid du Colombier 	m->tlbpurge++;
358*a81c3ea0SDavid du Colombier 
359*a81c3ea0SDavid du Colombier 	/*
360*a81c3ea0SDavid du Colombier 	 * find all pid entries that are no longer used by processes
361*a81c3ea0SDavid du Colombier 	 */
362*a81c3ea0SDavid du Colombier 	mno = m->machno;
363*a81c3ea0SDavid du Colombier 	pidproc = m->pidproc;
364*a81c3ea0SDavid du Colombier 	for(i=1; i<NTLBPID; i++) {
365*a81c3ea0SDavid du Colombier 		sp = pidproc[i];
366*a81c3ea0SDavid du Colombier 		if(sp && sp->pidonmach[mno] != i)
367*a81c3ea0SDavid du Colombier 			pidproc[i] = 0;
368*a81c3ea0SDavid du Colombier 	}
369*a81c3ea0SDavid du Colombier 
370*a81c3ea0SDavid du Colombier 	/*
371*a81c3ea0SDavid du Colombier 	 * shoot down the one we want
372*a81c3ea0SDavid du Colombier 	 */
373*a81c3ea0SDavid du Colombier 	sp = pidproc[pid];
374*a81c3ea0SDavid du Colombier 	if(sp != 0)
375*a81c3ea0SDavid du Colombier 		sp->pidonmach[mno] = 0;
376*a81c3ea0SDavid du Colombier 	pidproc[pid] = 0;
377*a81c3ea0SDavid du Colombier 
378*a81c3ea0SDavid du Colombier 	/*
379*a81c3ea0SDavid du Colombier 	 * clean out all dead pids from the stlb;
380*a81c3ea0SDavid du Colombier 	 */
381*a81c3ea0SDavid du Colombier 	entry = m->stb;
382*a81c3ea0SDavid du Colombier 	for(etab = &entry[STLBSIZE]; entry < etab; entry++)
383*a81c3ea0SDavid du Colombier 		if(pidproc[TLBPID(entry->virt)] == 0)
384*a81c3ea0SDavid du Colombier 			entry->virt = 0;
385*a81c3ea0SDavid du Colombier 
386*a81c3ea0SDavid du Colombier 	/*
387*a81c3ea0SDavid du Colombier 	 * clean up the hardware
388*a81c3ea0SDavid du Colombier 	 */
389*a81c3ea0SDavid du Colombier 	for(i=tlbroff; i<NTLB; i++)
390*a81c3ea0SDavid du Colombier 		if(pidproc[TLBPID(gettlbvirt(i))] == 0)
391*a81c3ea0SDavid du Colombier 			TLBINVAL(i, pid);
392*a81c3ea0SDavid du Colombier }
393*a81c3ea0SDavid du Colombier 
394*a81c3ea0SDavid du Colombier void
flushmmu(void)395*a81c3ea0SDavid du Colombier flushmmu(void)
396*a81c3ea0SDavid du Colombier {
397*a81c3ea0SDavid du Colombier 	int s;
398*a81c3ea0SDavid du Colombier 
399*a81c3ea0SDavid du Colombier 	s = splhi();
400*a81c3ea0SDavid du Colombier 	up->newtlb = 1;
401*a81c3ea0SDavid du Colombier 	mmuswitch(up);
402*a81c3ea0SDavid du Colombier 	splx(s);
403*a81c3ea0SDavid du Colombier }
404*a81c3ea0SDavid du Colombier 
405*a81c3ea0SDavid du Colombier /* tlbvirt also has TLBPID() in its low byte as the asid */
406*a81c3ea0SDavid du Colombier Softtlb*
putstlb(ulong tlbvirt,ulong tlbphys)407*a81c3ea0SDavid du Colombier putstlb(ulong tlbvirt, ulong tlbphys)
408*a81c3ea0SDavid du Colombier {
409*a81c3ea0SDavid du Colombier 	int odd;
410*a81c3ea0SDavid du Colombier 	Softtlb *entry;
411*a81c3ea0SDavid du Colombier 
412*a81c3ea0SDavid du Colombier 	/* identical calculation in l.s/utlbmiss */
413*a81c3ea0SDavid du Colombier 	entry = &m->stb[stlbhash(tlbvirt)];
414*a81c3ea0SDavid du Colombier 	odd = tlbvirt & BY2PG;		/* even/odd bit */
415*a81c3ea0SDavid du Colombier 	tlbvirt &= ~BY2PG;		/* zero even/odd bit */
416*a81c3ea0SDavid du Colombier 	if(entry->virt != tlbvirt) {	/* not my entry? overwrite it */
417*a81c3ea0SDavid du Colombier 		if(entry->virt != 0) {
418*a81c3ea0SDavid du Colombier 			m->hashcoll++;
419*a81c3ea0SDavid du Colombier 			if (Debughash)
420*a81c3ea0SDavid du Colombier 				iprint("putstlb: hash collision: %#lx old virt "
421*a81c3ea0SDavid du Colombier 					"%#lux new virt %#lux page %#lux\n",
422*a81c3ea0SDavid du Colombier 					entry - m->stb, entry->virt, tlbvirt,
423*a81c3ea0SDavid du Colombier 					tlbvirt >> (PGSHIFT+1));
424*a81c3ea0SDavid du Colombier 		}
425*a81c3ea0SDavid du Colombier 		entry->virt = tlbvirt;
426*a81c3ea0SDavid du Colombier 		entry->phys0 = 0;
427*a81c3ea0SDavid du Colombier 		entry->phys1 = 0;
428*a81c3ea0SDavid du Colombier 	}
429*a81c3ea0SDavid du Colombier 
430*a81c3ea0SDavid du Colombier 	if(odd)
431*a81c3ea0SDavid du Colombier 		entry->phys1 = tlbphys;
432*a81c3ea0SDavid du Colombier 	else
433*a81c3ea0SDavid du Colombier 		entry->phys0 = tlbphys;
434*a81c3ea0SDavid du Colombier 
435*a81c3ea0SDavid du Colombier 	if(entry->phys0 == 0 && entry->phys1 == 0)
436*a81c3ea0SDavid du Colombier 		entry->virt = 0;
437*a81c3ea0SDavid du Colombier 
438*a81c3ea0SDavid du Colombier 	return entry;
439*a81c3ea0SDavid du Colombier }
440*a81c3ea0SDavid du Colombier 
441*a81c3ea0SDavid du Colombier void
checkmmu(ulong,ulong)442*a81c3ea0SDavid du Colombier checkmmu(ulong, ulong)
443*a81c3ea0SDavid du Colombier {
444*a81c3ea0SDavid du Colombier }
445*a81c3ea0SDavid du Colombier 
446*a81c3ea0SDavid du Colombier void
countpagerefs(ulong *,int)447*a81c3ea0SDavid du Colombier countpagerefs(ulong*, int)
448*a81c3ea0SDavid du Colombier {
449*a81c3ea0SDavid du Colombier }
450*a81c3ea0SDavid du Colombier 
451*a81c3ea0SDavid du Colombier /*
452*a81c3ea0SDavid du Colombier  * Return the number of bytes that can be accessed via KADDR(pa).
453*a81c3ea0SDavid du Colombier  * If pa is not a valid argument to KADDR, return 0.
454*a81c3ea0SDavid du Colombier  */
455*a81c3ea0SDavid du Colombier uintptr
cankaddr(uintptr pa)456*a81c3ea0SDavid du Colombier cankaddr(uintptr pa)
457*a81c3ea0SDavid du Colombier {
458*a81c3ea0SDavid du Colombier 	if(pa >= KZERO || pa >= memsize)
459*a81c3ea0SDavid du Colombier 		return 0;
460*a81c3ea0SDavid du Colombier 	return memsize - pa;
461*a81c3ea0SDavid du Colombier }
462*a81c3ea0SDavid du Colombier 
463*a81c3ea0SDavid du Colombier /* print tlb entries for debug */
464*a81c3ea0SDavid du Colombier #define TLBPHYS(x)	((((x)&~0x3f)<<6) | ((x)&0x3f))	/* phys addr & flags */
465*a81c3ea0SDavid du Colombier 
466*a81c3ea0SDavid du Colombier void
dumptlb(void)467*a81c3ea0SDavid du Colombier dumptlb(void)
468*a81c3ea0SDavid du Colombier {
469*a81c3ea0SDavid du Colombier 	Softtlb entry;
470*a81c3ea0SDavid du Colombier 	int i;
471*a81c3ea0SDavid du Colombier 
472*a81c3ea0SDavid du Colombier 	iprint("dump tlb\n");
473*a81c3ea0SDavid du Colombier 	for(i=0; i<NTLB; i++) {
474*a81c3ea0SDavid du Colombier 		gettlbx(i, &entry);
475*a81c3ea0SDavid du Colombier 		if(entry.phys0 != 0 || entry.phys1 != 0)
476*a81c3ea0SDavid du Colombier 			iprint("tlb index %2d, virt %.8lux, phys0 %.8lux, phys1 %.8lux\n",
477*a81c3ea0SDavid du Colombier 				i, entry.virt, TLBPHYS(entry.phys0), TLBPHYS(entry.phys1));
478*a81c3ea0SDavid du Colombier 	}
479*a81c3ea0SDavid du Colombier }
480*a81c3ea0SDavid du Colombier 
481*a81c3ea0SDavid du Colombier void
dumpstlb(void)482*a81c3ea0SDavid du Colombier dumpstlb(void)
483*a81c3ea0SDavid du Colombier {
484*a81c3ea0SDavid du Colombier 	Softtlb *entry;
485*a81c3ea0SDavid du Colombier 	int i;
486*a81c3ea0SDavid du Colombier 
487*a81c3ea0SDavid du Colombier 	iprint("dump stlb\n");
488*a81c3ea0SDavid du Colombier 	for(i=0; i<STLBSIZE; i++) {
489*a81c3ea0SDavid du Colombier 		entry = &m->stb[i];
490*a81c3ea0SDavid du Colombier 		if(entry->virt != 0)
491*a81c3ea0SDavid du Colombier 			iprint("stlb index %2d, virt %.8lux, phys0 %.8lux, phys1 %.8lux\n",
492*a81c3ea0SDavid du Colombier 				i, entry->virt, TLBPHYS(entry->phys0), TLBPHYS(entry->phys1));
493*a81c3ea0SDavid du Colombier 	}
494*a81c3ea0SDavid du Colombier }
495