Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/alphapc/mmu.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## 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();
}

.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].