xref: /plan9-contrib/sys/src/9/vt5/mmu.c (revision 1c9d674cbfa2c1924558af05e99c43e5c5cd4845)
1*1c9d674cSDavid du Colombier #include "u.h"
2*1c9d674cSDavid du Colombier #include "../port/lib.h"
3*1c9d674cSDavid du Colombier #include "mem.h"
4*1c9d674cSDavid du Colombier #include "dat.h"
5*1c9d674cSDavid du Colombier #include "fns.h"
6*1c9d674cSDavid du Colombier 
7*1c9d674cSDavid du Colombier /*
8*1c9d674cSDavid du Colombier  * 440 mmu
9*1c9d674cSDavid du Colombier  *
10*1c9d674cSDavid du Colombier  * l.s has set some global TLB entries for the kernel at
11*1c9d674cSDavid du Colombier  * the top of the tlb (NTLB-1 down), partly to account for
12*1c9d674cSDavid du Colombier  * the way the firmware sets things up on some platforms (eg, 440).
13*1c9d674cSDavid du Colombier  * The first entry not used by the kernel (eg, by kmapphys) is m->utlbhi.
14*1c9d674cSDavid du Colombier  * User tlbs are assigned indices from 0 to m->utlbhi, round-robin.
15*1c9d674cSDavid du Colombier  * m->utlbnext is the next to use.  Kernel tlbs are added at utlbhi, which then moves.
16*1c9d674cSDavid du Colombier  *
17*1c9d674cSDavid du Colombier  * In this version, the kernel TLB entries are in zone 0,
18*1c9d674cSDavid du Colombier  * and user pages are in zone 1.  The kernel entries are also PID 0 (global)
19*1c9d674cSDavid du Colombier  * so they are usable as the PID changes (0=no user; non-zero=user process mapped).
20*1c9d674cSDavid du Colombier   */
21*1c9d674cSDavid du Colombier 
22*1c9d674cSDavid du Colombier enum {
23*1c9d674cSDavid du Colombier 	Minutlb=	NTLB/2,	/* at least this many for user process */
24*1c9d674cSDavid du Colombier };
25*1c9d674cSDavid du Colombier 
26*1c9d674cSDavid du Colombier #define	DEBUG	0
27*1c9d674cSDavid du Colombier 
28*1c9d674cSDavid du Colombier Softtlb	softtlb[MAXMACH][STLBSIZE];
29*1c9d674cSDavid du Colombier 
30*1c9d674cSDavid du Colombier static int	newtlbpid(Proc*);
31*1c9d674cSDavid du Colombier static void	purgetlb(int);
32*1c9d674cSDavid du Colombier static void putstlb(int, u32int, u32int, u32int);
33*1c9d674cSDavid du Colombier 
34*1c9d674cSDavid du Colombier static int
lookstlb(int pid,u32int va)35*1c9d674cSDavid du Colombier lookstlb(int pid, u32int va)
36*1c9d674cSDavid du Colombier {
37*1c9d674cSDavid du Colombier 	int i;
38*1c9d674cSDavid du Colombier 
39*1c9d674cSDavid du Colombier 	pid <<= 2;
40*1c9d674cSDavid du Colombier 	i = ((va>>12)^pid)&(STLBSIZE-1);
41*1c9d674cSDavid du Colombier 	if(m->stlb[i].hi == (va|pid))
42*1c9d674cSDavid du Colombier 		return i;
43*1c9d674cSDavid du Colombier 
44*1c9d674cSDavid du Colombier 	return -1;
45*1c9d674cSDavid du Colombier }
46*1c9d674cSDavid du Colombier 
47*1c9d674cSDavid du Colombier void
tlbdump(char * s)48*1c9d674cSDavid du Colombier tlbdump(char *s)
49*1c9d674cSDavid du Colombier {
50*1c9d674cSDavid du Colombier 	int i, p;
51*1c9d674cSDavid du Colombier 	u32int hi, lo, mi, stid;
52*1c9d674cSDavid du Colombier 
53*1c9d674cSDavid du Colombier 	p = pidget();
54*1c9d674cSDavid du Colombier 	iprint("tlb[%s] pid %d lastpid %d utlbnext %d\n",
55*1c9d674cSDavid du Colombier 		s, p, m->lastpid, m->utlbnext);
56*1c9d674cSDavid du Colombier 	for(i=0; i<NTLB; i++){
57*1c9d674cSDavid du Colombier 		hi = tlbrehi(i);
58*1c9d674cSDavid du Colombier 		if(hi & TLBVALID){
59*1c9d674cSDavid du Colombier 			stid = stidget();
60*1c9d674cSDavid du Colombier 			lo = tlbrelo(i);
61*1c9d674cSDavid du Colombier 			mi = tlbremd(i);
62*1c9d674cSDavid du Colombier 			iprint("%.2d %8.8ux %8.8ux %8.8ux %3d %2d\n",
63*1c9d674cSDavid du Colombier 				i, hi, mi, lo, stid, lookstlb(i, TLBEPN(hi)));
64*1c9d674cSDavid du Colombier 		}
65*1c9d674cSDavid du Colombier 		if(i == m->utlbhi)
66*1c9d674cSDavid du Colombier 			iprint("-----\n");
67*1c9d674cSDavid du Colombier 	}
68*1c9d674cSDavid du Colombier 	stidput(p);	/* tlbrehi changes STID */
69*1c9d674cSDavid du Colombier }
70*1c9d674cSDavid du Colombier 
71*1c9d674cSDavid du Colombier void
alltlbdump(void)72*1c9d674cSDavid du Colombier alltlbdump(void)
73*1c9d674cSDavid du Colombier {
74*1c9d674cSDavid du Colombier 	Mreg s;
75*1c9d674cSDavid du Colombier 	Proc *p;
76*1c9d674cSDavid du Colombier 	int i, machno;
77*1c9d674cSDavid du Colombier 
78*1c9d674cSDavid du Colombier 	s = splhi();
79*1c9d674cSDavid du Colombier 	machno = m->machno;
80*1c9d674cSDavid du Colombier 	iprint("cpu%d pidproc:\n", machno);
81*1c9d674cSDavid du Colombier 	for(i=0; i<nelem(m->pidproc); i++){
82*1c9d674cSDavid du Colombier 		p = m->pidproc[i];
83*1c9d674cSDavid du Colombier 		if(p != nil && (p->mmupid != i || p == up))
84*1c9d674cSDavid du Colombier 			iprint("%d -> %ld [%d]\n", i, p->pid, p->mmupid);
85*1c9d674cSDavid du Colombier 	}
86*1c9d674cSDavid du Colombier 	tlbdump("final");
87*1c9d674cSDavid du Colombier 	splx(s);
88*1c9d674cSDavid du Colombier }
89*1c9d674cSDavid du Colombier 
90*1c9d674cSDavid du Colombier /*
91*1c9d674cSDavid du Colombier  * l.s provides a set of tlb entries for the kernel, allocating
92*1c9d674cSDavid du Colombier  * them starting at the highest index down.  user-level entries
93*1c9d674cSDavid du Colombier  * will be allocated from index 0 up.
94*1c9d674cSDavid du Colombier  */
95*1c9d674cSDavid du Colombier void
mmuinit(void)96*1c9d674cSDavid du Colombier mmuinit(void)
97*1c9d674cSDavid du Colombier {
98*1c9d674cSDavid du Colombier 	int i;
99*1c9d674cSDavid du Colombier 
100*1c9d674cSDavid du Colombier 	pidput(0);
101*1c9d674cSDavid du Colombier 	stidput(0);
102*1c9d674cSDavid du Colombier 	m->stlb = softtlb[m->machno];
103*1c9d674cSDavid du Colombier 	if(DEBUG)
104*1c9d674cSDavid du Colombier 		tlbdump("init0");
105*1c9d674cSDavid du Colombier 
106*1c9d674cSDavid du Colombier 	m->lastpid = 0;
107*1c9d674cSDavid du Colombier 	m->utlbhi = 0;
108*1c9d674cSDavid du Colombier 	for(i = 0; i < NTLB; i++){
109*1c9d674cSDavid du Colombier 		if(tlbrehi(i) & TLBVALID)
110*1c9d674cSDavid du Colombier 			break;
111*1c9d674cSDavid du Colombier 		m->utlbhi = i;
112*1c9d674cSDavid du Colombier 		stidput(0);
113*1c9d674cSDavid du Colombier 		tlbwrx(i, 0, 0, 0);
114*1c9d674cSDavid du Colombier 	}
115*1c9d674cSDavid du Colombier 	pidput(0);
116*1c9d674cSDavid du Colombier 	stidput(0);
117*1c9d674cSDavid du Colombier 	if(DEBUG)
118*1c9d674cSDavid du Colombier 		tlbdump("init1");
119*1c9d674cSDavid du Colombier }
120*1c9d674cSDavid du Colombier 
121*1c9d674cSDavid du Colombier void
flushmmu(void)122*1c9d674cSDavid du Colombier flushmmu(void)
123*1c9d674cSDavid du Colombier {
124*1c9d674cSDavid du Colombier 	Mreg s;
125*1c9d674cSDavid du Colombier 
126*1c9d674cSDavid du Colombier 	s = splhi();
127*1c9d674cSDavid du Colombier 	up->newtlb = 1;
128*1c9d674cSDavid du Colombier 	mmuswitch(up);
129*1c9d674cSDavid du Colombier 	splx(s);
130*1c9d674cSDavid du Colombier }
131*1c9d674cSDavid du Colombier 
132*1c9d674cSDavid du Colombier /*
133*1c9d674cSDavid du Colombier  * called with splhi
134*1c9d674cSDavid du Colombier  */
135*1c9d674cSDavid du Colombier void
mmuswitch(Proc * p)136*1c9d674cSDavid du Colombier mmuswitch(Proc *p)
137*1c9d674cSDavid du Colombier {
138*1c9d674cSDavid du Colombier 	int pid;
139*1c9d674cSDavid du Colombier 
140*1c9d674cSDavid du Colombier 	if(p->newtlb){
141*1c9d674cSDavid du Colombier 		p->mmupid = 0;
142*1c9d674cSDavid du Colombier 		p->newtlb = 0;
143*1c9d674cSDavid du Colombier 	}
144*1c9d674cSDavid du Colombier 	pid = p->mmupid;
145*1c9d674cSDavid du Colombier 	if(pid == 0 && !p->kp)
146*1c9d674cSDavid du Colombier 		pid = newtlbpid(p);
147*1c9d674cSDavid du Colombier 	pidput(pid);
148*1c9d674cSDavid du Colombier 	stidput(pid);
149*1c9d674cSDavid du Colombier }
150*1c9d674cSDavid du Colombier 
151*1c9d674cSDavid du Colombier void
mmurelease(Proc * p)152*1c9d674cSDavid du Colombier mmurelease(Proc* p)
153*1c9d674cSDavid du Colombier {
154*1c9d674cSDavid du Colombier 	p->mmupid = 0;
155*1c9d674cSDavid du Colombier 	pidput(0);
156*1c9d674cSDavid du Colombier 	stidput(0);
157*1c9d674cSDavid du Colombier }
158*1c9d674cSDavid du Colombier 
159*1c9d674cSDavid du Colombier void
putmmu(uintptr va,uintptr pa,Page * page)160*1c9d674cSDavid du Colombier putmmu(uintptr va, uintptr pa, Page* page)
161*1c9d674cSDavid du Colombier {
162*1c9d674cSDavid du Colombier 	Mreg s;
163*1c9d674cSDavid du Colombier 	int x, tp;
164*1c9d674cSDavid du Colombier 	char *ctl;
165*1c9d674cSDavid du Colombier 	u32int tlbhi, tlblo, tlbmi;
166*1c9d674cSDavid du Colombier 
167*1c9d674cSDavid du Colombier 	if(va >= KZERO)
168*1c9d674cSDavid du Colombier 		panic("mmuput");
169*1c9d674cSDavid du Colombier 
170*1c9d674cSDavid du Colombier 	tlbhi = TLBEPN(va) | TLB4K | TLBVALID;
171*1c9d674cSDavid du Colombier 	tlbmi = TLBRPN(pa);	/* TO DO: 36-bit physical memory */
172*1c9d674cSDavid du Colombier 	tlblo = TLBUR | TLBUX | TLBSR;	/* shouldn't need TLBSX */
173*1c9d674cSDavid du Colombier 	if(pa & PTEWRITE)
174*1c9d674cSDavid du Colombier 		tlblo |= TLBUW | TLBSW;
175*1c9d674cSDavid du Colombier 	if(pa & PTEUNCACHED)
176*1c9d674cSDavid du Colombier 		tlblo |= TLBI | TLBG;
177*1c9d674cSDavid du Colombier 
178*1c9d674cSDavid du Colombier 	s = splhi();
179*1c9d674cSDavid du Colombier 	tp = up->mmupid;
180*1c9d674cSDavid du Colombier 	if(tp == 0){
181*1c9d674cSDavid du Colombier 		if(up->kp)
182*1c9d674cSDavid du Colombier 			panic("mmuput kp");
183*1c9d674cSDavid du Colombier 		tp = newtlbpid(up);
184*1c9d674cSDavid du Colombier 		pidput(tp);
185*1c9d674cSDavid du Colombier 		stidput(tp);
186*1c9d674cSDavid du Colombier 	}
187*1c9d674cSDavid du Colombier 	else if(pidget() != tp || stidget() != tp){
188*1c9d674cSDavid du Colombier 		iprint("mmuput: cpu%d pid up->mmupid=%d pidget=%d stidget=%d s=%#ux\n",
189*1c9d674cSDavid du Colombier 			m->machno, tp, pidget(), stidget(), s);
190*1c9d674cSDavid du Colombier 		alltlbdump();
191*1c9d674cSDavid du Colombier 		panic("mmuput: cpu%d pid %d %d s=%#ux",
192*1c9d674cSDavid du Colombier 			m->machno, tp, pidget(), s);
193*1c9d674cSDavid du Colombier 	}
194*1c9d674cSDavid du Colombier 
195*1c9d674cSDavid du Colombier 	/* see if it's already there: note that tlbsx[cc] uses STID */
196*1c9d674cSDavid du Colombier 	x = tlbsxcc(va);
197*1c9d674cSDavid du Colombier 	if(x < 0){
198*1c9d674cSDavid du Colombier 		if(m->utlbnext > m->utlbhi)
199*1c9d674cSDavid du Colombier 			m->utlbnext = 0;
200*1c9d674cSDavid du Colombier 		x = m->utlbnext++;
201*1c9d674cSDavid du Colombier 	}else if(x > m->utlbhi)
202*1c9d674cSDavid du Colombier 		panic("mmuput index va=%#p x=%d klo=%d", va, x, m->utlbhi);	/* shouldn't touch kernel entries */
203*1c9d674cSDavid du Colombier //	if(DEBUG)
204*1c9d674cSDavid du Colombier //		iprint("put %#p %#p-> %d: %8.8ux %8.8ux %8.8ux\n", va, pa, x, tlbhi, tlbmi, tlblo);
205*1c9d674cSDavid du Colombier 	if(stidget() != tp)
206*1c9d674cSDavid du Colombier 		panic("mmuput stid:pid mismatch");
207*1c9d674cSDavid du Colombier 	stidput(tp);
208*1c9d674cSDavid du Colombier 	tlbwrx(x, tlbhi, tlbmi, tlblo);
209*1c9d674cSDavid du Colombier 	putstlb(tp, TLBEPN(va), tlbmi, tlblo);
210*1c9d674cSDavid du Colombier 
211*1c9d674cSDavid du Colombier 	ctl = &page->cachectl[m->machno];
212*1c9d674cSDavid du Colombier 	switch(*ctl){
213*1c9d674cSDavid du Colombier 	case PG_TXTFLUSH:
214*1c9d674cSDavid du Colombier 		dcflush(page->va, BY2PG);
215*1c9d674cSDavid du Colombier 		icflush(page->va, BY2PG);
216*1c9d674cSDavid du Colombier 		*ctl = PG_NOFLUSH;
217*1c9d674cSDavid du Colombier 		break;
218*1c9d674cSDavid du Colombier 	case PG_DATFLUSH:
219*1c9d674cSDavid du Colombier 		dcflush(page->va, BY2PG);
220*1c9d674cSDavid du Colombier 		*ctl = PG_NOFLUSH;
221*1c9d674cSDavid du Colombier 		break;
222*1c9d674cSDavid du Colombier 	case PG_NEWCOL:
223*1c9d674cSDavid du Colombier //		cleancache();		/* expensive, but fortunately not needed here */
224*1c9d674cSDavid du Colombier 		*ctl = PG_NOFLUSH;
225*1c9d674cSDavid du Colombier 		break;
226*1c9d674cSDavid du Colombier 	}
227*1c9d674cSDavid du Colombier 	splx(s);
228*1c9d674cSDavid du Colombier }
229*1c9d674cSDavid du Colombier 
230*1c9d674cSDavid du Colombier /*
231*1c9d674cSDavid du Colombier  * Process must be splhi
232*1c9d674cSDavid du Colombier  */
233*1c9d674cSDavid du Colombier static int
newtlbpid(Proc * p)234*1c9d674cSDavid du Colombier newtlbpid(Proc *p)
235*1c9d674cSDavid du Colombier {
236*1c9d674cSDavid du Colombier 	int i, s;
237*1c9d674cSDavid du Colombier 	Proc **h;
238*1c9d674cSDavid du Colombier 
239*1c9d674cSDavid du Colombier 	i = m->lastpid;
240*1c9d674cSDavid du Colombier 	h = m->pidproc;
241*1c9d674cSDavid du Colombier 	for(s = 0; s < NTLBPID; s++) {
242*1c9d674cSDavid du Colombier 		i++;
243*1c9d674cSDavid du Colombier 		if(i >= NTLBPID)
244*1c9d674cSDavid du Colombier 			i = 1;
245*1c9d674cSDavid du Colombier 		if(h[i] == nil)
246*1c9d674cSDavid du Colombier 			break;
247*1c9d674cSDavid du Colombier 	}
248*1c9d674cSDavid du Colombier 
249*1c9d674cSDavid du Colombier 	if(h[i] != nil){
250*1c9d674cSDavid du Colombier 		purgetlb(i);
251*1c9d674cSDavid du Colombier 		if(h[i] != nil)
252*1c9d674cSDavid du Colombier 			panic("newtlb");
253*1c9d674cSDavid du Colombier 	}
254*1c9d674cSDavid du Colombier 
255*1c9d674cSDavid du Colombier 	m->pidproc[i] = p;
256*1c9d674cSDavid du Colombier 	p->mmupid = i;
257*1c9d674cSDavid du Colombier 	m->lastpid = i;
258*1c9d674cSDavid du Colombier 
259*1c9d674cSDavid du Colombier 	return i;
260*1c9d674cSDavid du Colombier }
261*1c9d674cSDavid du Colombier 
262*1c9d674cSDavid du Colombier static void
purgetlb(int pid)263*1c9d674cSDavid du Colombier purgetlb(int pid)
264*1c9d674cSDavid du Colombier {
265*1c9d674cSDavid du Colombier 	int i;
266*1c9d674cSDavid du Colombier 	Proc *sp, **pidproc;
267*1c9d674cSDavid du Colombier 	Softtlb *entry, *etab;
268*1c9d674cSDavid du Colombier 	u32int hi;
269*1c9d674cSDavid du Colombier 
270*1c9d674cSDavid du Colombier 	m->tlbpurge++;
271*1c9d674cSDavid du Colombier 
272*1c9d674cSDavid du Colombier 	/*
273*1c9d674cSDavid du Colombier 	 * find all pid entries that are no longer used by processes
274*1c9d674cSDavid du Colombier 	 */
275*1c9d674cSDavid du Colombier 	pidproc = m->pidproc;
276*1c9d674cSDavid du Colombier 	for(i=1; i<NTLBPID; i++) {
277*1c9d674cSDavid du Colombier 		sp = pidproc[i];
278*1c9d674cSDavid du Colombier 		if(sp != nil && sp->mmupid != i)
279*1c9d674cSDavid du Colombier 			pidproc[i] = nil;
280*1c9d674cSDavid du Colombier 	}
281*1c9d674cSDavid du Colombier 
282*1c9d674cSDavid du Colombier 	/*
283*1c9d674cSDavid du Colombier 	 * shoot down the one we want
284*1c9d674cSDavid du Colombier 	 */
285*1c9d674cSDavid du Colombier 	sp = pidproc[pid];
286*1c9d674cSDavid du Colombier 	if(sp != nil)
287*1c9d674cSDavid du Colombier 		sp->mmupid = 0;
288*1c9d674cSDavid du Colombier 	pidproc[pid] = nil;
289*1c9d674cSDavid du Colombier 
290*1c9d674cSDavid du Colombier 	/*
291*1c9d674cSDavid du Colombier 	 * clean out all dead pids from the stlb;
292*1c9d674cSDavid du Colombier 	 */
293*1c9d674cSDavid du Colombier 	entry = m->stlb;
294*1c9d674cSDavid du Colombier 	for(etab = &entry[STLBSIZE]; entry < etab; entry++)
295*1c9d674cSDavid du Colombier 		if(pidproc[(entry->hi>>2)&0xFF] == nil){
296*1c9d674cSDavid du Colombier 			entry->hi = 0;
297*1c9d674cSDavid du Colombier 			entry->mid = 0;
298*1c9d674cSDavid du Colombier 			entry->lo = 0;
299*1c9d674cSDavid du Colombier 		}
300*1c9d674cSDavid du Colombier 
301*1c9d674cSDavid du Colombier 	/*
302*1c9d674cSDavid du Colombier 	 * clean up the hardware
303*1c9d674cSDavid du Colombier 	 */
304*1c9d674cSDavid du Colombier 	for(i = 0; i <= m->utlbhi; i++){
305*1c9d674cSDavid du Colombier 		hi = tlbrehi(i);
306*1c9d674cSDavid du Colombier 		if((hi & TLBVALID) && pidproc[stidget()] == nil)
307*1c9d674cSDavid du Colombier 			tlbwrx(i, 0, 0, 0);
308*1c9d674cSDavid du Colombier 	}
309*1c9d674cSDavid du Colombier 	stidput(pidget());
310*1c9d674cSDavid du Colombier 	mbar();
311*1c9d674cSDavid du Colombier 	barriers();
312*1c9d674cSDavid du Colombier 	iccci();
313*1c9d674cSDavid du Colombier }
314*1c9d674cSDavid du Colombier 
315*1c9d674cSDavid du Colombier /*
316*1c9d674cSDavid du Colombier  * return required size and alignment to map n bytes in a tlb entry
317*1c9d674cSDavid du Colombier  */
318*1c9d674cSDavid du Colombier ulong
mmumapsize(ulong n)319*1c9d674cSDavid du Colombier mmumapsize(ulong n)
320*1c9d674cSDavid du Colombier {
321*1c9d674cSDavid du Colombier 	ulong size;
322*1c9d674cSDavid du Colombier 	int i;
323*1c9d674cSDavid du Colombier 
324*1c9d674cSDavid du Colombier 	size = 1024;
325*1c9d674cSDavid du Colombier 	for(i = 0; i < 10 && size < n; i++)
326*1c9d674cSDavid du Colombier 		size <<= 2;
327*1c9d674cSDavid du Colombier 	return size;
328*1c9d674cSDavid du Colombier }
329*1c9d674cSDavid du Colombier 
330*1c9d674cSDavid du Colombier /*
331*1c9d674cSDavid du Colombier  * map a physical addresses at pa to va, with the given attributes.
332*1c9d674cSDavid du Colombier  * the virtual address must not be mapped already.
333*1c9d674cSDavid du Colombier  * if va is nil, map it at pa in virtual space.
334*1c9d674cSDavid du Colombier  */
335*1c9d674cSDavid du Colombier void*
kmapphys(uintptr va,uintptr pa,ulong nb,ulong attr,ulong le)336*1c9d674cSDavid du Colombier kmapphys(uintptr va, uintptr pa, ulong nb, ulong attr, ulong le)
337*1c9d674cSDavid du Colombier {
338*1c9d674cSDavid du Colombier 	Mreg s;
339*1c9d674cSDavid du Colombier 	int i;
340*1c9d674cSDavid du Colombier 	ulong size;
341*1c9d674cSDavid du Colombier 
342*1c9d674cSDavid du Colombier 	if(va == 0)
343*1c9d674cSDavid du Colombier 		va = pa;	/* simplest is to use a 1-1 map */
344*1c9d674cSDavid du Colombier 	size = 1024;
345*1c9d674cSDavid du Colombier 	for(i = 0; i < 10 && size < nb; i++)
346*1c9d674cSDavid du Colombier 		size <<= 2;
347*1c9d674cSDavid du Colombier 	if(i >= 10)
348*1c9d674cSDavid du Colombier 		return 0;
349*1c9d674cSDavid du Colombier 	if(i == 6 || i == 8)
350*1c9d674cSDavid du Colombier 		i++;	/* skip sizes not implemented by hardware */
351*1c9d674cSDavid du Colombier 	if(m->utlbhi <= Minutlb)
352*1c9d674cSDavid du Colombier 		panic("kmapphys");
353*1c9d674cSDavid du Colombier 
354*1c9d674cSDavid du Colombier 	s = splhi();
355*1c9d674cSDavid du Colombier 	stidput(0);
356*1c9d674cSDavid du Colombier 	tlbwrx(m->utlbhi, va | (i<<4) | TLBVALID, pa, attr | le);
357*1c9d674cSDavid du Colombier 	m->utlbhi--;
358*1c9d674cSDavid du Colombier 	stidput(pidget());
359*1c9d674cSDavid du Colombier 	splx(s);
360*1c9d674cSDavid du Colombier 
361*1c9d674cSDavid du Colombier 	if(DEBUG)
362*1c9d674cSDavid du Colombier 		tlbdump("kmapphys");
363*1c9d674cSDavid du Colombier 
364*1c9d674cSDavid du Colombier 	return UINT2PTR(va);
365*1c9d674cSDavid du Colombier }
366*1c9d674cSDavid du Colombier 
367*1c9d674cSDavid du Colombier /*
368*1c9d674cSDavid du Colombier  * return an uncached alias for the memory at a
369*1c9d674cSDavid du Colombier  */
370*1c9d674cSDavid du Colombier void*
mmucacheinhib(void * a,ulong nb)371*1c9d674cSDavid du Colombier mmucacheinhib(void* a, ulong nb)
372*1c9d674cSDavid du Colombier {
373*1c9d674cSDavid du Colombier 	uintptr pa;
374*1c9d674cSDavid du Colombier 
375*1c9d674cSDavid du Colombier 	if(a == nil)
376*1c9d674cSDavid du Colombier 		return nil;
377*1c9d674cSDavid du Colombier 	dcflush(PTR2UINT(a), nb);
378*1c9d674cSDavid du Colombier 	pa = PADDR(a);
379*1c9d674cSDavid du Colombier 	return kmapphys(KSEG1|pa, pa, nb, TLBWR | TLBI | TLBG, 0);
380*1c9d674cSDavid du Colombier }
381*1c9d674cSDavid du Colombier 
382*1c9d674cSDavid du Colombier static void
putstlb(int pid,u32int va,u32int tlbmid,u32int tlblo)383*1c9d674cSDavid du Colombier putstlb(int pid, u32int va, u32int tlbmid, u32int tlblo)
384*1c9d674cSDavid du Colombier {
385*1c9d674cSDavid du Colombier 	Softtlb *entry;
386*1c9d674cSDavid du Colombier 
387*1c9d674cSDavid du Colombier 	pid <<= 2;
388*1c9d674cSDavid du Colombier 	entry = &m->stlb[((va>>12)^pid)&(STLBSIZE-1)];
389*1c9d674cSDavid du Colombier 	entry->hi = va | pid;
390*1c9d674cSDavid du Colombier 	entry->mid = tlbmid;
391*1c9d674cSDavid du Colombier 	entry->lo = tlblo;
392*1c9d674cSDavid du Colombier }
393*1c9d674cSDavid du Colombier 
394*1c9d674cSDavid du Colombier /*
395*1c9d674cSDavid du Colombier  * Return the number of bytes that can be accessed via KADDR(pa).
396*1c9d674cSDavid du Colombier  * If pa is not a valid argument to KADDR, return 0.
397*1c9d674cSDavid du Colombier  */
398*1c9d674cSDavid du Colombier uintptr
cankaddr(uintptr pa)399*1c9d674cSDavid du Colombier cankaddr(uintptr pa)
400*1c9d674cSDavid du Colombier {
401*1c9d674cSDavid du Colombier 	if( /* pa >= PHYSDRAM && */ pa < PHYSDRAM + 512*MiB)
402*1c9d674cSDavid du Colombier 		return PHYSDRAM + 512*MiB - pa;
403*1c9d674cSDavid du Colombier 	return 0;
404*1c9d674cSDavid du Colombier }
405