## diffname alphapc/mmu.c 1999/0415 ## diff -e /dev/null /n/emeliedump/1999/0415/sys/src/brazil/alphapc/mmu.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "/sys/src/boot/alphapc/conf.h" static uvlong origlvl1; /* physical address */ static uvlong klvl2; /* physical, as created by boot loader */ static uchar *nextio; /* next virtual address to be allocated by kmapv */ extern Bootconf *bootconf; #define LVL2OFF(v) ((((long)(v))>>(2*PGSHIFT-3))&(PTE2PG-1)) #define LVL3OFF(v) ((((long)(v))>>(PGSHIFT))&(PTE2PG-1)) static void setptb(ulong pa) { m->ptbr = (uvlong)pa>>PGSHIFT; swpctx(m); } void mmuinit(void) { uvlong *plvl2; /* set PCB to new one in mach structure before stomping on old one */ m->usp = 0; m->fen = 1; m->ptbr = bootconf->pcb->ptbr; origlvl1 = (m->ptbr << PGSHIFT); setpcb(m); plvl2 = (uvlong*) (KZERO|origlvl1|(BY2PG-8)); klvl2 = (*plvl2 >> 32)<maxphys); } /* * Called splhi, not in Running state */ void mmuswitch(Proc *p) { Page *pg; uvlong *lvl2; if(p->newtlb){ /* * newtlb set means that they are inconsistent * with the segment.c data structures. * * bin the current 3rd level page tables and * the pointers to them in the 2nd level page. * pg->daddr is used by putmmu to save the offset into * the 2nd level page. */ if(p->mmutop && p->mmuused){ lvl2 = (uvlong*)p->mmulvl2->va; for(pg = p->mmuused; pg->next; pg = pg->next) lvl2[pg->daddr] = 0; lvl2[pg->daddr] = 0; pg->next = p->mmufree; p->mmufree = p->mmuused; p->mmuused = 0; } p->newtlb = 0; } /* tell processor about new page table and flush cached entries */ if(p->mmutop == 0) setptb(origlvl1); else setptb(p->mmutop->pa); tlbflush(-1, 0); icflush(); } /* * give all page table pages back to the free pool. This is called in sched() * with palloc locked. */ void mmurelease(Proc *p) { Page *pg; Page *next; if(canlock(&palloc)) panic("mmurelease"); /* point to protoype page map */ setptb(origlvl1); icflush(); /* give away page table pages */ for(pg = p->mmuused; pg; pg = next){ next = pg->next; pg->next = p->mmufree; p->mmufree = pg; } p->mmuused = 0; if(p->mmutop) { p->mmutop->next = p->mmufree; p->mmufree = p->mmutop; p->mmutop = 0; } if(p->mmulvl2) { p->mmulvl2->next = p->mmufree; p->mmufree = p->mmulvl2; p->mmulvl2 = 0; } for(pg = p->mmufree; pg; pg = next){ next = pg->next; if(--pg->ref) panic("mmurelease: pg->ref %d\n", pg->ref); pagechainhead(pg); } if(p->mmufree && palloc.r.p) wakeup(&palloc.r); p->mmufree = 0; } void mmunewtop(void) { Page *top, *lvl2; uvlong *ppte; top = newpage(1, 0, 0); top->va = VA(kmap(top)); lvl2 = newpage(1, 0, 0); lvl2->va = VA(kmap(lvl2)); ppte = (uvlong *)top->va; ppte[0] = PTEPFN(lvl2->pa) | PTEKVALID; ppte[PTE2PG-2] = PTEPFN(top->pa) | PTEKVALID; ppte[PTE2PG-1] = PTEPFN(klvl2) | PTEKVALID; up->mmutop = top; up->mmulvl2 = lvl2; setptb(top->pa); tlbflush(-1, 0); icflush(); } void putmmu(ulong va, ulong pa, Page *pg) { int lvl2off; uvlong *lvl2, *pt; int s; if(up->mmutop == 0) mmunewtop(); lvl2 = (uvlong*)up->mmulvl2->va; lvl2off = LVL2OFF(va); /* * if bottom level page table missing, allocate one * and point the top level page at it. */ s = splhi(); if(lvl2[lvl2off] == 0){ if(up->mmufree == 0){ spllo(); pg = newpage(1, 0, 0); pg->va = VA(kmap(pg)); splhi(); } else { pg = up->mmufree; up->mmufree = pg->next; memset((void*)pg->va, 0, BY2PG); } lvl2[lvl2off] = PTEPFN(pg->pa) | PTEVALID; pg->daddr = lvl2off; pg->next = up->mmuused; up->mmuused = pg; } /* * put in new mmu entry */ pt = (uvlong*)(((lvl2[lvl2off] >> 32)<>PGSHIFT); va = nextio+offset; lvl2 = (uvlong*)(KZERO|klvl2); for (i = 0; i < npage; i++) { lvl2off = LVL2OFF(nextio); if (lvl2[lvl2off] == 0) { new = xspanalloc(BY2PG, BY2PG, 0); memset(new, 0, BY2PG); lvl2[lvl2off] = PTEPFN(PADDR(new)) | PTEKVALID | PTEASM; } pt = (uvlong*)(((lvl2[lvl2off] >> 32)<newtlb = 1; mmuswitch(up); splx(s); } ulong upamalloc(...) { panic("upamalloc"); } void upafree(...) { panic("upafree"); } . ## diffname alphapc/mmu.c 1999/0511 ## diff -e /n/emeliedump/1999/0415/sys/src/brazil/alphapc/mmu.c /n/emeliedump/1999/0511/sys/src/brazil/alphapc/mmu.c 238c void *va; /* * Viability hack. return kmapv(((uvlong)space<<32LL)|offset, size); return kmapio(0x88, addr, len); */ USED(align); print("upa0: pa %luX size %d, align %d nextio %luX\n", pa, size, align, nextio); va = kmapv(((uvlong)0x88<<32LL)|pa, size); print("upa1: va %luX nextio %luX\n", va, nextio); if(va == nil) return 0; return PADDR(va); . 236c upamalloc(ulong pa, int size, int align) . ## diffname alphapc/mmu.c 1999/0512 ## diff -e /n/emeliedump/1999/0511/sys/src/brazil/alphapc/mmu.c /n/emeliedump/1999/0512/sys/src/brazil/alphapc/mmu.c 248d 246d 244a if(pa == 0) return 0; . 241,243c * Viability hack. Only for PCI frambuffers. . ## diffname alphapc/mmu.c 2000/0401 ## diff -e /n/emeliedump/1999/0512/sys/src/brazil/alphapc/mmu.c /n/emeliedump/2000/0401/sys/src/9/alphapc/mmu.c 255c print("upafree: virtual mapping not freed\n"); . 253c upafree(ulong, int) . ## diffname alphapc/mmu.c 2000/0517 ## diff -e /n/emeliedump/2000/0401/sys/src/9/alphapc/mmu.c /n/emeliedump/2000/0517/sys/src/9/alphapc/mmu.c 241c * Viability hack. Only for PCI framebuffers. . ## diffname alphapc/mmu.c 2001/0727 ## diff -e /n/emeliedump/2000/0517/sys/src/9/alphapc/mmu.c /n/emeliedump/2001/0727/sys/src/9/alphapc/mmu.c 256a void mmudump(void) { Page *top, *lvl2; iprint("ptbr %lux up %lux\n", (ulong)m->ptbr, up); if(up) { top = up->mmutop; if(top != nil) iprint("top %lux top[N-1] %lux\n", top->va, ((uvlong *)top->va)[PTE2PG-1]); lvl2 = up->mmulvl2; if(lvl2 != nil) iprint("lvl2 %lux\n", lvl2->va); } } . ## diffname alphapc/mmu.c 2001/0728 ## diff -e /n/emeliedump/2001/0727/sys/src/9/alphapc/mmu.c /n/emeliedump/2001/0728/sys/src/9/alphapc/mmu.c 123c proc->mmufree = 0; . 115,121c if(proc->mmufree && palloc.r.p) . 110,113c for(page = proc->mmufree; page; page = next){ next = page->next; if(--page->ref) panic("mmurelease: page->ref %d\n", page->ref); pagechainhead(page); . 104,108c if(proc->mmulvl2) { proc->mmulvl2->next = proc->mmufree; proc->mmufree = proc->mmulvl2; proc->mmulvl2 = 0; . 98,102c mmuptefree(proc); proc->mmuused = 0; if(proc->mmutop) { proc->mmutop->next = proc->mmufree; proc->mmufree = proc->mmutop; proc->mmutop = 0; . 91,93d 88,89c Page *page, *next; . 86c mmurelease(Proc *proc) . 76c setptb(proc->mmutop->pa); . 73c if(proc->mmutop == 0) . 71a void mmuswitch(Proc *proc) { if(proc->newtlb){ mmuptefree(proc); proc->newtlb = 0; } . 70a } . 69c *last = proc->mmufree; proc->mmufree = proc->mmuused; proc->mmuused = 0; . 50,67c if(proc->mmutop && proc->mmuused){ lvl2 = (uvlong*)proc->mmulvl2->va; last = &proc->mmuused; for(page = *last; page; page = page->next){ lvl2[page->daddr] = 0; last = &page->next; . 48a Page **last, *page; . 47d 41,45c static void mmuptefree(Proc* proc) . ## diffname alphapc/mmu.c 2001/1121 ## diff -e /n/emeliedump/2001/0728/sys/src/9/alphapc/mmu.c /n/emeliedump/2001/1121/sys/src/9/alphapc/mmu.c 254c iprint("top %lux top[N-1] %llux\n", top->va, ((uvlong *)top->va)[PTE2PG-1]); . ## diffname alphapc/mmu.c 2002/0116 ## diff -e /n/emeliedump/2001/1121/sys/src/9/alphapc/mmu.c /n/emeliedump/2002/0116/sys/src/9/alphapc/mmu.c 86,89c mmupark(); . 76a /* point to protoype page map */ void mmupark(void) { setptb(origlvl1); icflush(); } .