~kris/9p

9hist

932da88aa778957f97318743d9d7784c03aa4169 — David du Colombier 25 years ago eae1d26
Plan 9 from Bell Labs 2000-09-24
1 files changed, 48 insertions(+), 45 deletions(-)

M bitsy/mmu.c
M bitsy/mmu.c => bitsy/mmu.c +48 -45
@@ 94,62 94,65 @@ mmuinit(void)
 *  map special space uncached, assume that the space isn't already mapped
 */
ulong*
mapspecmeg(ulong physaddr, int len)
ulong*
mapspecial(ulong physaddr, int len)
mapspecial(ulong pa, int len)
{
	ulong *t;
	ulong virtaddr, i, base, end, off, entry, candidate;

	base = physaddr & ~(BY2PG-1);
	end = (physaddr+len-1) & ~(BY2PG-1);
	if(len > 128*1024)
		usemeg = 1;
	off = 0;
	candidate = 0;

	/* first see if we've mapped it somewhere, the first hole means we're done */
	for(virtaddr = REGZERO; virtaddr < REGTOP; virtaddr += OneMeg){
		if((l1table[virtaddr>>20] & L1TypeMask) != L1PageTable){
			/* create a page table and break */
	ulong va, i, base, end, off;
	int livelarge;
	ulong* rv;

	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;

	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 */
			t = xspanalloc(BY2PG, 1024, 0);
			memzero(t, BY2PG, 0);
			l1table[virtaddr>>20] = L1PageTable | L1Domain0 |
			l1table[va>>20] = L1PageTable | L1Domain0 |
						(((ulong)t) & L1PTBaseMask);
			break;
		}
		t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask);

		t = (ulong*)(l1table[va>>20] & L1PTBaseMask);
		for(i = 0; i < OneMeg; i += BY2PG){
			entry = t[(virtaddr+i)>>20];

			/* first hole means nothing left, add map */
			if((entry & L2TypeMask) != L2SmallPage)
				break;

			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;
				}
			entry = t[i>>PGSHIFT];

			/* 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;
			}

			/* if we're at the end of the range, area is already mapped */
			if((entry & L2PageBaseMask) == end)
				return candidate + (physaddr-base);
		}
		if(i < OneMeg){
			virtaddr += i;
			break;
		}
	}

	/* we get here if no entry was found mapping this physical range */
	/* didn't fit */
	if(base <= end)
		return nil;

	return rv;
}

void