plan 9 kernel history: overview | file list | diff list

2000/0924/bitsy/mmu.c (diff list | history)

2000/0902/sys/src/9/bitsy/mmu.c:8,132000/0905/sys/src/9/bitsy/mmu.c:8,18 (short | long)
2000/0902    
#include	"../port/error.h" 
 
void 
2000/0905    
mmuinit(void) 
{ 
} 
 
void 
2000/0902    
putmmu(ulong va, ulong pa, Page*) 
{ 
	USED(va, pa); 
2000/0905/sys/src/9/bitsy/mmu.c:7,152000/0906/sys/src/9/bitsy/mmu.c:7,59 (short | long)
2000/0902    
#include	"ureg.h" 
#include	"../port/error.h" 
 
2000/0906    
/* real protection bits */ 
enum 
{ 
	Small_Page=	(2<<0), 
	Large_Page=	(1<<0), 
	Cached=		(1<<3), 
	Buffered=	(1<<2), 
	UserRO=		(0xAA<<4), 
	UserRW=		(0xFF<<4), 
	KernelRW=	(0x55<<4), 
}; 
 
 
/* 
 *  table to map fault.c bits to physical bits 
 */ 
static ulong phystrans[8] = 
{ 
	[PTEVALID]			Small_Page|Cached|Buffered|UserRO, 
	[PTEVALID|PTEWRITE]		Small_Page|Cached|Buffered|UserRW, 
	[PTEVALID|UNCACHED]		Small_Page|UserRO, 
	[PTEVALID|UNCACHED|PTEWRITE]	Small_Page|UserRW, 
}; 
 
ulong *l1page; 
 
/* 
 *  We map all of memory, flash, and the zeros area with sections. 
 *  Special use space is mapped on the fly with regmap. 
 */ 
2000/0902    
void 
2000/0905    
mmuinit(void) 
{ 
2000/0906    
	ulong a, e; 
 
	/* set up the domain register to cause all domains to obey pte access bits */ 
	putdac(0x55555555); 
 
	/* get a prototype level 1 page */ 
	l1page = xspanalloc(BY2PG, 16*1024, 0); 
	memset(l1page, 0, BY2PG); 
 
	/* map DRAM */ 
	e = PHYSDRAM0 + BY2PG*con 
	for( 
	/* map zeros */ 
	/* map flash */ 
2000/0905    
} 
 
void 
2000/0906/sys/src/9/bitsy/mmu.c:10,372000/0907/sys/src/9/bitsy/mmu.c:10,58 (short | long)
2000/0906    
/* real protection bits */ 
enum 
{ 
	Small_Page=	(2<<0), 
	Large_Page=	(1<<0), 
	Cached=		(1<<3), 
	Buffered=	(1<<2), 
	UserRO=		(0xAA<<4), 
	UserRW=		(0xFF<<4), 
	KernelRW=	(0x55<<4), 
2000/0907    
	/* level 1 descriptor bits */ 
	L1TypeMask=	(3<<0), 
	L1Invalid=	(0<<0), 
	L1PageTable=	(1<<0), 
	L1Section=	(2<<0), 
	L1Cached=	(1<<3), 
	L1Buffered=	(1<<2), 
	L1Domain0=	(0<<5), 
	L1KernelRW=	(0x1<<10), 
	L1UserRO=	(0x2<<10), 
	L1UserRW=	(0x3<<10), 
	L1SectBaseMask=	(0xFFF<<20), 
	L1PTBaseMask=	(0x3FFFFF<<10), 
	 
	/* level 2 descriptor bits */ 
	L2TypeMask=	(3<<0), 
	L2SmallPage=	(2<<0), 
	L2LargePage=	(1<<0), 
	L2Cached=	(1<<3), 
	L2Buffered=	(1<<2), 
	L2KernelRW=	(0x55<<4), 
	L2UserRO=	(0xAA<<4), 
	L2UserRW=	(0xFF<<4), 
	L2PageBaseMask=	(0xFFFFF<<12), 
2000/0906    
}; 
 
                 
/* 
 *  table to map fault.c bits to physical bits 
 */ 
static ulong phystrans[8] = 
2000/0907    
static ulong phystrans[16] = 
2000/0906    
{ 
	[PTEVALID]			Small_Page|Cached|Buffered|UserRO, 
	[PTEVALID|PTEWRITE]		Small_Page|Cached|Buffered|UserRW, 
	[PTEVALID|UNCACHED]		Small_Page|UserRO, 
	[PTEVALID|UNCACHED|PTEWRITE]	Small_Page|UserRW, 
2000/0907    
	[PTEVALID]				L2SmallPage|L2Cached|L2Buffered|L2UserRO, 
	[PTEVALID|PTEWRITE]			L2SmallPage|L2Cached|L2Buffered|L2UserRW, 
	[PTEVALID|PTEUNCACHED]			L2SmallPage|L2UserRO, 
	[PTEVALID|PTEUNCACHED|PTEWRITE]		L2SmallPage|L2UserRW, 
 
	[PTEKERNEL|PTEVALID]			L2SmallPage|L2Cached|L2Buffered|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEWRITE]		L2SmallPage|L2Cached|L2Buffered|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEUNCACHED]		L2SmallPage|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE]	L2SmallPage|L2KernelRW, 
2000/0906    
}; 
 
ulong *l1page; 
2000/0907    
ulong *l1table; 
2000/0906    
 
/* 
 *  We map all of memory, flash, and the zeros area with sections. 
2000/0906/sys/src/9/bitsy/mmu.c:46,592000/0907/sys/src/9/bitsy/mmu.c:67,123
2000/0906    
	putdac(0x55555555); 
 
	/* get a prototype level 1 page */ 
	l1page = xspanalloc(BY2PG, 16*1024, 0); 
	memset(l1page, 0, BY2PG); 
2000/0907    
	l1table = xspanalloc(BY2PG, 16*1024, 0); 
	memset(l1table, 0, BY2PG); 
2000/0906    
 
	/* map DRAM */ 
	e = PHYSDRAM0 + BY2PG*con 
	for( 
	/* map zeros */ 
	/* map flash */ 
2000/0907    
	/* direct map DRAM */ 
	e = conf.base1 + BY2PG*conf.npage2; 
	for(a = PHYSDRAM0; a < e; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | 
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
 
	/* direct map zeros area */ 
	for(a = PHYSNULL0; a < PHYSNULL0 + 128 * OneMeg; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | 
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
 
	/* direct map flash */ 
	for(a = PHYFLASH0; a < PHYFLASH0 + 128 * OneMeg; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | 
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
 
	/* map the uart so that we can continue using iprint */ 
	uart3regs = mapspecial(UART3REGS, 64); 
} 
 
/* 
 *  map special use space  
 */ 
ulong* 
mapspecial(ulong addr, int len) 
{ 
	ulong *t; 
	ulong a, i; 
 
	/* first see if we've mapped it somewhere, the first hole means we're done */ 
	for(a = REGZERO; a < REGTOP; a += OneMeg){ 
		if((l1table[a>>20] & L1TypeMask) != L1PageTable){ 
			/* create a page table and break */ 
			t = xspanalloc(BY2PG, 1024, 0); 
			memzero(t, BY2PG, 0); 
			l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); 
			break; 
		} 
		t = (ulong*)(l1table[a>>20] & L1PTBaseMask); 
		for(i = 0; i < OneMeg; i += BY2PG){ 
			if((t[a>>20] & L2TypeMask) != L2SmallPage) 
				break; 
		} 
		if(i < OneMeg){ 
			a += i; 
			break; 
		} 
	} 
2000/0905    
} 
 
void 
2000/0907/sys/src/9/bitsy/mmu.c:94,1232000/0909/sys/src/9/bitsy/mmu.c:94,126 (short | long)
2000/0907    
 *  map special use space  
 */ 
ulong* 
mapspecial(ulong addr, int len) 
2000/0909    
mapspecial(ulong physaddr, int len) 
2000/0907    
{ 
	ulong *t; 
	ulong a, i; 
2000/0909    
	ulong virtaddr, i; 
2000/0907    
 
	/* first see if we've mapped it somewhere, the first hole means we're done */ 
	for(a = REGZERO; a < REGTOP; a += OneMeg){ 
		if((l1table[a>>20] & L1TypeMask) != L1PageTable){ 
2000/0909    
	for(virtaddr = REGZERO; virtaddr < REGTOP; virtaddr += OneMeg){ 
		if((l1table[virtaddr>>20] & L1TypeMask) != L1PageTable){ 
2000/0907    
			/* create a page table and break */ 
			t = xspanalloc(BY2PG, 1024, 0); 
			memzero(t, BY2PG, 0); 
			l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); 
2000/0909    
			l1table[virtaddr>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); 
2000/0907    
			break; 
		} 
		t = (ulong*)(l1table[a>>20] & L1PTBaseMask); 
2000/0909    
		t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask); 
2000/0907    
		for(i = 0; i < OneMeg; i += BY2PG){ 
			if((t[a>>20] & L2TypeMask) != L2SmallPage) 
2000/0909    
			if((t[virtaddr>>20] & L2TypeMask) != L2SmallPage) 
2000/0907    
				break; 
		} 
		if(i < OneMeg){ 
			a += i; 
2000/0909    
			virtaddr += i; 
2000/0907    
			break; 
		} 
	} 
2000/0909    
 
	/* we get here if no entry was found mapping this physical address */ 
	 
2000/0905    
} 
 
void 
2000/0909/sys/src/9/bitsy/mmu.c:91,972000/0920/sys/src/9/bitsy/mmu.c:91,97 (short | long)
2000/0907    
} 
 
/* 
 *  map special use space  
2000/0920    
 *  map special use space 
2000/0907    
 */ 
ulong* 
2000/0909    
mapspecial(ulong physaddr, int len) 
2000/0909/sys/src/9/bitsy/mmu.c:110,1172000/0920/sys/src/9/bitsy/mmu.c:110,118
2000/0907    
		} 
2000/0909    
		t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask); 
2000/0907    
		for(i = 0; i < OneMeg; i += BY2PG){ 
2000/0909    
			if((t[virtaddr>>20] & L2TypeMask) != L2SmallPage) 
2000/0920    
			if((t[(virtaddr+i)>>20] & L2TypeMask) != L2SmallPage) 
2000/0907    
				break; 
2000/0920    
			 
2000/0907    
		} 
		if(i < OneMeg){ 
2000/0909    
			virtaddr += i; 
2000/0909/sys/src/9/bitsy/mmu.c:119,1262000/0920/sys/src/9/bitsy/mmu.c:120,126
2000/0907    
		} 
	} 
2000/0909    
 
	/* we get here if no entry was found mapping this physical address */ 
	                 
2000/0920    
	/* we get here if no entry was found mapping this physical range */ 
2000/0905    
} 
 
void 
2000/0920/sys/src/9/bitsy/mmu.c:91,1042000/0921/sys/src/9/bitsy/mmu.c:91,111 (short | long)
2000/0907    
} 
 
/* 
2000/0920    
 *  map special use space 
2000/0921    
 *  map special space, assume that the space isn't already mapped 
2000/0907    
 */ 
ulong* 
2000/0909    
mapspecial(ulong physaddr, int len) 
2000/0907    
{ 
	ulong *t; 
2000/0909    
	ulong virtaddr, i; 
2000/0921    
	ulong virtaddr, i, base, end, off, entry, candidate; 
2000/0907    
 
2000/0921    
	base = physaddr & ~(BY2PG-1); 
	end = (physaddr+len-1) & ~(BY2PG-1); 
	if(len > 128*1024) 
		usemeg = 1; 
	off = 0; 
	candidate = 0; 
 
2000/0907    
	/* first see if we've mapped it somewhere, the first hole means we're done */ 
2000/0909    
	for(virtaddr = REGZERO; virtaddr < REGTOP; virtaddr += OneMeg){ 
		if((l1table[virtaddr>>20] & L1TypeMask) != L1PageTable){ 
2000/0920/sys/src/9/bitsy/mmu.c:105,1182000/0921/sys/src/9/bitsy/mmu.c:112,145
2000/0907    
			/* create a page table and break */ 
			t = xspanalloc(BY2PG, 1024, 0); 
			memzero(t, BY2PG, 0); 
2000/0909    
			l1table[virtaddr>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); 
2000/0921    
			l1table[virtaddr>>20] = L1PageTable | L1Domain0 | 
						(((ulong)t) & L1PTBaseMask); 
2000/0907    
			break; 
		} 
2000/0909    
		t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask); 
2000/0907    
		for(i = 0; i < OneMeg; i += BY2PG){ 
2000/0920    
			if((t[(virtaddr+i)>>20] & L2TypeMask) != L2SmallPage) 
2000/0921    
			entry = t[(virtaddr+i)>>20]; 
 
			/* first hole means nothing left, add map */ 
			if((entry & L2TypeMask) != L2SmallPage) 
2000/0907    
				break; 
2000/0920    
			                 
2000/0921    
 
			if(candidate == 0){ 
				/* look for start of range */ 
				if((entry & L2PageBaseMask) != base) 
					continue; 
				candidate = virtaddr+i; 
			} else { 
				/* look for contiunued range */ 
				if((entry & L2PageBaseMask) != base + off) 
					candidate = 0; 
					continue; 
				} 
			} 
 
			/* if we're at the end of the range, area is already mapped */ 
			if((entry & L2PageBaseMask) == end) 
				return candidate + (physaddr-base); 
2000/0907    
		} 
		if(i < OneMeg){ 
2000/0909    
			virtaddr += i; 
2000/0921/sys/src/9/bitsy/mmu.c:91,992000/0923/sys/src/9/bitsy/mmu.c:91,101 (short | long)
2000/0907    
} 
 
/* 
2000/0921    
 *  map special space, assume that the space isn't already mapped 
2000/0923    
 *  map special space uncached, assume that the space isn't already mapped 
2000/0907    
 */ 
ulong* 
2000/0923    
mapspecmeg(ulong physaddr, int len) 
ulong* 
2000/0909    
mapspecial(ulong physaddr, int len) 
2000/0907    
{ 
	ulong *t; 
2000/0921/sys/src/9/bitsy/mmu.c:131,1372000/0923/sys/src/9/bitsy/mmu.c:133,139
2000/0921    
				candidate = virtaddr+i; 
			} else { 
				/* look for contiunued range */ 
				if((entry & L2PageBaseMask) != base + off) 
2000/0923    
				if((entry & L2PageBaseMask) != base + off){ 
2000/0921    
					candidate = 0; 
					continue; 
				} 
2000/0923/sys/src/9/bitsy/mmu.c:94,1552000/0924/sys/src/9/bitsy/mmu.c:94,158 (short | long)
2000/0923    
 *  map special space uncached, assume that the space isn't already mapped 
2000/0907    
 */ 
ulong* 
2000/0923    
mapspecmeg(ulong physaddr, int len) 
ulong* 
2000/0909    
mapspecial(ulong physaddr, int len) 
2000/0924    
mapspecial(ulong pa, int len) 
2000/0907    
{ 
	ulong *t; 
2000/0921    
	ulong virtaddr, i, base, end, off, entry, candidate; 
2000/0924    
	ulong va, i, base, end, off; 
	int livelarge; 
	ulong* rv; 
2000/0907    
 
2000/0921    
	base = physaddr & ~(BY2PG-1); 
	end = (physaddr+len-1) & ~(BY2PG-1); 
	if(len > 128*1024) 
		usemeg = 1; 
	off = 0; 
	candidate = 0; 
2000/0924    
	rv = nil; 
	livelarge = len >= 128*1024; 
	if(livelarge){ 
		base = pa & ~(OneMeg-1); 
		end = (pa+len-1) & ~(OneMeg-1); 
	} else { 
		base = pa & ~(BY2PG-1); 
		end = (pa+len-1) & ~(BY2PG-1); 
	} 
	off = pa - base; 
2000/0921    
 
2000/0907    
	/* first see if we've mapped it somewhere, the first hole means we're done */ 
2000/0909    
	for(virtaddr = REGZERO; virtaddr < REGTOP; virtaddr += OneMeg){ 
		if((l1table[virtaddr>>20] & L1TypeMask) != L1PageTable){ 
2000/0907    
			/* create a page table and break */ 
2000/0924    
	for(va = REGZERO; va < REGTOP && base >= end; va += OneMeg){ 
		if((l1table[va>>20] & L1TypeMask) != L1PageTable){ 
 
			/* found unused entry on level 1 table */ 
			if(livelarge){ 
				if(rv == nil) 
					rv = (ulong*)(va+i*BY2PG+off); 
				l1table[va>>20] = L1Section | L1KernelRW | 
							(base&L1SectBaseMask); 
				base += OneMeg; 
				continue; 
			} 
 
			/* create a page table and keep going */ 
2000/0907    
			t = xspanalloc(BY2PG, 1024, 0); 
			memzero(t, BY2PG, 0); 
2000/0921    
			l1table[virtaddr>>20] = L1PageTable | L1Domain0 | 
2000/0924    
			l1table[va>>20] = L1PageTable | L1Domain0 | 
2000/0921    
						(((ulong)t) & L1PTBaseMask); 
2000/0907    
			break; 
		} 
2000/0909    
		t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask); 
2000/0924    
 
		t = (ulong*)(l1table[va>>20] & L1PTBaseMask); 
2000/0907    
		for(i = 0; i < OneMeg; i += BY2PG){ 
2000/0921    
			entry = t[(virtaddr+i)>>20]; 
2000/0924    
			entry = t[i>>PGSHIFT]; 
2000/0921    
 
			/* first hole means nothing left, add map */ 
			if((entry & L2TypeMask) != L2SmallPage) 
2000/0907    
				break; 
2000/0921    
                 
			if(candidate == 0){ 
				/* look for start of range */ 
				if((entry & L2PageBaseMask) != base) 
					continue; 
				candidate = virtaddr+i; 
			} else { 
				/* look for contiunued range */ 
2000/0923    
				if((entry & L2PageBaseMask) != base + off){ 
2000/0921    
					candidate = 0; 
					continue; 
				} 
2000/0924    
			/* found unused entry on level 2 table */ 
			if((entry & L2TypeMask) != L2SmallPage){ 
				if(rv == nil) 
					rv = (ulong*)(va+i*BY2PG+off); 
				t[i>>PGSHIFT] = L2SmallPage | L2KernelRW |  
						(base & L2PageBaseMask); 
				base += BY2PG; 
				continue; 
2000/0921    
			} 
                 
			/* if we're at the end of the range, area is already mapped */ 
			if((entry & L2PageBaseMask) == end) 
				return candidate + (physaddr-base); 
2000/0907    
		} 
		if(i < OneMeg){ 
2000/0909    
			virtaddr += i; 
2000/0907    
			break; 
		} 
	} 
2000/0909    
 
2000/0920    
	/* we get here if no entry was found mapping this physical range */ 
2000/0924    
	/* didn't fit */ 
	if(base <= end) 
		return nil; 
 
	return rv; 
2000/0905    
} 
 
void 
2000/0924/sys/src/9/bitsy/mmu.c:63,812000/0928/sys/src/9/bitsy/mmu.c:63,82 (short | long)
2000/0905    
{ 
2000/0906    
	ulong a, e; 
 
	/* set up the domain register to cause all domains to obey pte access bits */ 
	putdac(0x55555555); 
                 
	/* get a prototype level 1 page */ 
2000/0907    
	l1table = xspanalloc(BY2PG, 16*1024, 0); 
	memset(l1table, 0, BY2PG); 
2000/0906    
 
2000/0907    
	/* direct map DRAM */ 
	e = conf.base1 + BY2PG*conf.npage2; 
2000/0928    
	e = conf.base1 + BY2PG*conf.npage1; 
2000/0907    
	for(a = PHYSDRAM0; a < e; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | 
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
 
2000/0928    
	/* direct map devs */ 
	for(a = REGZERO; a < REGTOP; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask); 
 
2000/0907    
	/* direct map zeros area */ 
	for(a = PHYSNULL0; a < PHYSNULL0 + 128 * OneMeg; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | 
2000/0924/sys/src/9/bitsy/mmu.c:82,932000/0928/sys/src/9/bitsy/mmu.c:83,102
2000/0907    
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
 
	/* direct map flash */ 
	for(a = PHYFLASH0; a < PHYFLASH0 + 128 * OneMeg; a += OneMeg) 
2000/0928    
	for(a = PHYSFLASH0; a < PHYSFLASH0 + 128 * OneMeg; a += OneMeg) 
2000/0907    
		l1table[a>>20] = L1Section | L1KernelRW | 
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
 
	/* map the uart so that we can continue using iprint */ 
	uart3regs = mapspecial(UART3REGS, 64); 
2000/0928    
//	uart3regs = mapspecial(UART3REGS, 64); 
 
	/* set up the domain register to cause all domains to obey pte access bits */ 
	iprint("setting up domain access\n"); 
	putdac(0x55555555); 
 
	/* point to map */ 
	iprint("setting tlb map %lux\n", (ulong)l1table); 
	putttb((ulong)l1table); 
2000/0907    
} 
 
/* 
2000/0924/sys/src/9/bitsy/mmu.c:97,1032000/0928/sys/src/9/bitsy/mmu.c:106,112
2000/0924    
mapspecial(ulong pa, int len) 
2000/0907    
{ 
	ulong *t; 
2000/0924    
	ulong va, i, base, end, off; 
2000/0928    
	ulong va, i, base, end, off, entry; 
2000/0924    
	int livelarge; 
	ulong* rv; 
2000/0907    
 
2000/0924/sys/src/9/bitsy/mmu.c:127,1332000/0928/sys/src/9/bitsy/mmu.c:136,142
2000/0924    
 
			/* create a page table and keep going */ 
2000/0907    
			t = xspanalloc(BY2PG, 1024, 0); 
			memzero(t, BY2PG, 0); 
2000/0928    
			memset(t, 0, BY2PG); 
2000/0924    
			l1table[va>>20] = L1PageTable | L1Domain0 | 
2000/0921    
						(((ulong)t) & L1PTBaseMask); 
2000/0907    
		} 
2000/0928/sys/src/9/bitsy/mmu.c:62,672000/0929/sys/src/9/bitsy/mmu.c:62,68 (short | long)
2000/0905    
mmuinit(void) 
{ 
2000/0906    
	ulong a, e; 
2000/0929    
	ulong *t; 
2000/0906    
 
	/* get a prototype level 1 page */ 
2000/0907    
	l1table = xspanalloc(BY2PG, 16*1024, 0); 
2000/0928/sys/src/9/bitsy/mmu.c:70,1022000/0929/sys/src/9/bitsy/mmu.c:71,109
2000/0907    
	/* direct map DRAM */ 
2000/0928    
	e = conf.base1 + BY2PG*conf.npage1; 
2000/0907    
	for(a = PHYSDRAM0; a < e; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | 
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
2000/0929    
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | 
				L1Cached | L1Buffered; 
2000/0907    
 
2000/0928    
	/* direct map devs */ 
	for(a = REGZERO; a < REGTOP; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask); 
                 
2000/0907    
	/* direct map zeros area */ 
	for(a = PHYSNULL0; a < PHYSNULL0 + 128 * OneMeg; a += OneMeg) 
		l1table[a>>20] = L1Section | L1KernelRW | 
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
2000/0929    
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask); 
2000/0907    
 
	/* direct map flash */ 
2000/0928    
	for(a = PHYSFLASH0; a < PHYSFLASH0 + 128 * OneMeg; a += OneMeg) 
2000/0907    
		l1table[a>>20] = L1Section | L1KernelRW | 
				L1Cached | L1Buffered | (a&L1SectBaseMask); 
2000/0929    
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | 
				L1Cached | L1Buffered; 
2000/0907    
 
	/* map the uart so that we can continue using iprint */ 
2000/0928    
//	uart3regs = mapspecial(UART3REGS, 64); 
2000/0929    
	/* map first page of DRAM also into 0xFFFF0000 for the interrupt vectors */ 
	t = xspanalloc(BY2PG, 16*1024, 0); 
	memset(t, 0, BY2PG); 
	l1table[0xFFFF0000>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); 
	t[0xF0000>>PGSHIFT] = L2SmallPage | L2KernelRW | PHYSDRAM0; 
2000/0928    
 
	/* set up the domain register to cause all domains to obey pte access bits */ 
	iprint("setting up domain access\n"); 
	putdac(0x55555555); 
2000/0929    
	putdac(0xFFFFFFFF); 
2000/0928    
 
	/* point to map */ 
	iprint("setting tlb map %lux\n", (ulong)l1table); 
	putttb((ulong)l1table); 
2000/0929    
 
	/* map the uart so that we can continue using iprint */ 
	uart3regs = (Uartregs*)mapspecial(UART3REGS, 64); 
 
	/* enable mmu, and make 0xFFFF0000 the virtual address of the exception vecs */ 
	mmuenable(); 
 
	iprint("uart3regs now at %lux\n", uart3regs); 
2000/0907    
} 
 
/* 
2000/0928/sys/src/9/bitsy/mmu.c:121,1462000/0929/sys/src/9/bitsy/mmu.c:128,162
2000/0924    
	} 
	off = pa - base; 
2000/0921    
 
2000/0924    
	for(va = REGZERO; va < REGTOP && base >= end; va += OneMeg){ 
		if((l1table[va>>20] & L1TypeMask) != L1PageTable){ 
                 
2000/0929    
	for(va = REGZERO; va < REGTOP && base <= end; va += OneMeg){ 
		switch(l1table[va>>20] & L1TypeMask){ 
		default: 
2000/0924    
			/* found unused entry on level 1 table */ 
			if(livelarge){ 
				if(rv == nil) 
					rv = (ulong*)(va+i*BY2PG+off); 
2000/0929    
					rv = (ulong*)(va+off); 
2000/0924    
				l1table[va>>20] = L1Section | L1KernelRW | 
							(base&L1SectBaseMask); 
2000/0929    
							(base & L1SectBaseMask); 
2000/0924    
				base += OneMeg; 
				continue; 
			} 
2000/0929    
			} else { 
2000/0924    
 
			/* create a page table and keep going */ 
2000/0907    
			t = xspanalloc(BY2PG, 1024, 0); 
2000/0928    
			memset(t, 0, BY2PG); 
2000/0924    
			l1table[va>>20] = L1PageTable | L1Domain0 | 
2000/0921    
						(((ulong)t) & L1PTBaseMask); 
2000/0929    
				/* create an L2 page table and keep going */ 
				t = xspanalloc(BY2PG, 1024, 0); 
				memset(t, 0, BY2PG); 
				l1table[va>>20] = L1PageTable | L1Domain0 | 
							(((ulong)t) & L1PTBaseMask); 
			} 
			break; 
		case L1Section: 
			continue; 
		case L1PageTable: 
			if(livelarge) 
				continue; 
			break; 
2000/0907    
		} 
2000/0924    
 
2000/0929    
		/* here if we're using page maps instead of sections */ 
2000/0924    
		t = (ulong*)(l1table[va>>20] & L1PTBaseMask); 
2000/0907    
		for(i = 0; i < OneMeg; i += BY2PG){ 
2000/0924    
			entry = t[i>>PGSHIFT]; 
2000/0928/sys/src/9/bitsy/mmu.c:148,1542000/0929/sys/src/9/bitsy/mmu.c:164,170
2000/0924    
			/* found unused entry on level 2 table */ 
			if((entry & L2TypeMask) != L2SmallPage){ 
				if(rv == nil) 
					rv = (ulong*)(va+i*BY2PG+off); 
2000/0929    
					rv = (ulong*)(va+i+off); 
2000/0924    
				t[i>>PGSHIFT] = L2SmallPage | L2KernelRW |  
						(base & L2PageBaseMask); 
				base += BY2PG; 
2000/0929/sys/src/9/bitsy/mmu.c:98,1042000/1002/sys/src/9/bitsy/mmu.c:98,104 (short | long)
2000/0928    
	putttb((ulong)l1table); 
2000/0929    
 
	/* map the uart so that we can continue using iprint */ 
	uart3regs = (Uartregs*)mapspecial(UART3REGS, 64); 
2000/1002    
	uart3regs = mapspecial(UART3REGS, 64); 
2000/0929    
 
	/* enable mmu, and make 0xFFFF0000 the virtual address of the exception vecs */ 
	mmuenable(); 
2000/0929/sys/src/9/bitsy/mmu.c:109,1152000/1002/sys/src/9/bitsy/mmu.c:109,115
2000/0907    
/* 
2000/0923    
 *  map special space uncached, assume that the space isn't already mapped 
2000/0907    
 */ 
ulong* 
2000/1002    
void* 
2000/0924    
mapspecial(ulong pa, int len) 
2000/0907    
{ 
	ulong *t; 
2000/1002/sys/src/9/bitsy/mmu.c:97,1092000/1006/sys/src/9/bitsy/mmu.c:97,104 (short | long)
2000/0928    
	iprint("setting tlb map %lux\n", (ulong)l1table); 
	putttb((ulong)l1table); 
2000/0929    
 
	/* map the uart so that we can continue using iprint */ 
2000/1002    
	uart3regs = mapspecial(UART3REGS, 64); 
2000/0929    
                 
	/* enable mmu, and make 0xFFFF0000 the virtual address of the exception vecs */ 
	mmuenable(); 
                 
	iprint("uart3regs now at %lux\n", uart3regs); 
2000/0907    
} 
 
/* 
2000/1006/sys/src/9/bitsy/mmu.c:54,592000/1007/sys/src/9/bitsy/mmu.c:54,60 (short | long)
2000/0906    
 
2000/0907    
ulong *l1table; 
2000/0906    
 
2000/1007    
 
2000/0906    
/* 
 *  We map all of memory, flash, and the zeros area with sections. 
 *  Special use space is mapped on the fly with regmap. 
2000/1006/sys/src/9/bitsy/mmu.c:65,722000/1007/sys/src/9/bitsy/mmu.c:66,73
2000/0929    
	ulong *t; 
2000/0906    
 
	/* get a prototype level 1 page */ 
2000/0907    
	l1table = xspanalloc(BY2PG, 16*1024, 0); 
	memset(l1table, 0, BY2PG); 
2000/1007    
	l1table = xspanalloc(16*1024, 16*1024, 0); 
	memset(l1table, 0, 16*1024); 
2000/0906    
 
2000/0907    
	/* direct map DRAM */ 
2000/0928    
	e = conf.base1 + BY2PG*conf.npage1; 
2000/1006/sys/src/9/bitsy/mmu.c:83,932000/1007/sys/src/9/bitsy/mmu.c:84,97
2000/0929    
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | 
				L1Cached | L1Buffered; 
2000/0907    
 
2000/0929    
	/* map first page of DRAM also into 0xFFFF0000 for the interrupt vectors */ 
	t = xspanalloc(BY2PG, 16*1024, 0); 
2000/1007    
	/* 
	 *  double map start of ram to exception vectors 
	 */ 
	a = EVECTORS; 
	t = xspanalloc(BY2PG, 1024, 0); 
2000/0929    
	memset(t, 0, BY2PG); 
	l1table[0xFFFF0000>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); 
	t[0xF0000>>PGSHIFT] = L2SmallPage | L2KernelRW | PHYSDRAM0; 
2000/1007    
	l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask); 
	t[(a&0xfffff)>>PGSHIFT] = L2SmallPage | L2KernelRW | (PHYSDRAM0 & L2PageBaseMask); 
2000/0928    
 
	/* set up the domain register to cause all domains to obey pte access bits */ 
	iprint("setting up domain access\n"); 
2000/1006/sys/src/9/bitsy/mmu.c:97,1032000/1007/sys/src/9/bitsy/mmu.c:101,110
2000/0928    
	iprint("setting tlb map %lux\n", (ulong)l1table); 
	putttb((ulong)l1table); 
2000/0929    
 
	/* enable mmu, and make 0xFFFF0000 the virtual address of the exception vecs */ 
2000/1007    
	/* enable mmu */ 
	wbflush(); 
	flushcache(); 
	flushmmu(); 
2000/0929    
	mmuenable(); 
2000/0907    
} 
 
2000/1007/sys/src/9/bitsy/mmu.c:7,122000/1011/sys/src/9/bitsy/mmu.c:7,20 (short | long)
2000/0902    
#include	"ureg.h" 
#include	"../port/error.h" 
 
2000/1011    
/* 
 *  to avoid mmu and cash flushing, we use the pid register in the MMU 
 *  to map all user addresses.  Although there are 64 possible pids, we 
 *  can only use 31 because there are only 32 protection domains and we 
 *  need one for the kernel.  Pid i is thus associated with domain i. 
 *  Domain 0 is used for the kernel. 
 */ 
 
2000/0906    
/* real protection bits */ 
enum 
{ 
2000/1007/sys/src/9/bitsy/mmu.c:17,232000/1011/sys/src/9/bitsy/mmu.c:25,32
2000/0907    
	L1Section=	(2<<0), 
	L1Cached=	(1<<3), 
	L1Buffered=	(1<<2), 
	L1Domain0=	(0<<5), 
2000/1011    
	L1DomShift=	5, 
	L1Domain0=	(0<<L1DomShift), 
2000/0907    
	L1KernelRW=	(0x1<<10), 
	L1UserRO=	(0x2<<10), 
	L1UserRW=	(0x3<<10), 
2000/1007/sys/src/9/bitsy/mmu.c:34,552000/1011/sys/src/9/bitsy/mmu.c:43,53
2000/0907    
	L2UserRO=	(0xAA<<4), 
	L2UserRW=	(0xFF<<4), 
	L2PageBaseMask=	(0xFFFFF<<12), 
2000/0906    
}; 
 
/* 
 *  table to map fault.c bits to physical bits 
 */ 
2000/0907    
static ulong phystrans[16] = 
2000/0906    
{ 
2000/0907    
	[PTEVALID]				L2SmallPage|L2Cached|L2Buffered|L2UserRO, 
	[PTEVALID|PTEWRITE]			L2SmallPage|L2Cached|L2Buffered|L2UserRW, 
	[PTEVALID|PTEUNCACHED]			L2SmallPage|L2UserRO, 
	[PTEVALID|PTEUNCACHED|PTEWRITE]		L2SmallPage|L2UserRW, 
                 
	[PTEKERNEL|PTEVALID]			L2SmallPage|L2Cached|L2Buffered|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEWRITE]		L2SmallPage|L2Cached|L2Buffered|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEUNCACHED]		L2SmallPage|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE]	L2SmallPage|L2KernelRW, 
2000/1011    
	/* domain values */ 
	Dnoaccess=	0, 
	Dclient=	1, 
	Dmanager=	3, 
2000/0906    
}; 
 
2000/0907    
ulong *l1table; 
2000/1007/sys/src/9/bitsy/mmu.c:62,682000/1011/sys/src/9/bitsy/mmu.c:60,66
2000/0902    
void 
2000/0905    
mmuinit(void) 
{ 
2000/0906    
	ulong a, e; 
2000/1011    
	ulong a, o; 
2000/0929    
	ulong *t; 
2000/0906    
 
	/* get a prototype level 1 page */ 
2000/1007/sys/src/9/bitsy/mmu.c:69,892000/1011/sys/src/9/bitsy/mmu.c:67,95
2000/1007    
	l1table = xspanalloc(16*1024, 16*1024, 0); 
	memset(l1table, 0, 16*1024); 
2000/0906    
 
2000/0907    
	/* direct map DRAM */ 
2000/0928    
	e = conf.base1 + BY2PG*conf.npage1; 
2000/0907    
	for(a = PHYSDRAM0; a < e; a += OneMeg) 
2000/0929    
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | 
				L1Cached | L1Buffered; 
2000/1011    
	/* map DRAM */ 
	for(o = 0; o < DRAMTOP; o += OneMeg) 
		l1table[(DRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0  
			| L1Cached | L1Buffered 
			| ((PHYSDRAM0+o)&L1SectBaseMask); 
2000/0907    
 
	/* direct map zeros area */ 
	for(a = PHYSNULL0; a < PHYSNULL0 + 128 * OneMeg; a += OneMeg) 
2000/0929    
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask); 
2000/1011    
	/* map zeros area */ 
	for(o = 0; o < 128 * OneMeg; o += OneMeg) 
		l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 
			| ((PHYSNULL0+o)&L1SectBaseMask); 
2000/0907    
 
	/* direct map flash */ 
2000/0928    
	for(a = PHYSFLASH0; a < PHYSFLASH0 + 128 * OneMeg; a += OneMeg) 
2000/0929    
		l1table[a>>20] = L1Section | L1KernelRW | (a&L1SectBaseMask) | 
				L1Cached | L1Buffered; 
2000/1011    
	/* map flash */ 
	for(o = 0; o < 128 * OneMeg; o += OneMeg) 
		l1table[(FLASHZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 
			| L1Cached | L1Buffered 
			| ((PHYSFLASH0+o)&L1SectBaseMask); 
2000/0907    
 
2000/1011    
	/* map peripheral control module regs */ 
	mapspecial(0x80000000, OneMeg); 
 
	/* map system control module regs */ 
	mapspecial(0x90000000, OneMeg); 
 
2000/1007    
	/* 
	 *  double map start of ram to exception vectors 
	 */ 
2000/1007/sys/src/9/bitsy/mmu.c:95,1012000/1011/sys/src/9/bitsy/mmu.c:101,107
2000/0928    
 
	/* set up the domain register to cause all domains to obey pte access bits */ 
	iprint("setting up domain access\n"); 
2000/0929    
	putdac(0xFFFFFFFF); 
2000/1011    
	putdac(Dclient); 
2000/0928    
 
	/* point to map */ 
	iprint("setting tlb map %lux\n", (ulong)l1table); 
2000/1007/sys/src/9/bitsy/mmu.c:137,1432000/1011/sys/src/9/bitsy/mmu.c:143,149
2000/0924    
			if(livelarge){ 
				if(rv == nil) 
2000/0929    
					rv = (ulong*)(va+off); 
2000/0924    
				l1table[va>>20] = L1Section | L1KernelRW | 
2000/1011    
				l1table[va>>20] = L1Section | L1KernelRW | L1Domain0 | 
2000/0929    
							(base & L1SectBaseMask); 
2000/0924    
				base += OneMeg; 
				continue; 
2000/1007/sys/src/9/bitsy/mmu.c:151,1562000/1011/sys/src/9/bitsy/mmu.c:157,169
2000/0929    
			} 
			break; 
		case L1Section: 
2000/1011    
			/* if it's already mapped in a one meg area, don't remap */ 
			entry = l1table[va>>20]; 
			i = entry & L1SectBaseMask; 
			if(pa >= i && (pa+len) <= i + OneMeg) 
			if((entry & ~L1SectBaseMask) == (L1Section | L1KernelRW | L1Domain0)) 
				return (void*)(va + (pa & (OneMeg-1))); 
				 
2000/0929    
			continue; 
		case L1PageTable: 
			if(livelarge) 
2000/1007/sys/src/9/bitsy/mmu.c:182,2012000/1011/sys/src/9/bitsy/mmu.c:195,290
2000/0924    
	return rv; 
2000/0905    
} 
 
2000/1011    
/* 
 *  find a new pid.  If none exist, flush all pids, mmu, and caches. 
 */ 
static Lock pidlock; 
 
int 
newtlbpid(Proc *p) 
{ 
	return p->pid; 
} 
 
/* 
 *  table to map fault.c bits to physical bits 
 */ 
static ulong mmubits[16] = 
{ 
	[PTEVALID]				L2SmallPage|L2Cached|L2Buffered|L2UserRO, 
	[PTEVALID|PTEWRITE]			L2SmallPage|L2Cached|L2Buffered|L2UserRW, 
	[PTEVALID|PTEUNCACHED]			L2SmallPage|L2UserRO, 
	[PTEVALID|PTEUNCACHED|PTEWRITE]		L2SmallPage|L2UserRW, 
 
	[PTEKERNEL|PTEVALID]			L2SmallPage|L2Cached|L2Buffered|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEWRITE]		L2SmallPage|L2Cached|L2Buffered|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEUNCACHED]		L2SmallPage|L2KernelRW, 
	[PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE]	L2SmallPage|L2KernelRW, 
}; 
 
/* 
 *  add an entry to the current map 
 */ 
2000/0905    
void 
2000/0902    
putmmu(ulong va, ulong pa, Page*) 
{ 
	USED(va, pa); 
2000/1011    
	ulong pva; 
	Page *p; 
	ulong *t; 
 
	/* if user memory, offset by pid value */ 
	if((va & 0xfe000000) == 0) 
		pva = va | (up->pid << 25); 
	else 
		pva = va; 
 
	/* always point L1 entry to L2 page, can't hurt */ 
	p = up->l1[va>>20]; 
	if(p == nil){ 
		p = auxpage(); 
		if(p == nil) 
			pexit("out of memory", 1); 
		p->va = VA(kmap(p)); 
		up->l1[va>>20] = p; 
	} 
	l1table[pva>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); 
	t = (ulong*)p->va; 
 
	/* set L2 entry */ 
	t[(pva & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] 
		| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); 
 
	wbflush(); 
2000/0902    
} 
 
2000/1011    
/* 
 *  this is called with palloc locked so the pagechainhead is kosher 
 */ 
2000/0902    
void 
mmurelease(Proc* proc) 
2000/1011    
mmurelease(Proc* p) 
2000/0902    
{ 
	USED(proc); 
2000/1011    
	Page *pg; 
	int i; 
 
	for(i = 0; i < nelem(p->l1); i++){ 
		pg = p->l1[i]; 
		if(pg == nil) 
			continue; 
		if(--pg->ref) 
			panic("mmurelease: pg->ref %d\n", pg->ref); 
		pagechainhead(pg); 
		p->l1[i] = nil; 
	} 
2000/0902    
} 
 
void 
mmuswitch(Proc* proc) 
2000/1011    
mmuswitch(Proc* p) 
2000/0902    
{ 
	USED(proc); 
2000/1011    
	/* set pid */ 
	if(p->pid <= 0) 
		p->pid = newtlbpid(p); 
	putpid(p->pid<<25); 
 
	/* set domain register to this + the kernel's domains */ 
	putdac((Dclient<<(2*p->pid)) | Dclient); 
2000/0902    
} 
2000/1011/sys/src/9/bitsy/mmu.c:100,1102000/1012/sys/src/9/bitsy/mmu.c:100,108 (short | long)
2000/1007    
	t[(a&0xfffff)>>PGSHIFT] = L2SmallPage | L2KernelRW | (PHYSDRAM0 & L2PageBaseMask); 
2000/0928    
 
	/* set up the domain register to cause all domains to obey pte access bits */ 
	iprint("setting up domain access\n"); 
2000/1011    
	putdac(Dclient); 
2000/0928    
 
	/* point to map */ 
	iprint("setting tlb map %lux\n", (ulong)l1table); 
	putttb((ulong)l1table); 
2000/0929    
 
2000/1007    
	/* enable mmu */ 
2000/1011/sys/src/9/bitsy/mmu.c:196,2092000/1012/sys/src/9/bitsy/mmu.c:194,227
2000/0905    
} 
 
2000/1011    
/* 
 *  find a new pid.  If none exist, flush all pids, mmu, and caches. 
2000/1012    
 *  maintain pids 
2000/1011    
 */ 
static Lock pidlock; 
 
2000/1012    
void 
flushpids(void) 
{ 
	memset(l1table, 0, BY2WD*nelem(m->pid2proc)*32); 
	memset(m->pid2proc, 0, sizeof(m->pid2proc)); 
	flushcache(); 
	flushmmu(); 
} 
 
2000/1011    
int 
newtlbpid(Proc *p) 
{ 
	return p->pid; 
2000/1012    
	int i; 
 
	ilock(&pidlock); 
	i = ++(m->lastpid); 
	if(i >= nelem(m->pid2proc)){ 
		flushpids(); 
		i = m->lastpid = 0; 
	} 
	m->pid2proc[i] = p; 
	p->tlbpid = i+1; 
	iunlock(&pidlock); 
	return p->tlbpid; 
2000/1011    
} 
 
/* 
2000/1011/sys/src/9/bitsy/mmu.c:232,2402000/1012/sys/src/9/bitsy/mmu.c:250,259
2000/1011    
	Page *p; 
	ulong *t; 
 
	/* if user memory, offset by pid value */ 
2000/1012    
iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); 
	/* if user memory, add pid value */ 
2000/1011    
	if((va & 0xfe000000) == 0) 
		pva = va | (up->pid << 25); 
2000/1012    
		pva = va | (up->tlbpid << 25); 
2000/1011    
	else 
		pva = va; 
 
2000/1011/sys/src/9/bitsy/mmu.c:281,2902000/1012/sys/src/9/bitsy/mmu.c:300,310
2000/1011    
mmuswitch(Proc* p) 
2000/0902    
{ 
2000/1011    
	/* set pid */ 
	if(p->pid <= 0) 
		p->pid = newtlbpid(p); 
	putpid(p->pid<<25); 
2000/1012    
	if(p->tlbpid <= 0) 
		p->tlbpid = newtlbpid(p); 
iprint("using tlbpid %d\n", p->tlbpid); 
	putpid(p->tlbpid<<25); 
2000/1011    
 
	/* set domain register to this + the kernel's domains */ 
	putdac((Dclient<<(2*p->pid)) | Dclient); 
2000/1012    
	putdac((Dclient<<(2*p->tlbpid)) | Dclient); 
2000/0902    
} 
2000/1012/sys/src/9/bitsy/mmu.c:67,742000/1013/sys/src/9/bitsy/mmu.c:67,80 (short | long)
2000/1007    
	l1table = xspanalloc(16*1024, 16*1024, 0); 
	memset(l1table, 0, 16*1024); 
2000/0906    
 
2000/1013    
	/* map low mem */ 
	for(o = 0; o < 1*OneMeg; o += OneMeg) 
		l1table[(0+o)>>20] = L1Section | L1KernelRW| L1Domain0  
			| L1Cached | L1Buffered 
			| ((0+o)&L1SectBaseMask); 
 
2000/1011    
	/* map DRAM */ 
	for(o = 0; o < DRAMTOP; o += OneMeg) 
2000/1013    
	for(o = 0; o < 128*OneMeg; o += OneMeg) 
2000/1011    
		l1table[(DRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0  
			| L1Cached | L1Buffered 
			| ((PHYSDRAM0+o)&L1SectBaseMask); 
2000/1012/sys/src/9/bitsy/mmu.c:194,2302000/1013/sys/src/9/bitsy/mmu.c:200,205
2000/0905    
} 
 
2000/1011    
/* 
2000/1012    
 *  maintain pids 
2000/1011    
 */ 
static Lock pidlock; 
                 
2000/1012    
void 
flushpids(void) 
{ 
	memset(l1table, 0, BY2WD*nelem(m->pid2proc)*32); 
	memset(m->pid2proc, 0, sizeof(m->pid2proc)); 
	flushcache(); 
	flushmmu(); 
} 
                 
2000/1011    
int 
newtlbpid(Proc *p) 
{ 
2000/1012    
	int i; 
                 
	ilock(&pidlock); 
	i = ++(m->lastpid); 
	if(i >= nelem(m->pid2proc)){ 
		flushpids(); 
		i = m->lastpid = 0; 
	} 
	m->pid2proc[i] = p; 
	p->tlbpid = i+1; 
	iunlock(&pidlock); 
	return p->tlbpid; 
2000/1011    
} 
                 
/* 
 *  table to map fault.c bits to physical bits 
 */ 
static ulong mmubits[16] = 
2000/1012/sys/src/9/bitsy/mmu.c:246,2792000/1013/sys/src/9/bitsy/mmu.c:221,250
2000/0905    
void 
2000/0902    
putmmu(ulong va, ulong pa, Page*) 
{ 
2000/1011    
	ulong pva; 
	Page *p; 
	ulong *t; 
 
2000/1012    
iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); 
	/* if user memory, add pid value */ 
2000/1011    
	if((va & 0xfe000000) == 0) 
2000/1012    
		pva = va | (up->tlbpid << 25); 
2000/1011    
	else 
		pva = va; 
                 
	/* always point L1 entry to L2 page, can't hurt */ 
	p = up->l1[va>>20]; 
2000/1013    
	p = up->l1page[va>>20]; 
2000/1011    
	if(p == nil){ 
		p = auxpage(); 
		if(p == nil) 
			pexit("out of memory", 1); 
		p->va = VA(kmap(p)); 
		up->l1[va>>20] = p; 
2000/1013    
		up->l1page[va>>20] = p; 
2000/1011    
	} 
	l1table[pva>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); 
2000/1013    
	l1table[va>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); 
iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); 
	up->l1table[va>>20] = l1table[va>>20]; 
2000/1011    
	t = (ulong*)p->va; 
 
	/* set L2 entry */ 
	t[(pva & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] 
2000/1013    
	t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] 
2000/1011    
		| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); 
2000/1013    
iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1011    
 
	wbflush(); 
2000/1013    
	flushmmu(); 
2000/0902    
} 
 
2000/1011    
/* 
2000/1012/sys/src/9/bitsy/mmu.c:285,2982000/1013/sys/src/9/bitsy/mmu.c:256,269
2000/1011    
	Page *pg; 
	int i; 
 
	for(i = 0; i < nelem(p->l1); i++){ 
		pg = p->l1[i]; 
2000/1013    
	for(i = 0; i < nelem(p->l1page); i++){ 
		pg = p->l1page[i]; 
2000/1011    
		if(pg == nil) 
			continue; 
		if(--pg->ref) 
			panic("mmurelease: pg->ref %d\n", pg->ref); 
		pagechainhead(pg); 
		p->l1[i] = nil; 
2000/1013    
		p->l1page[i] = nil; 
2000/1011    
	} 
2000/0902    
} 
 
2000/1012/sys/src/9/bitsy/mmu.c:299,3102000/1013/sys/src/9/bitsy/mmu.c:270,276
2000/0902    
void 
2000/1011    
mmuswitch(Proc* p) 
2000/0902    
{ 
2000/1011    
	/* set pid */ 
2000/1012    
	if(p->tlbpid <= 0) 
		p->tlbpid = newtlbpid(p); 
iprint("using tlbpid %d\n", p->tlbpid); 
	putpid(p->tlbpid<<25); 
2000/1011    
                 
	/* set domain register to this + the kernel's domains */ 
2000/1012    
	putdac((Dclient<<(2*p->tlbpid)) | Dclient); 
2000/1013    
//	flushcache();	/* drain and flush the cache */ 
//	flushmmu(); 
//	memmove(l1table, p->l1table, sizeof(p->l1table)); 
2000/0902    
} 
2000/1013/sys/src/9/bitsy/mmu.c:233,2402000/1014/sys/src/9/bitsy/mmu.c:233,242 (short | long)
2000/1011    
			pexit("out of memory", 1); 
		p->va = VA(kmap(p)); 
2000/1013    
		up->l1page[va>>20] = p; 
2000/1014    
		memset((uchar*)(p->va), 0, BY2PG); 
2000/1011    
	} 
2000/1013    
	l1table[va>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); 
2000/1014    
	cleanaddr((ulong)&l1table[va>>20]); 
2000/1013    
iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); 
	up->l1table[va>>20] = l1table[va>>20]; 
2000/1011    
	t = (ulong*)p->va; 
2000/1013/sys/src/9/bitsy/mmu.c:243,2502000/1014/sys/src/9/bitsy/mmu.c:245,253
2000/1013    
	t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] 
2000/1011    
		| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); 
2000/1013    
iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1014    
	cleanaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1011    
 
2000/1013    
	flushmmu(); 
2000/1014    
	wbflush(); 
2000/0902    
} 
 
2000/1011    
/* 
2000/1013/sys/src/9/bitsy/mmu.c:270,2762000/1014/sys/src/9/bitsy/mmu.c:273,304
2000/0902    
void 
2000/1011    
mmuswitch(Proc* p) 
2000/0902    
{ 
2000/1013    
//	flushcache();	/* drain and flush the cache */ 
//	flushmmu(); 
//	memmove(l1table, p->l1table, sizeof(p->l1table)); 
2000/1014    
iprint("switching to proc %d\n", p->pid); 
	memmove(l1table, p->l1table, sizeof(p->l1table)); 
	cleanaddr((ulong)l1table); 
	wbflush(); 
} 
 
void 
peekmmu(ulong va) 
{ 
	ulong e; 
 
	e = l1table[va>>20]; 
	switch(e & L1TypeMask){ 
	default: 
		iprint("l1: %lux invalid\n", e); 
		break; 
	case L1PageTable: 
		iprint("l1: %lux pt\n", e); 
		va &= OneMeg-1; 
		va >>= PGSHIFT; 
		e &= L1PTBaseMask; 
		e = ((ulong*)e)[va]; 
		iprint("l2: %lux\n", e); 
		break; 
	case L1Section: 
		iprint("l1: %lux section\n", e); 
		break; 
	} 
2000/0902    
} 
2000/1014/sys/src/9/bitsy/mmu.c:82,872000/1015/sys/src/9/bitsy/mmu.c:82,88 (short | long)
2000/1011    
	/* map zeros area */ 
	for(o = 0; o < 128 * OneMeg; o += OneMeg) 
		l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 
2000/1015    
			| L1Cached | L1Buffered 
2000/1011    
			| ((PHYSNULL0+o)&L1SectBaseMask); 
2000/0907    
 
2000/1011    
	/* map flash */ 
2000/1014/sys/src/9/bitsy/mmu.c:113,1212000/1015/sys/src/9/bitsy/mmu.c:114,122
2000/0929    
 
2000/1007    
	/* enable mmu */ 
	wbflush(); 
	flushcache(); 
	flushmmu(); 
2000/1015    
	mmuinvalidate(); 
2000/0929    
	mmuenable(); 
2000/1015    
	cacheflush(); 
2000/0907    
} 
 
/* 
2000/1014/sys/src/9/bitsy/mmu.c:224,2302000/1015/sys/src/9/bitsy/mmu.c:225,231
2000/1011    
	Page *p; 
	ulong *t; 
 
2000/1012    
iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); 
2000/1015    
//iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); 
2000/1011    
	/* always point L1 entry to L2 page, can't hurt */ 
2000/1013    
	p = up->l1page[va>>20]; 
2000/1011    
	if(p == nil){ 
2000/1014/sys/src/9/bitsy/mmu.c:236,2432000/1015/sys/src/9/bitsy/mmu.c:237,244
2000/1014    
		memset((uchar*)(p->va), 0, BY2PG); 
2000/1011    
	} 
2000/1013    
	l1table[va>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); 
2000/1014    
	cleanaddr((ulong)&l1table[va>>20]); 
2000/1013    
iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); 
2000/1015    
	cacheflushaddr((ulong)&l1table[va>>20]); 
//iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); 
2000/1013    
	up->l1table[va>>20] = l1table[va>>20]; 
2000/1011    
	t = (ulong*)p->va; 
 
2000/1014/sys/src/9/bitsy/mmu.c:244,2822000/1015/sys/src/9/bitsy/mmu.c:245,333
2000/1011    
	/* set L2 entry */ 
2000/1013    
	t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] 
2000/1011    
		| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); 
2000/1013    
iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1014    
	cleanaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1015    
//iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); 
	cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1011    
 
2000/1014    
	wbflush(); 
2000/0902    
} 
 
2000/1011    
/* 
 *  this is called with palloc locked so the pagechainhead is kosher 
2000/1015    
 *  free up all page tables for this proc 
2000/1011    
 */ 
2000/0902    
void 
2000/1011    
mmurelease(Proc* p) 
2000/1015    
mmuptefree(Proc *p) 
2000/0902    
{ 
2000/1011    
	Page *pg; 
	int i; 
 
2000/1013    
	for(i = 0; i < nelem(p->l1page); i++){ 
2000/1015    
	for(i = 0; i < Nmeg; i++){ 
2000/1013    
		pg = p->l1page[i]; 
2000/1011    
		if(pg == nil) 
			continue; 
2000/1015    
		p->l1page[i] = nil; 
		pg->next = p->mmufree; 
		p->mmufree = pg; 
	} 
	memset(p->l1table, 0, sizeof(p->l1table)); 
} 
 
/* 
 *  this is called with palloc locked so the pagechainhead is kosher 
 */ 
void 
mmurelease(Proc* p) 
{ 
	Page *pg, *next; 
 
	/* write back dirty cache entries before changing map */ 
	cacheflush(); 
 
	mmuptefree(p); 
 
	for(pg = p->mmufree; pg; pg = next){ 
		next = pg->next; 
2000/1011    
		if(--pg->ref) 
			panic("mmurelease: pg->ref %d\n", pg->ref); 
		pagechainhead(pg); 
2000/1013    
		p->l1page[i] = nil; 
2000/1011    
	} 
2000/1015    
	if(p->mmufree && palloc.r.p) 
		wakeup(&palloc.r); 
	p->mmufree = nil; 
 
	memset(l1table, 0, sizeof(p->l1table)); 
2000/0902    
} 
 
void 
2000/1011    
mmuswitch(Proc* p) 
2000/0902    
{ 
2000/1014    
iprint("switching to proc %d\n", p->pid); 
2000/1015    
	if(p->newtlb){ 
		mmuptefree(p); 
		p->newtlb = 0; 
	} 
 
	/* write back dirty cache entries before changing map */ 
	cacheflush(); 
 
	/* move in new map */ 
2000/1014    
	memmove(l1table, p->l1table, sizeof(p->l1table)); 
	cleanaddr((ulong)l1table); 
2000/1015    
 
	/* make sure map is in memory and drain write buffer */ 
	cacheflushaddr((ulong)l1table); 
2000/1014    
	wbflush(); 
2000/1015    
 
	/* lose any possible stale tlb entries */ 
	mmuinvalidate(); 
} 
 
void 
flushmmu(void) 
{ 
	int s; 
 
	s = splhi(); 
	up->newtlb = 1; 
	mmuswitch(up); 
	splx(s); 
2000/1014    
} 
 
void 
2000/1015/sys/src/9/bitsy/mmu.c:222,2512000/1016/sys/src/9/bitsy/mmu.c:222,256 (short | long)
2000/0905    
void 
2000/0902    
putmmu(ulong va, ulong pa, Page*) 
{ 
2000/1011    
	Page *p; 
2000/1016    
	Page *pg; 
2000/1011    
	ulong *t; 
 
2000/1015    
//iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); 
2000/1016    
print("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); 
2000/1011    
	/* always point L1 entry to L2 page, can't hurt */ 
2000/1013    
	p = up->l1page[va>>20]; 
2000/1011    
	if(p == nil){ 
		p = auxpage(); 
		if(p == nil) 
			pexit("out of memory", 1); 
		p->va = VA(kmap(p)); 
2000/1013    
		up->l1page[va>>20] = p; 
2000/1014    
		memset((uchar*)(p->va), 0, BY2PG); 
2000/1016    
	pg = up->l1page[va>>20]; 
	if(pg == nil){ 
		pg = up->mmufree; 
		if(pg != nil){ 
			up->mmufree = pg->next; 
		} else { 
			pg = auxpage(); 
			if(pg == nil) 
				pexit("out of memory", 1); 
		} 
		pg->va = VA(kmap(pg)); 
		up->l1page[va>>20] = pg; 
		memset((uchar*)(pg->va), 0, BY2PG); 
2000/1011    
	} 
2000/1013    
	l1table[va>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask); 
2000/1016    
	l1table[va>>20] = L1PageTable | L1Domain0 | (pg->pa & L1PTBaseMask); 
2000/1015    
	cacheflushaddr((ulong)&l1table[va>>20]); 
//iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); 
2000/1016    
print("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); 
2000/1013    
	up->l1table[va>>20] = l1table[va>>20]; 
2000/1011    
	t = (ulong*)p->va; 
2000/1016    
	t = (ulong*)pg->va; 
2000/1011    
 
	/* set L2 entry */ 
2000/1013    
	t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] 
2000/1011    
		| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); 
2000/1015    
//iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1016    
print("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1015    
	cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1011    
 
2000/1014    
	wbflush(); 
2000/1015/sys/src/9/bitsy/mmu.c:298,3052000/1016/sys/src/9/bitsy/mmu.c:303,314
2000/0902    
} 
 
void 
2000/1011    
mmuswitch(Proc* p) 
2000/1016    
mmuswitch(Proc *p) 
2000/0902    
{ 
2000/1016    
	if(m->mmupid == p->pid && p->newtlb == 0) 
		return; 
	m->mmupid = p->pid; 
 
2000/1015    
	if(p->newtlb){ 
		mmuptefree(p); 
		p->newtlb = 0; 
2000/1016/sys/src/9/bitsy/mmu.c:220,2592000/1018/sys/src/9/bitsy/mmu.c:220,276 (short | long)
2000/1011    
 *  add an entry to the current map 
 */ 
2000/0905    
void 
2000/0902    
putmmu(ulong va, ulong pa, Page*) 
2000/1018    
putmmu(ulong va, ulong pa, Page *pg) 
2000/0902    
{ 
2000/1016    
	Page *pg; 
2000/1011    
	ulong *t; 
2000/1018    
	Page *l2pg; 
	ulong *t, *l1p, *l2p; 
	int s; 
2000/1011    
 
2000/1016    
print("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); 
2000/1011    
	/* always point L1 entry to L2 page, can't hurt */ 
2000/1016    
	pg = up->l1page[va>>20]; 
	if(pg == nil){ 
		pg = up->mmufree; 
		if(pg != nil){ 
			up->mmufree = pg->next; 
2000/1018    
	s = splhi(); 
 
	/* clear out the current entry */ 
	mmuinvalidateaddr(va); 
 
	l2pg = up->l1page[va>>20]; 
	if(l2pg == nil){ 
		l2pg = up->mmufree; 
		if(l2pg != nil){ 
			up->mmufree = l2pg->next; 
2000/1016    
		} else { 
			pg = auxpage(); 
			if(pg == nil) 
2000/1018    
			l2pg = auxpage(); 
			if(l2pg == nil) 
2000/1016    
				pexit("out of memory", 1); 
		} 
		pg->va = VA(kmap(pg)); 
		up->l1page[va>>20] = pg; 
		memset((uchar*)(pg->va), 0, BY2PG); 
2000/1018    
		l2pg->va = VA(kmap(l2pg)); 
		up->l1page[va>>20] = l2pg; 
		memset((uchar*)(l2pg->va), 0, BY2PG); 
2000/1011    
	} 
2000/1016    
	l1table[va>>20] = L1PageTable | L1Domain0 | (pg->pa & L1PTBaseMask); 
2000/1015    
	cacheflushaddr((ulong)&l1table[va>>20]); 
2000/1016    
print("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); 
2000/1013    
	up->l1table[va>>20] = l1table[va>>20]; 
2000/1016    
	t = (ulong*)pg->va; 
2000/1011    
 
2000/1018    
	/* always point L1 entry to L2 page, can't hurt */ 
	l1p = &l1table[va>>20]; 
	*l1p = L1PageTable | L1Domain0 | (l2pg->pa & L1PTBaseMask); 
	up->l1table[va>>20] = *l1p; 
	t = (ulong*)l2pg->va; 
 
2000/1011    
	/* set L2 entry */ 
2000/1013    
	t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] 
2000/1018    
	l2p = &t[(va & (OneMeg-1))>>PGSHIFT]; 
	*l2p = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] 
2000/1011    
		| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); 
2000/1016    
print("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1015    
	cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); 
2000/1011    
 
2000/1014    
	wbflush(); 
2000/1018    
	/*  write back dirty entries - we need this because the pio() in 
	 *  fault.c is writing via a different virt addr and won't clean 
	 *  its changes out of the dcache.  Page coloring doesn't work 
	 *  on this mmu because the virtual cache is set associative 
	 *  rather than direct mapped. 
	 */ 
	cachewb(); 
	if(pg->cachectl[0] == PG_TXTFLUSH){ 
		/* pio() sets PG_TXTFLUSH whenever a text page has been written */ 
		icacheinvalidate(); 
		pg->cachectl[0] = PG_NOFLUSH; 
	} 
 
	splx(s); 
2000/0902    
} 
 
2000/1011    
/* 
2000/1016/sys/src/9/bitsy/mmu.c:300,3052000/1018/sys/src/9/bitsy/mmu.c:317,323
2000/1015    
	p->mmufree = nil; 
 
	memset(l1table, 0, sizeof(p->l1table)); 
2000/1018    
	cachewbregion(l1table, sizeof(p->l1table)); 
2000/0902    
} 
 
void 
2000/1016/sys/src/9/bitsy/mmu.c:309,3282000/1018/sys/src/9/bitsy/mmu.c:327,345
2000/1016    
		return; 
	m->mmupid = p->pid; 
 
2000/1018    
	/* write back dirty cache entries and invalidate all cache entries */ 
	cacheflush(); 
 
2000/1015    
	if(p->newtlb){ 
		mmuptefree(p); 
		p->newtlb = 0; 
	} 
 
	/* write back dirty cache entries before changing map */ 
	cacheflush(); 
                 
	/* move in new map */ 
2000/1014    
	memmove(l1table, p->l1table, sizeof(p->l1table)); 
2000/1015    
 
	/* make sure map is in memory and drain write buffer */ 
	cacheflushaddr((ulong)l1table); 
2000/1014    
	wbflush(); 
2000/1018    
	/* make sure map is in memory */ 
	cachewbregion(l1table, sizeof(p->l1table)); 
2000/1015    
 
	/* lose any possible stale tlb entries */ 
	mmuinvalidate(); 
2000/1018/sys/src/9/bitsy/mmu.c:127,1382000/1019/sys/src/9/bitsy/mmu.c:127,138 (short | long)
2000/0907    
{ 
	ulong *t; 
2000/0928    
	ulong va, i, base, end, off, entry; 
2000/0924    
	int livelarge; 
2000/1019    
	int large; 
2000/0924    
	ulong* rv; 
2000/0907    
 
2000/0924    
	rv = nil; 
	livelarge = len >= 128*1024; 
	if(livelarge){ 
2000/1019    
	large = len >= 128*1024; 
	if(large){ 
2000/0924    
		base = pa & ~(OneMeg-1); 
		end = (pa+len-1) & ~(OneMeg-1); 
	} else { 
2000/1018/sys/src/9/bitsy/mmu.c:145,1512000/1019/sys/src/9/bitsy/mmu.c:145,151
2000/0929    
		switch(l1table[va>>20] & L1TypeMask){ 
		default: 
2000/0924    
			/* found unused entry on level 1 table */ 
			if(livelarge){ 
2000/1019    
			if(large){ 
2000/0924    
				if(rv == nil) 
2000/0929    
					rv = (ulong*)(va+off); 
2000/1011    
				l1table[va>>20] = L1Section | L1KernelRW | L1Domain0 | 
2000/1018/sys/src/9/bitsy/mmu.c:171,1772000/1019/sys/src/9/bitsy/mmu.c:171,177
2000/1011    
				 
2000/0929    
			continue; 
		case L1PageTable: 
			if(livelarge) 
2000/1019    
			if(large) 
2000/0929    
				continue; 
			break; 
2000/0907    
		} 
2000/1018/sys/src/9/bitsy/mmu.c:178,1842000/1019/sys/src/9/bitsy/mmu.c:178,184
2000/0924    
 
2000/0929    
		/* here if we're using page maps instead of sections */ 
2000/0924    
		t = (ulong*)(l1table[va>>20] & L1PTBaseMask); 
2000/0907    
		for(i = 0; i < OneMeg; i += BY2PG){ 
2000/1019    
		for(i = 0; i < OneMeg && base <= end; i += BY2PG){ 
2000/0924    
			entry = t[i>>PGSHIFT]; 
2000/0921    
 
2000/0924    
			/* found unused entry on level 2 table */ 
2000/1018/sys/src/9/bitsy/mmu.c:196,2012000/1019/sys/src/9/bitsy/mmu.c:196,202
2000/0924    
	/* didn't fit */ 
	if(base <= end) 
		return nil; 
2000/1019    
	cacheflush(); 
2000/0924    
 
	return rv; 
2000/0905    
} 
2000/1018/sys/src/9/bitsy/mmu.c:359,3812000/1019/sys/src/9/bitsy/mmu.c:360,382
2000/1014    
void 
peekmmu(ulong va) 
{ 
	ulong e; 
2000/1019    
	ulong e, d; 
2000/1014    
 
	e = l1table[va>>20]; 
	switch(e & L1TypeMask){ 
	default: 
		iprint("l1: %lux invalid\n", e); 
2000/1019    
		iprint("l1: %lux[%lux] = %lux invalid\n", l1table, va>>20, e); 
2000/1014    
		break; 
	case L1PageTable: 
		iprint("l1: %lux pt\n", e); 
2000/1019    
		iprint("l1: %lux[%lux] = %lux pt\n", l1table, va>>20, e); 
2000/1014    
		va &= OneMeg-1; 
		va >>= PGSHIFT; 
		e &= L1PTBaseMask; 
		e = ((ulong*)e)[va]; 
		iprint("l2: %lux\n", e); 
2000/1019    
		d = ((ulong*)e)[va]; 
		iprint("l2: %lux[%lux] = %lux\n", e, va, d); 
2000/1014    
		break; 
	case L1Section: 
		iprint("l1: %lux section\n", e); 
2000/1019    
		iprint("l1: %lux[%lux] = %lux section\n", l1table, va>>20, e); 
2000/1014    
		break; 
	} 
2000/0902    
} 
2000/1019/sys/src/9/bitsy/mmu.c:318,3242000/1106/sys/src/9/bitsy/mmu.c:318,324 (short | long)
2000/1015    
	p->mmufree = nil; 
 
	memset(l1table, 0, sizeof(p->l1table)); 
2000/1018    
	cachewbregion(l1table, sizeof(p->l1table)); 
2000/1106    
	cachewbregion((ulong)l1table, sizeof(p->l1table)); 
2000/0902    
} 
 
void 
2000/1019/sys/src/9/bitsy/mmu.c:340,3462000/1106/sys/src/9/bitsy/mmu.c:340,346
2000/1014    
	memmove(l1table, p->l1table, sizeof(p->l1table)); 
2000/1015    
 
2000/1018    
	/* make sure map is in memory */ 
	cachewbregion(l1table, sizeof(p->l1table)); 
2000/1106    
	cachewbregion((ulong)l1table, sizeof(p->l1table)); 
2000/1015    
 
	/* lose any possible stale tlb entries */ 
	mmuinvalidate(); 
2000/1106/sys/src/9/bitsy/mmu.c:51,582000/1118/sys/src/9/bitsy/mmu.c:51,58 (short | long)
2000/0906    
}; 
 
2000/0907    
ulong *l1table; 
2000/1118    
static int mmuinited; 
2000/0906    
 
2000/1007    
                 
2000/0906    
/* 
 *  We map all of memory, flash, and the zeros area with sections. 
 *  Special use space is mapped on the fly with regmap. 
2000/1106/sys/src/9/bitsy/mmu.c:67,732000/1118/sys/src/9/bitsy/mmu.c:67,73
2000/1007    
	l1table = xspanalloc(16*1024, 16*1024, 0); 
	memset(l1table, 0, 16*1024); 
2000/0906    
 
2000/1013    
	/* map low mem */ 
2000/1118    
	/* map low mem (I really don't know why I have to do this -- presotto) */ 
2000/1013    
	for(o = 0; o < 1*OneMeg; o += OneMeg) 
		l1table[(0+o)>>20] = L1Section | L1KernelRW| L1Domain0  
			| L1Cached | L1Buffered 
2000/1106/sys/src/9/bitsy/mmu.c:74,942000/1118/sys/src/9/bitsy/mmu.c:74,93
2000/1013    
			| ((0+o)&L1SectBaseMask); 
 
2000/1011    
	/* map DRAM */ 
2000/1013    
	for(o = 0; o < 128*OneMeg; o += OneMeg) 
2000/1118    
	for(o = 0; o < DRAMTOP-DRAMZERO; o += OneMeg) 
2000/1011    
		l1table[(DRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0  
			| L1Cached | L1Buffered 
			| ((PHYSDRAM0+o)&L1SectBaseMask); 
2000/0907    
 
2000/1011    
	/* map zeros area */ 
	for(o = 0; o < 128 * OneMeg; o += OneMeg) 
2000/1118    
	for(o = 0; o < NULLTOP-NULLZERO; o += OneMeg) 
2000/1011    
		l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 
2000/1015    
			| L1Cached | L1Buffered 
2000/1011    
			| ((PHYSNULL0+o)&L1SectBaseMask); 
2000/0907    
 
2000/1011    
	/* map flash */ 
	for(o = 0; o < 128 * OneMeg; o += OneMeg) 
2000/1118    
	for(o = 0; o < FLASHTOP-FLASHZERO; o += OneMeg) 
2000/1011    
		l1table[(FLASHZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 
			| L1Cached | L1Buffered 
			| ((PHYSFLASH0+o)&L1SectBaseMask); 
2000/0907    
 
2000/1011    
	/* map peripheral control module regs */ 
2000/1106/sys/src/9/bitsy/mmu.c:117,1292000/1118/sys/src/9/bitsy/mmu.c:116,130
2000/1015    
	mmuinvalidate(); 
2000/0929    
	mmuenable(); 
2000/1015    
	cacheflush(); 
2000/1118    
 
	mmuinited = 1; 
2000/0907    
} 
 
/* 
2000/0923    
 *  map special space uncached, assume that the space isn't already mapped 
2000/1118    
 *  map on request 
2000/0907    
 */ 
2000/1002    
void* 
2000/0924    
mapspecial(ulong pa, int len) 
2000/1118    
static void* 
_map(ulong pa, int len, ulong zero, ulong top, ulong l1prop, ulong l2prop) 
2000/0907    
{ 
	ulong *t; 
2000/0928    
	ulong va, i, base, end, off, entry; 
2000/1106/sys/src/9/bitsy/mmu.c:141,1472000/1118/sys/src/9/bitsy/mmu.c:142,148
2000/0924    
	} 
	off = pa - base; 
2000/0921    
 
2000/0929    
	for(va = REGZERO; va < REGTOP && base <= end; va += OneMeg){ 
2000/1118    
	for(va = zero; va < top && base <= end; va += OneMeg){ 
2000/0929    
		switch(l1table[va>>20] & L1TypeMask){ 
		default: 
2000/0924    
			/* found unused entry on level 1 table */ 
2000/1106/sys/src/9/bitsy/mmu.c:148,1542000/1118/sys/src/9/bitsy/mmu.c:149,155
2000/1019    
			if(large){ 
2000/0924    
				if(rv == nil) 
2000/0929    
					rv = (ulong*)(va+off); 
2000/1011    
				l1table[va>>20] = L1Section | L1KernelRW | L1Domain0 | 
2000/1118    
				l1table[va>>20] = L1Section | l1prop | L1Domain0 | 
2000/0929    
							(base & L1SectBaseMask); 
2000/0924    
				base += OneMeg; 
				continue; 
2000/1106/sys/src/9/bitsy/mmu.c:166,1722000/1118/sys/src/9/bitsy/mmu.c:167,173
2000/1011    
			entry = l1table[va>>20]; 
			i = entry & L1SectBaseMask; 
			if(pa >= i && (pa+len) <= i + OneMeg) 
			if((entry & ~L1SectBaseMask) == (L1Section | L1KernelRW | L1Domain0)) 
2000/1118    
			if((entry & ~L1SectBaseMask) == (L1Section | l1prop | L1Domain0)) 
2000/1011    
				return (void*)(va + (pa & (OneMeg-1))); 
				 
2000/0929    
			continue; 
2000/1106/sys/src/9/bitsy/mmu.c:185,1912000/1118/sys/src/9/bitsy/mmu.c:186,192
2000/0924    
			if((entry & L2TypeMask) != L2SmallPage){ 
				if(rv == nil) 
2000/0929    
					rv = (ulong*)(va+i+off); 
2000/0924    
				t[i>>PGSHIFT] = L2SmallPage | L2KernelRW |  
2000/1118    
				t[i>>PGSHIFT] = L2SmallPage | l2prop |  
2000/0924    
						(base & L2PageBaseMask); 
				base += BY2PG; 
				continue; 
2000/1106/sys/src/9/bitsy/mmu.c:199,2042000/1118/sys/src/9/bitsy/mmu.c:200,308
2000/1019    
	cacheflush(); 
2000/0924    
 
	return rv; 
2000/1118    
} 
 
/* map in i/o registers */ 
void* 
mapspecial(ulong pa, int len) 
{ 
	return _map(pa, len, REGZERO, REGTOP, L1KernelRW, L2KernelRW); 
} 
 
/* map add on memory */ 
void* 
mapmem(ulong pa, int len) 
{ 
	return _map(pa, len, EMEMZERO, EMEMTOP, L1KernelRW|L1Cached|L1Buffered, 
			L2KernelRW|L2Cached|L2Buffered); 
} 
 
/* map a virtual address to a physical one */ 
ulong 
mmu_paddr(ulong va) 
{ 
	ulong entry; 
	ulong *t; 
 
	entry = l1table[va>>20]; 
	switch(entry & L1TypeMask){ 
	case L1Section: 
		return (entry & L1SectBaseMask) | (va & (OneMeg-1)); 
	case L1PageTable: 
		t = (ulong*)(entry & L1PTBaseMask); 
		va &= OneMeg-1; 
		entry = t[va>>PGSHIFT]; 
		switch(entry & L1TypeMask){ 
		case L2SmallPage: 
			return (entry & L2PageBaseMask) | (va & (BY2PG-1)); 
		} 
	} 
	return 0; 
} 
 
/* map a physical address to a virtual one */ 
static ulong 
findva(ulong pa, ulong zero, ulong top) 
{ 
	int i; 
	ulong entry, va; 
	ulong start, end; 
	ulong *t; 
 
	for(va = zero; va < top; va += OneMeg){ 
		/* search the L1 entry */ 
		entry = l1table[va>>20]; 
		switch(entry & L1TypeMask){ 
		default: 
			return 0;	/* no holes */ 
		case L1Section: 
			start = entry & L1SectBaseMask; 
			end = start + OneMeg; 
			if(pa >= start && pa < end) 
				return va | (pa & (OneMeg-1)); 
			continue; 
		case L1PageTable: 
			break; 
		} 
 
		/* search the L2 entry */ 
		t = (ulong*)(l1table[va>>20] & L1PTBaseMask); 
		for(i = 0; i < OneMeg; i += BY2PG){ 
			entry = t[i>>PGSHIFT]; 
 
			/* found unused entry on level 2 table */ 
			if((entry & L2TypeMask) != L2SmallPage) 
				break; 
 
			start = entry & L2PageBaseMask; 
			end = start + BY2PG; 
			if(pa >= start && pa < end) 
				return va | (BY2PG*i) | (pa & (BY2PG-1)); 
		} 
	} 
	return 0; 
} 
ulong 
mmu_kaddr(ulong pa) 
{ 
	ulong va; 
 
	/* try the easy stuff first (the first case is true most of the time) */ 
	if(pa >= PHYSDRAM0 && pa <= PHYSDRAM0+(DRAMTOP-DRAMZERO)) 
		return DRAMZERO+(pa-PHYSDRAM0); 
	if(pa >= PHYSFLASH0 && pa <= PHYSFLASH0+(FLASHTOP-FLASHZERO)) 
		return FLASHZERO+(pa-PHYSFLASH0); 
	if(pa >= PHYSNULL0 && pa <= PHYSNULL0+(NULLTOP-NULLZERO)) 
		return NULLZERO+(pa-PHYSNULL0); 
 
	if(!mmuinited) 
		return 0;	/* this shouldn't happen */ 
 
	/* walk the map for the special regs and extended memory */ 
	va = findva(pa, EMEMZERO, EMEMTOP); 
	if(va != 0) 
		return va; 
	return findva(pa, REGZERO, REGTOP); 
2000/0905    
} 
 
2000/1011    
/* 
2000/1118/sys/src/9/bitsy/mmu.c:211,2202000/1121/sys/src/9/bitsy/mmu.c:211,228 (short | long)
2000/1118    
 
/* map add on memory */ 
void* 
mapmem(ulong pa, int len) 
2000/1121    
mapmem(ulong pa, int len, int cached) 
2000/1118    
{ 
	return _map(pa, len, EMEMZERO, EMEMTOP, L1KernelRW|L1Cached|L1Buffered, 
			L2KernelRW|L2Cached|L2Buffered); 
2000/1121    
	ulong l1, l2; 
 
	if(cached){ 
		l1 = L1KernelRW|L1Cached|L1Buffered; 
		l2 = L2KernelRW|L2Cached|L2Buffered; 
	} else { 
		l1 = L1KernelRW; 
		l2 = L2KernelRW; 
	} 
	return _map(pa, len, EMEMZERO, EMEMTOP, l1, l2); 
2000/1118    
} 
 
/* map a virtual address to a physical one */ 
2000/1121/sys/src/9/bitsy/mmu.c:79,842000/1130/sys/src/9/bitsy/mmu.c:79,89 (short | long)
2000/1011    
			| L1Cached | L1Buffered 
			| ((PHYSDRAM0+o)&L1SectBaseMask); 
2000/0907    
 
2000/1130    
	/* uncached DRAM */ 
	for(o = 0; o < UCDRAMTOP-UCDRAMZERO; o += OneMeg) 
		l1table[(UCDRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0  
			| ((PHYSDRAM0+o)&L1SectBaseMask); 
 
2000/1011    
	/* map zeros area */ 
2000/1118    
	for(o = 0; o < NULLTOP-NULLZERO; o += OneMeg) 
2000/1011    
		l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)