void mmuinit(void) { PTE *l1, *l2; uintptr pa, va; l1 = (PTE*)PADDR(L1); l2 = (PTE*)PADDR(L2); /* map all of ram at KZERO */ va = KZERO; for(pa = PHYSDRAM; pa < PHYSDRAM+DRAMSIZE; pa += MiB){ l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|Cached|Buffered; va += MiB; } /* identity map first MB of ram so mmu can be enabled */ l1[L1X(PHYSDRAM)] = PHYSDRAM|Dom0|L1AP(Krw)|Section|Cached|Buffered; /* map i/o registers */ va = VIRTIO; for(pa = PHYSIO; pa < PHYSIO+IOSIZE; pa += MiB){ l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section; va += MiB; } /* double map exception vectors at top of virtual memory */ va = HVECTORS; l1[L1X(va)] = (uintptr)l2|Dom0|Coarse; l2[L2X(va)] = PHYSDRAM|L2AP(Krw)|Small; }
void mmuinit(void) { uintptr pa; PTE *l1, *l2; pa = ttbget(); l1 = KADDR(pa); /* redundant with l.s; only covers first MB of 17MB */ l1[L1X(VIRTIO)] = PHYSIO|Dom0|L1AP(Krw)|Section; idmap(l1, PHYSETHER); /* igep 9221 ethernet regs */ idmap(l1, PHYSL4PROT); idmap(l1, PHYSL3); idmap(l1, PHYSSMS); idmap(l1, PHYSDRC); idmap(l1, PHYSGPMC); /* map high vectors to start of dram, but only 4K, not 1MB */ pa -= MACHSIZE+2*1024; l2 = KADDR(pa); memset(l2, 0, 1024); /* vectors step on u-boot, but so do page tables */ l2[L2X(HVECTORS)] = PHYSDRAM|L2AP(Krw)|Small; l1[L1X(HVECTORS)] = pa|Dom0|Coarse; /* vectors -> ttb-machsize-2k */ coherence(); cacheuwbinv(); l2cacheuwbinv(); mmuinvalidate(); m->mmul1 = l1; // mmudump(l1); /* DEBUG */ }
/* map `mbs' megabytes from virt to phys */ void mmumap(uintptr virt, uintptr phys, int mbs) { uint off; PTE *l1; phys &= ~(MB-1); virt &= ~(MB-1); l1 = KADDR(ttbget()); for (off = 0; mbs-- > 0; off += MB) l1[L1X(virt + off)] = (phys + off) | Dom0 | L1AP(Krw) | Section; cacheuwbinv(); l2cacheuwbinv(); mmuinvalidate(); }
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; }
/* identity map the megabyte containing va, uncached */ static void idmap(PTE *l1, ulong va) { va &= ~(MB-1); l1[L1X(va)] = va | Dom0 | L1AP(Krw) | Section; }