git: 9front

Download patch

ref: 93b93be63818cf02b18ab6d53b3420517f2f21bd
parent: 0649393fceae059f8486caec5258c35534ccb827
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Feb 6 17:41:42 EST 2014

pc64: fix kmap()

kmapindex has to be per process, not per mach, as the process
can be switched to another processor while the mapping is
established.

to bootstrap the first process, we have to temporarily set up
so the kmap MMU's can be attached to the process. previously
we assumed that the first two pages for the initial process
where below 2GB and could be accessed with KADDR() directly.
with 16GB machine, all the 2GB above KZERO are dedicated to
the kernel so the user pages returned by newpage() need to
be mapped.

--- a/sys/src/9/pc64/dat.h
+++ b/sys/src/9/pc64/dat.h
@@ -142,6 +142,7 @@
 	MMU*	kmaphead;
 	MMU*	kmaptail;
 	int	kmapcount;
+	int	kmapindex;
 	int	mmucount;
 };
 
@@ -182,7 +183,6 @@
 	u64int	mmumap[4];		/* bitmap of pml4 entries for zapping */
 	MMU*	mmufree;		/* freelist for MMU structures */
 	int	mmucount;		/* number of MMU structures in freelist */
-	int	kmapindex;		/* next KMAP page index for use */
 
 	ulong	ticks;			/* of the clock since boot time */
 	Label	sched;			/* scheduler wakeup */
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -346,6 +346,9 @@
 	p->sched.pc = (uintptr)init0;
 	p->sched.sp = (uintptr)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
 
+	/* temporarily set up for kmap() */
+	up = p;
+
 	/*
 	 * User Stack
 	 */
@@ -371,6 +374,10 @@
 	memset(v, 0, BY2PG);
 	memmove(v, initcode, sizeof initcode);
 	kunmap(v);
+
+	/* free kmap */
+	mmurelease(p);
+	up = nil;
 
 	ready(p);
 }
--- a/sys/src/9/pc64/mmu.c
+++ b/sys/src/9/pc64/mmu.c
@@ -415,7 +415,7 @@
 		proc->mmucount += proc->kmapcount;
 
 		proc->kmaphead = proc->kmaptail = nil;
-		proc->kmapcount = 0;
+		proc->kmapcount = proc->kmapindex = 0;
 	}
 	mmufree(proc);
 	taskswitch((uintptr)m+MACHSIZE);
@@ -469,13 +469,13 @@
 		return (KMap*)KADDR(pa);
 
 	x = splhi();
-	va = KMAP + ((uintptr)m->kmapindex << PGSHIFT);
+	va = KMAP + ((uintptr)up->kmapindex << PGSHIFT);
 	pte = mmuwalk(m->pml4, va, 0, 1);
 	if(pte == 0 || *pte & PTEVALID)
 		panic("kmap: pa=%#p va=%#p", pa, va);
 	*pte = pa | PTEWRITE|PTEVALID;
-	m->kmapindex = (m->kmapindex + 1) % (1<<PTSHIFT);
-	if(m->kmapindex == 0)
+ 	up->kmapindex = (up->kmapindex + 1) % (1<<PTSHIFT);
+	if(up->kmapindex == 0)
 		mmuflushtlb();
 	splx(x);
 	return (KMap*)va;
--