2 #include "../port/lib.h"
14 pe = PHYSDRAM + soc.dramsize;
15 if(pe > (uintptr)-KZERO)
18 for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(1))
19 l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
20 | PTEKERNEL | PTESH(SHARE_INNER);
22 for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(2))
23 l1[PTL1X(pa, 2)] = (uintptr)&l1[L1TABLEX(pa, 1)] | PTEVALID | PTETABLE;
25 for(pa = PHYSDRAM; pa < pe; pa += PGLSZ(3))
26 l1[PTL1X(pa, 3)] = (uintptr)&l1[L1TABLEX(pa, 2)] | PTEVALID | PTETABLE;
29 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
30 l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
31 | PTEKERNEL | PTESH(SHARE_INNER);
33 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
34 l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
36 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
37 l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
40 pe = -VIRTIO + soc.physio;
41 for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
42 l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
43 | PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
45 for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
46 l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
48 for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
49 l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
53 mmu0clear(uintptr *l1)
57 pe = PHYSDRAM + soc.dramsize;
58 if(pe > (uintptr)-KZERO)
61 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
62 if(PTL1X(pa, 1) != PTL1X(va, 1))
66 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
67 if(PTL1X(pa, 2) != PTL1X(va, 2))
71 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
72 if(PTL1X(pa, 3) != PTL1X(va, 3))
85 pe = PHYSDRAM + soc.dramsize;
86 if(pe > (uintptr)-KZERO)
89 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
90 if(PTL1X(pa, 1) != PTL1X(va, 1))
91 l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
92 | PTEKERNEL | PTESH(SHARE_INNER);
95 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){
96 if(PTL1X(pa, 2) != PTL1X(va, 2))
97 l1[PTL1X(pa, 2)] = PADDR(&l1[L1TABLEX(pa, 1)]) | PTEVALID | PTETABLE;
100 for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){
101 if(PTL1X(pa, 3) != PTL1X(va, 3))
102 l1[PTL1X(pa, 3)] = PADDR(&l1[L1TABLEX(pa, 2)]) | PTEVALID | PTETABLE;
104 setttbr(PADDR(&l1[L1TABLEX(0, PTLEVELS-1)]));
110 m->mmul1 = mallocalign(L1SIZE+L1TOPSIZE, BY2PG, L1SIZE, 0);
112 panic("mmu1init: no memory for mmul1");
113 memset(m->mmul1, 0, L1SIZE+L1TOPSIZE);
120 if((uintptr)va >= KZERO)
121 return (uintptr)va-KZERO;
122 panic("paddr: va=%#p pc=%#p", va, getcallerpc(&va));
129 if(pa < (uintptr)-KZERO)
137 if(pa < (uintptr)-KZERO)
138 return (void*)(pa + KZERO);
139 panic("kaddr: pa=%#p pc=%#p", pa, getcallerpc(&pa));
160 mmukmap(uintptr va, uintptr pa, usize size)
162 uintptr a, pe, off, attr;
167 attr = va & PTEMA(7);
171 pe = (pa + size + (PGLSZ(1)-1)) & -PGLSZ(1);
173 ((uintptr*)L1)[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | PTEWRITE | PTEAF
174 | PTEKERNEL | PTESH(SHARE_OUTER) | attr;
183 mmuwalk(uintptr va, int level)
189 x = PTLX(va, PTLEVELS-1);
190 table = &m->mmul1[L1TABLEX(va, PTLEVELS-1)];
191 for(i = PTLEVELS-2; i >= level; i--){
194 if(pte & (0xFFFFULL<<48))
195 iprint("strange pte %#p va %#p\n", pte, va);
196 pte &= ~(0xFFFFULL<<48 | BY2PG-1);
202 up->mmufree = pg->next;
203 pg->va = va & -PGLSZ(i+1);
204 if((pg->next = up->mmuhead[i+1]) == nil)
205 up->mmutail[i+1] = pg;
206 up->mmuhead[i+1] = pg;
207 memset(KADDR(pg->pa), 0, BY2PG);
209 table[x] = pg->pa | PTEVALID | PTETABLE;
210 table = KADDR(pg->pa);
212 x = PTLX(va, (uintptr)i);
217 static Proc *asidlist[256];
233 a %= nelem(asidlist);
235 continue; // reserved
237 if(x == p || x == nil || (x->asid < 0 && x->mach == nil))
255 if(a > 0 && asidlist[a] == p)
264 * Prevent the following scenario:
265 * pX sleeps on cpuA, leaving its page tables in mmul1
266 * pX wakes up on cpuB, and exits, freeing its page tables
267 * pY on cpuB allocates a freed page table page and overwrites with data
268 * cpuA takes an interrupt, and is now running with bad page tables
269 * In theory this shouldn't hurt because only user address space tables
270 * are affected, and mmuswitch will clear mmul1 before a user process is
271 * dispatched. But empirically it correlates with weird problems, eg
272 * resetting of the core clock at 0x4000001C which confuses local timers.
282 putmmu(uintptr va, uintptr pa, Page *pg)
288 while((pte = mmuwalk(va, 0)) == nil){
290 assert(up->mmufree == nil);
291 up->mmufree = newpage(0, nil, 0);
296 if((old & PTEVALID) != 0)
297 flushasidvall((uvlong)up->asid<<48 | va>>12);
299 flushasidva((uvlong)up->asid<<48 | va>>12);
300 *pte = pa | PTEPAGE | PTEUSER | PTENG | PTEAF | PTESH(SHARE_INNER);
301 if(pg->txtflush & (1UL<<m->machno)){
302 /* pio() sets PG_TXTFLUSH whenever a text pg has been written */
303 cachedwbinvse((void*)KADDR(pg->pa), BY2PG);
304 cacheiinvse((void*)va, BY2PG);
305 pg->txtflush &= ~(1UL<<m->machno);
317 for(i=1; i<PTLEVELS; i++){
318 if(p->mmuhead[i] == nil)
320 p->mmutail[i]->next = p->mmufree;
321 p->mmufree = p->mmuhead[i];
322 p->mmuhead[i] = p->mmutail[i] = nil;
332 for(va = UZERO; va < USTKTOP; va += PGLSZ(PTLEVELS-1))
333 m->mmul1[PTL1X(va, PTLEVELS-1)] = 0;
336 setttbr(PADDR(&m->mmul1[L1TABLEX(0, PTLEVELS-1)]));
345 for(t = p->mmuhead[PTLEVELS-1]; t != nil; t = t->next){
347 m->mmul1[PTL1X(va, PTLEVELS-1)] = t->pa | PTEVALID | PTETABLE;
351 flushasid((uvlong)p->asid<<48);
353 setttbr((uvlong)p->asid<<48 | PADDR(&m->mmul1[L1TABLEX(0, PTLEVELS-1)]));
364 if((t = p->mmufree) != nil){
366 p->mmufree = t->next;
368 panic("mmurelease: bad page ref");
370 } while((t = p->mmufree) != nil);
387 checkmmu(uintptr, uintptr)