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