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