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

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

2000/0923/sys/src/9/bitsy/mmu.c:94,1552000/0924/sys/src/9/bitsy/mmu.c:94,158 (short | long | prev | next)
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 


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