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

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


## diffname carrera/mmu.c 1993/0903
## diff -e /dev/null /n/fornaxdump/1993/0903/sys/src/brazil/carrera/mmu.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"

/*
 *  tlb entry 0 is used only by mmuswitch() to set the current tlb pid.
 */

/*
 *  Kmap entries start at tlb index 1 and work their way up until
 *  kmapinval() removes them.  They then restart at 1.  As long as there
 *  are few kmap entries they will not pass TLBROFF (the WIRED tlb entry
 *  limit) and interfere with user tlb entries.
 */

/*
 *  All invalidations of the tlb are via indexed entries.  The virtual
 *  address used is always 'KZERO | (x<<(PGSHIFT+1) | currentpid' where
 *  'x' is the index into the tlb.  This ensures that the current pid doesn't
 *  change and that no two invalidated entries have matching virtual
 *  addresses just in case SGI/MIPS ever makes a chip that cares (as
 *  they keep threatening).  These entries should never be used in
 *  lookups since accesses to KZERO addresses don't go through the tlb.
 */

#define TLBINVAL(x, pid) puttlbx(x, KZERO|((x)<<(PGSHIFT+1))|(pid), 0, 0, PGSZ4K)

void
tlbinit(void)
{
	int i;

	for(i=0; i<NTLB; i++)
		TLBINVAL(i, 0);
}

Lock	kmaplock;
KMap	kpte[KPTESIZE];
KMap*	kmapfree;

void
kmapinit(void)
{
	KMap *k, *klast;

	lock(&kmaplock);
	kmapfree = kpte;
	klast = &kpte[KPTESIZE-1];
	for(k=kpte; k<klast; k++)
		k->next = k+1;
	k->next = 0;
	unlock(&kmaplock);
}

/*
 *  Arrange that the KMap'd virtual address will hit the same
 *  primary cache line as pg->va by making bits 14...12 of the
 *  tag the same as virtual address.  These bits are the index
 *  into the primary cache and are checked whenever accessing
 *  the secondary cache through the primary.  Violation causes
 *  a VCE trap.
 */
KMap *
kmap(Page *pg)
{
	int s;
	KMap *k;
	ulong pte;
	ulong x, virt;

	s = splhi();
	lock(&kmaplock);

	if(kmapfree == 0)
		panic("out of kmap");

	k = kmapfree;
	kmapfree = k->next;

	k->pg = pg;
	/* One for the allocation,
	 * One for kactive
	 */
	k->ref = 2;
	k->konmach[m->machno] = m->kactive;
	m->kactive = k;

	virt = pg->va;
	/* bits 14..12 form the secondary-cache virtual index */
	virt &= PIDX;	
	virt |= KMAPADDR | ((k-kpte)<<KMAPSHIFT);

	k->virt = virt;
	pte = PPN(pg->pa)|PTECOHERXCLW|PTEGLOBL|PTEWRITE|PTEVALID;
	if(virt & BY2PG) {
		k->phys0 = PTEGLOBL;
		k->phys1 = pte;
	}
	else {
		k->phys0 = pte;
		k->phys1 = PTEGLOBL;
	}

	x = m->ktlbnext;
	puttlbx(x, (virt & ~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K);
	m->ktlbx[x] = 1;
	if(++x >= NTLB)
		m->ktlbnext = 1;
	else
		m->ktlbnext = x;

	unlock(&kmaplock);

	splx(s);
	return k;
}

void
kunmap(KMap *k)
{
	int s;

	s = splhi();
	if(decref(k) == 0) {
		k->virt = 0;
		k->phys0 = 0;
		k->phys1 = 0;
		k->pg = 0;

		lock(&kmaplock);
		k->next = kmapfree;
		kmapfree = k;
		unlock(&kmaplock);
	}
	splx(s);
}

void
kfault(ulong addr)
{
	KMap *k, *f;
	ulong x, index;

	index = (addr & ~KSEGM) >> KMAPSHIFT;
	if(index >= KPTESIZE)
		panic("kmapfault: %lux", addr);

	k = &kpte[index];
	if(k->virt == 0)
		panic("kmapfault: unmapped %lux", addr);

	for(f = m->kactive; f; f = f->konmach[m->machno])
		if(f == k)
			break;
	if(f == 0) {
		incref(k);
		k->konmach[m->machno] = m->kactive;
		m->kactive = k;
	}

	x = m->ktlbnext;
	puttlbx(x, (k->virt & ~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K);
	m->ktlbx[x] = 1;
	if(++x >= NTLB)
		m->ktlbnext = 1;
	else
		m->ktlbnext = x;
}

void
kmapinval()
{
	int mno, i;
	KMap *k, *next;
	int curpid;
	uchar *ktlbx;


	if(m->kactive == 0)
		return;

	curpid = PTEPID(TLBPID(tlbvirt()));
	ktlbx = m->ktlbx;
	for(i = 0; i < NTLB; i++, ktlbx++){
		if(*ktlbx == 0)
			continue;
		TLBINVAL(i, curpid);
		*ktlbx = 0;
	}

	mno = m->machno;
	for(k = m->kactive; k; k = next) {
		next = k->konmach[mno];
		kunmap(k);
	}
	m->kactive = 0;
	m->ktlbnext = 1;
}

void
mmuswitch(Proc *p)
{
	int tp;

	if(p->newtlb) {
		memset(p->pidonmach, 0, sizeof p->pidonmach);
		p->newtlb = 0;
	}
	tp = p->pidonmach[m->machno];
	if(tp == 0)
		tp = newtlbpid(p);
	puttlbx(0, KZERO|PTEPID(tp), 0, 0, PGSZ4K);
}

void
mmurelease(Proc *p)
{
	memset(p->pidonmach, 0, sizeof p->pidonmach);
}

/*
 * Process must be splhi
 */
int
newtlbpid(Proc *p)
{
	int i, s;
	Proc **h;

	i = m->lastpid;
	h = m->pidproc;
	for(s = 0; s < NTLBPID; s++) {
		i++;
		if(i >= NTLBPID)
			i = 1;
		if(h[i] == 0)
			break;
	}

	if(h[i])
		purgetlb(i);
	if(h[i] != 0)
		panic("newtlb");

	m->pidproc[i] = p;
	p->pidonmach[m->machno] = i;
	m->lastpid = i;

	return i;
}

void
putmmu(ulong tlbvirt, ulong tlbphys, Page *pg)
{
	short tp;
	char *ctl;
	Softtlb *entry;
	int s;

	s = splhi();
	tp = up->pidonmach[m->machno];
	if(tp == 0)
		tp = newtlbpid(up);

	tlbvirt |= PTEPID(tp);
	if((tlbphys & PTEALGMASK) != PTEUNCACHED) {
		tlbphys &= ~PTEALGMASK;
		tlbphys |= PTECOHERXCLW;
	}

	entry = putstlb(tlbvirt, tlbphys);
	puttlb(entry->virt, entry->phys0, entry->phys1);

	ctl = &pg->cachectl[m->machno];
	if(*ctl == PG_TXTFLUSH) {
		icflush((void*)pg->va, BY2PG);
		*ctl = PG_NOFLUSH;
	}
	splx(s);
}

void
purgetlb(int pid)
{
	int i, mno;
	Proc *sp, **pidproc;
	Softtlb *entry, *etab;

	m->tlbpurge++;

	/*
	 * find all pid entries that are no longer used by processes
	 */
	mno = m->machno;
	pidproc = m->pidproc;
	for(i=1; i<NTLBPID; i++) {
		sp = pidproc[i];
		if(sp && sp->pidonmach[mno] != i)
			pidproc[i] = 0;
	}

	/*
	 * shoot down the one we want
	 */
	sp = pidproc[pid];
	if(sp != 0)
		sp->pidonmach[mno] = 0;
	pidproc[pid] = 0;

	/*
	 * clean out all dead pids from the stlb;
	 */
	entry = m->stb;
	for(etab = &entry[STLBSIZE]; entry < etab; entry++)
		if(pidproc[TLBPID(entry->virt)] == 0)
			entry->virt = 0;

	/*
	 * clean up the hardware
	 */
	for(i=TLBROFF; i<NTLB; i++)
		if(pidproc[TLBPID(gettlbvirt(i))] == 0)
			TLBINVAL(i, pid);
}

void
flushmmu(void)
{
	int s;

	s = splhi();
	up->newtlb = 1;
	mmuswitch(up);
	splx(s);
}

void
clearmmucache(void)
{
}

Softtlb*
putstlb(ulong tlbvirt, ulong tlbphys)
{
	int k;
	Softtlb *entry;

	k = tlbvirt & BY2PG;
	tlbvirt &= ~BY2PG;

	entry = &m->stb[(tlbvirt ^ (tlbvirt>>13)) & (STLBSIZE-1)];
	if(entry->virt != tlbvirt) {
		entry->virt = tlbvirt;
		entry->phys0 = 0;
		entry->phys1 = 0;
	}

	if(k)
		entry->phys1 = tlbphys;
	else
		entry->phys0 = tlbphys;

	if(entry->phys0 == 0 && entry->phys1 == 0)
		entry->virt = 0;

	return entry;
}
.
## diffname carrera/mmu.c 1993/0904
## diff -e /n/fornaxdump/1993/0903/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/0904/sys/src/brazil/carrera/mmu.c
199c
	m->ktlbnext = TLBROFF;
.
167c
		m->ktlbnext = TLBROFF;
.
110c
		m->ktlbnext = TLBROFF;
.
54a

	m->ktlbnext = TLBROFF;
.
## diffname carrera/mmu.c 1993/0905
## diff -e /n/fornaxdump/1993/0904/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/0905/sys/src/brazil/carrera/mmu.c
188c
	for(i = TLBROFF; i < NTLB; i++, ktlbx++){
.
105c
		k->phys1 = PTEGLOBL|PTECOHERXCLW;
.
100c
		k->phys0 = PTEGLOBL|PTECOHERXCLW;
.
## diffname carrera/mmu.c 1993/0906
## diff -e /n/fornaxdump/1993/0905/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/0906/sys/src/brazil/carrera/mmu.c
166c
	virt = (k->virt&~BY2PG)|TLBPID(tlbvirt());
	puttlbx(x, virt, k->phys0, k->phys1, PGSZ4K);

.
148c
	index = (addr & ~KMAPADDR) >> KMAPSHIFT;
.
146c
	ulong x, index, virt;
.
## diffname carrera/mmu.c 1993/0915
## diff -e /n/fornaxdump/1993/0906/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/0915/sys/src/brazil/carrera/mmu.c
270a
	/*
	 * Fix up EISA memory address which are greater
	 * than 32 bits physical: 0x100000000
	 */
	if((tlbphys&0xffff0000) == PPN(Eisamphys)) {
		tlbphys &= ~PPN(Eisamphys);
		tlbphys |= 0x04000000;
	}
.
264d
260a
	int s;
.
5a
#include	"io.h"
.
## diffname carrera/mmu.c 1993/1013
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1013/sys/src/brazil/carrera/mmu.c
148a
	addr = ur->badvaddr;
.
147a
	ulong addr;
.
144c
kfault(Ureg *ur)
.
6a
#include	"ureg.h"
.
## diffname carrera/mmu.c 1993/1208
## diff -e /n/fornaxdump/1993/1013/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1208/sys/src/brazil/carrera/mmu.c
130a
puttlb((k->virt & ~BY2PG) | TLBPID(tlbvirt()), k->phys0 & ~PTEVALID, k->phys1 & ~PTEVALID);
.
## diffname carrera/mmu.c 1993/1209
## diff -e /n/fornaxdump/1993/1208/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1209/sys/src/brazil/carrera/mmu.c
298a
((ulong*)0xA0090000)[8] = 0x6000;
.
297a
((ulong*)0xA0090000)[8] = 0x5000;
.
296a
((ulong*)0xA0090000)[8] = 0x4000;
.
295a
((ulong*)0xA0090000)[8] = 0x3000;
.
294a
ulong tlb[4];
extern int gettlbp(ulong, ulong*);
extern ulong tlbvirt(void);
((ulong*)0xA0090000)[6] = tlbphys;
((ulong*)0xA0090000)[7] = pg->va;
((ulong*)0xA0090000)[8] = 0x2000;
		if(gettlbp((pg->va & ~BY2PG)|TLBPID(tlbvirt()), tlb) < 0){
			print("entry->virt %lux pg->va %lux\n", entry->virt, pg->va);
			panic("icflush not in TLB");
		}
if(pg->va == 0x19000) {
print("xx>> virt %lux phys0 %lux phys1 %lux\n", tlb[0],tlb[1],tlb[2]);
}
.
293a
((ulong*)0xA0090000)[8] = 0x1000;
((ulong*)0xA0090000)[5] = tlbvirt;
.
8a
Mach	machstruct[100];

.
## diffname carrera/mmu.c 1993/1210
## diff -e /n/fornaxdump/1993/1209/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1210/sys/src/brazil/carrera/mmu.c
309c
if(0 && pg->va == 0x19000) {
.
133d
## diffname carrera/mmu.c 1993/1211
## diff -e /n/fornaxdump/1993/1210/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1211/sys/src/brazil/carrera/mmu.c
318d
316d
314d
312d
298,310d
295,296c
	if(*ctl == PG_DATFLUSH) {
		dcflush((void*)pg->va, BY2PG);
		*ctl = PG_NOFLUSH;
	}else
.
209d
195,196c
	ktlbx = m->ktlbx+TLBROFF;
	for(i = TLBROFF; i < NTLB; i++, ktlbx++) {
.
190d
187d
185c
	int mno, i, curpid;
.
9,10d
## diffname carrera/mmu.c 1993/1212
## diff -e /n/fornaxdump/1993/1211/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1212/sys/src/brazil/carrera/mmu.c
296a
		break;
.
293,295c
		break;
	case PG_NEWCOL:
		cleancache();		/* Too expensive */
.
290c
	switch(*ctl) {
	case PG_TXTFLUSH:
		icflush((void*)pg->va, BY2PG);
		*ctl = PG_NOFLUSH;
		break;
	case PG_DATFLUSH:
.
## diffname carrera/mmu.c 1993/1213
## diff -e /n/fornaxdump/1993/1212/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1213/sys/src/brazil/carrera/mmu.c
148,149c
	ulong x, index, virt, addr;
.
## diffname carrera/mmu.c 1993/1218
## diff -e /n/fornaxdump/1993/1213/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1218/sys/src/brazil/carrera/mmu.c
200a
		TLBINVAL(k->tlbi[mno], curpid);
.
190,197d
184d
182c
	int mno, curpid;
.
172d
170a
	k->tlbi[mno] = x;
.
164c
		k->konmach[mno] = m->kactive;
.
161a

.
159c
	for(f = m->kactive; f; f = f->konmach[mno])
.
151a

.
149a
	mno = m->machno;
.
146a
	int mno;
.
111,112c
	k->tlbi[m->machno] = x;
	puttlbx(x, (virt&~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K);
.
## diffname carrera/mmu.c 1993/1219
## diff -e /n/fornaxdump/1993/1218/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1219/sys/src/brazil/carrera/mmu.c
213a

.
159c
	if(k->virt == 0 || k->ref < 1)
.
## diffname carrera/mmu.c 1993/1221
## diff -e /n/fornaxdump/1993/1219/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1221/sys/src/brazil/carrera/mmu.c
288c
cleancache();		/* Too expensive */
/*		icflush((void*)pg->va, BY2PG);*/
.
## diffname carrera/mmu.c 1993/1228
## diff -e /n/fornaxdump/1993/1221/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1993/1228/sys/src/brazil/carrera/mmu.c
288,289c
		icflush((void*)pg->va, BY2PG);
.
## diffname carrera/mmu.c 1994/0728
## diff -e /n/fornaxdump/1993/1228/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1994/0728/sys/src/brazil/carrera/mmu.c
80,81c
	if(kmapfree == 0) {
		unlock(&kmaplock);
		kmapinval();		/* try and free some */
		lock(&kmaplock);
		if(kmapfree == 0)
			panic("out of kmap");
	}
.
## diffname carrera/mmu.c 1994/0808
## diff -e /n/fornaxdump/1994/0728/sys/src/brazil/carrera/mmu.c /n/fornaxdump/1994/0808/sys/src/brazil/carrera/mmu.c
56d
50d
## diffname carrera/mmu.c 2001/0527 # deleted
## diff -e /n/fornaxdump/1994/0808/sys/src/brazil/carrera/mmu.c /n/emeliedump/2001/0527/sys/src/9/carrera/mmu.c
1,391d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.