void mmurelease(Proc* proc) { Page *page, *next; /* write back dirty and invalidate l1 caches */ cacheuwbinv(); mmul2empty(proc, 0); for(page = proc->mmul2cache; page != nil; page = next){ next = page->next; if(--page->ref) panic("mmurelease: page->ref %d", page->ref); pagechainhead(page); } if(proc->mmul2cache && palloc.r.p) wakeup(&palloc.r); proc->mmul2cache = nil; mmul1empty(); /* make sure map is in memory */ /* could be smarter about how much? */ cachedwbse(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE)); /* lose any possible stale tlb entries */ mmuinvalidate(); }
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 */ }
/* * exit kernel either on a panic or user request */ void exit(int ispanic) { void (*f)(void); USED(ispanic); delay(1000); iprint("it's a wonderful day to die\n"); cacheflush(); mmuinvalidate(); mmudisable(); f = nil; (*f)(); }
void mmuinit1(void) { PTE *l1; l1 = (PTE*)L1; m->mmul1 = l1; /* * undo identity map of first MB of ram */ l1[L1X(PHYSDRAM)] = 0; cachedwbse(&l1[L1X(PHYSDRAM)], sizeof(PTE)); mmuinvalidate(); }
/* 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(); }
void mmuswitch(Proc* proc) { int x; PTE *l1; Page *page; /* do kprocs get here and if so, do they need to? */ if(m->mmupid == proc->pid && !proc->newtlb) return; m->mmupid = proc->pid; /* write back dirty and invalidate l1 caches */ cacheuwbinv(); if(proc->newtlb){ mmul2empty(proc, 1); proc->newtlb = 0; } mmul1empty(); /* move in new map */ l1 = m->mmul1; for(page = proc->mmul2; page != nil; page = page->next){ x = page->daddr; l1[x] = PPN(page->pa)|Dom0|Coarse; /* know here that L1lo < x < L1hi */ if(x+1 - m->mmul1lo < m->mmul1hi - x) m->mmul1lo = x+1; else m->mmul1hi = x; } /* make sure map is in memory */ /* could be smarter about how much? */ cachedwbse(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE)); /* lose any possible stale tlb entries */ mmuinvalidate(); //print("mmuswitch l1lo %d l1hi %d %d\n", // m->mmul1lo, m->mmul1hi, proc->kp); }
void main(void) { mmuinvalidate(); /* zero out bss */ memset(edata, 0, end-edata); /* point to Mach structure */ m = (Mach*)MACHADDR; memset(m, 0, sizeof(Mach)); m->ticks = 1; active.machs = 1; rs232power(1); quotefmtinstall(); iprint("\nPlan 9 bitsy kernel\n"); confinit(); xinit(); mmuinit(); machinit(); trapinit(); sa1110_uartsetup(1); dmainit(); screeninit(); printinit(); /* from here on, print works, before this we need iprint */ clockinit(); procinit0(); initseg(); links(); chandevreset(); pageinit(); swapinit(); userinit(); powerinit(); schedinit(); }