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