void* mmuuncache(void* v, usize size) { int x; PTE *pte; uintptr va; /* * Simple helper for ucalloc(). * Uncache a Section, must already be * valid in the MMU. */ va = PTR2UINT(v); assert(!(va & (1*MiB-1)) && size == 1*MiB); x = L1X(va); pte = &m->mmul1[x]; if((*pte & (Fine|Section|Coarse)) != Section) return nil; *pte &= ~(Cached|Buffered); mmuinvalidateaddr(va); cachedwbinvse(pte, 4); return v; }
uintptr mmukunmap(uintptr va, uintptr pa, usize size) { int x; PTE *pte; /* * Stub. */ assert(!(va & (1*MiB-1)) && !(pa & (1*MiB-1)) && size == 1*MiB); x = L1X(va); pte = &m->mmul1[x]; if(*pte != (pa|Dom0|L1AP(Krw)|Section)) return 0; *pte = Fault; mmuinvalidateaddr(va); cachedwbinvse(pte, 4); return va; }
uintptr mmukmap(uintptr va, uintptr pa, uint size) { int o; uint n; PTE *pte, *pte0; assert((va & (MiB-1)) == 0); o = pa & (MiB-1); pa -= o; size += o; pte = pte0 = &m->mmul1[L1X(va)]; for(n = 0; n < size; n += MiB) if(*pte++ != Fault) return 0; pte = pte0; for(n = 0; n < size; n += MiB){ *pte++ = (pa+n)|Dom0|L1AP(Krw)|Section; mmuinvalidateaddr(va+n); } cachedwbse(pte0, pte - pte0); return va + o; }
void putmmu(uintptr va, uintptr pa, Page* page) { int x; Page *pg; PTE *l1, *pte; x = L1X(va); l1 = &m->mmul1[x]; if(*l1 == Fault){ /* wasteful - l2 pages only have 256 entries - fix */ if(up->mmul2cache == nil){ /* auxpg since we don't need much? memset if so */ pg = newpage(1, 0, 0); pg->va = VA(kmap(pg)); } else{ pg = up->mmul2cache; up->mmul2cache = pg->next; memset(UINT2PTR(pg->va), 0, BY2PG); } pg->daddr = x; pg->next = up->mmul2; up->mmul2 = pg; /* force l2 page to memory */ cachedwbse((void *)pg->va, BY2PG); *l1 = PPN(pg->pa)|Dom0|Coarse; cachedwbse(l1, sizeof *l1); if(x >= m->mmul1lo && x < m->mmul1hi){ if(x+1 - m->mmul1lo < m->mmul1hi - x) m->mmul1lo = x+1; else m->mmul1hi = x; } } pte = UINT2PTR(KADDR(PPN(*l1))); /* protection bits are * PTERONLY|PTEVALID; * PTEWRITE|PTEVALID; * PTEWRITE|PTEUNCACHED|PTEVALID; */ x = Small; if(!(pa & PTEUNCACHED)) x |= Cached|Buffered; if(pa & PTEWRITE) x |= L2AP(Urw); else x |= L2AP(Uro); pte[L2X(va)] = PPN(pa)|x; cachedwbse(&pte[L2X(va)], sizeof pte[0]); /* clear out the current entry */ mmuinvalidateaddr(PPN(va)); /* write back dirty entries - we need this because the pio() in * fault.c is writing via a different virt addr and won't clean * its changes out of the dcache. Page coloring doesn't work * on this mmu because the virtual cache is set associative * rather than direct mapped. */ cachedwbinv(); if(page->txtflush){ cacheiinv(); page->txtflush = 0; } checkmmu(va, PPN(pa)); }