## 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)<<PGSHIFT;
nextio = (uchar*) (KZERO|bootconf->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)|KZERO);
pt[LVL3OFF(va)] = FIXPTE(pa);
/* flush cached mmu entries */
tlbflush(3, va);
icflush();
splx(s);
}
void *
kmapv(uvlong pa, int size)
{
void *va, *new;
int lvl2off, i, npage, offset;
uvlong *lvl2, *pt;
offset = pa&(BY2PG-1);
npage = ((size+offset+BY2PG-1)>>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)<<PGSHIFT)|KZERO);
pt[LVL3OFF(nextio)] = PTEPFN(pa) | PTEKVALID | PTEASM;
nextio += BY2PG;
pa += BY2PG;
}
return va;
}
void
flushmmu(void)
{
int s;
s = splhi();
up->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();
}
.
|