shithub: riscv

Download patch

ref: bfee76e5d34e893f7af047e6cd4358f5f1fbf428
parent: b7b3406657ef87fef57c3b639296d5cd33a5c3ae
author: cinap_lenrek <[email protected]>
date: Sun Feb 2 13:01:13 EST 2014

pc64: track per process kmap page tables in separate MMU list.

we have to keep kmap page tables in ther own list
because user tables are subject to (virtual) tlb flushing.

we never free kmap page tables except in mmurelease()
where we just link the kmap mmu list in front of the user
mmus and call mmufree() which will free all the mmu's
of the process.

--- a/sys/src/9/pc64/dat.h
+++ b/sys/src/9/pc64/dat.h
@@ -137,8 +137,11 @@
 #define NCOLOR 1
 struct PMMU
 {
-	MMU	*mmuhead;
-	MMU	*mmutail;
+	MMU*	mmuhead;
+	MMU*	mmutail;
+	MMU*	kmaphead;
+	MMU*	kmaptail;
+	int	kmapcount;
 	int	mmucount;
 };
 
--- a/sys/src/9/pc64/mem.h
+++ b/sys/src/9/pc64/mem.h
@@ -57,8 +57,8 @@
 #define VMAP		(0xffffffff00000000ull)	/* 2GB identity map of upper 2GB ram */
 #define VMAPSIZE	(2*GiB)
 
-#define	KMAP		(0xffffff7f00000000ull)
-#define KMAPSIZE	(512*GiB)
+#define	KMAP		(0xffffff7f00000000ull)	/* 2MB for per process temporary kernel mappings */
+#define KMAPSIZE	(2*MiB)
 
 /*
  * Fundamental addresses - bottom 64kB saved for return to real mode
--- a/sys/src/9/pc64/mmu.c
+++ b/sys/src/9/pc64/mmu.c
@@ -227,25 +227,36 @@
 				return 0;
 			pte = PTEWRITE|PTEVALID;
 			if(va < VMAP){
-				if(va < TSTKTOP)
+				if(va < TSTKTOP){
 					pte |= PTEUSER;
-				p = mmualloc();
-				p->index = x;
-				p->level = i;
-				if(i == PML4E){
-					/* PML4 entries linked to head */
-					p->next = up->mmuhead;
-					if(p->next == nil)
-						up->mmutail = p;
-					up->mmuhead = p;
-					if(p->index <= PTLX(TSTKTOP, 3))
+
+					p = mmualloc();
+					p->index = x;
+					p->level = i;
+					if(i == PML4E){
+						if((p->next = up->mmuhead) == nil)
+							up->mmutail = p;
+						up->mmuhead = p;
 						m->mmumap[p->index/MAPBITS] |= 1ull<<(p->index%MAPBITS);
-				} else {
-					/* PDP and PD entries linked to tail */
-					up->mmutail->next = p;
-					up->mmutail = p;
-				}
-				up->mmucount++;
+					} else {
+						up->mmutail->next = p;
+						up->mmutail = p;
+					}
+					up->mmucount++;
+				} else if(va >= KMAP && va < (KMAP+KMAPSIZE)) {
+					p = mmualloc();
+					p->index = x;
+					p->level = i;
+					if(i == PML4E){
+						up->kmaptail = p;
+						up->kmaphead = p;
+					} else {
+						up->kmaptail->next = p;
+						up->kmaptail = p;
+					}
+					up->kmapcount++;
+				} else
+					return 0;
 				page = p->page;
 			} else if(didmmuinit) {
 				page = mallocalign(PTSZ, BY2PG, 0, 0);
@@ -375,7 +386,6 @@
 void
 mmuswitch(Proc *proc)
 {
-	uintptr pte;
 	MMU *p;
 
 	mmuzap();
@@ -383,13 +393,11 @@
 		mmufree(proc);
 		proc->newtlb = 0;
 	}
-	for(p = proc->mmuhead; p && p->level==PML4E; p = p->next){
-		pte = PADDR(p->page) | PTEWRITE|PTEVALID;
-		if(p->index <= PTLX(TSTKTOP, 3)){
-			m->mmumap[p->index/MAPBITS] |= 1ull<<(p->index%MAPBITS);
-			pte |= PTEUSER;
-		}
-		m->pml4[p->index] = pte;
+	if((p = proc->kmaphead) != nil)
+		m->pml4[PTLX(KMAP, 3)] = PADDR(p->page) | PTEWRITE|PTEVALID;
+	for(p = proc->mmuhead; p != nil && p->level == PML4E; p = p->next){
+		m->mmumap[p->index/MAPBITS] |= 1ull<<(p->index%MAPBITS);
+		m->pml4[p->index] = PADDR(p->page) | PTEUSER|PTEWRITE|PTEVALID;
 	}
 	taskswitch((uintptr)proc->kstack+KSTACK);
 }
@@ -397,7 +405,18 @@
 void
 mmurelease(Proc *proc)
 {
+	MMU *p;
+
 	mmuzap();
+	if((p = proc->kmaptail) != nil){
+		if((p->next = proc->mmuhead) == nil)
+			proc->mmutail = p;
+		proc->mmuhead = p;
+		proc->mmucount += proc->kmapcount;
+
+		proc->kmaphead = proc->kmaptail = nil;
+		proc->kmapcount = 0;
+	}
 	mmufree(proc);
 	taskswitch((uintptr)m+MACHSIZE);
 }
@@ -410,10 +429,8 @@
 
 	x = splhi();
 	pte = mmuwalk(m->pml4, va, 0, 1);
-	if(pte == 0){
+	if(pte == 0)
 		panic("putmmu: bug: va=%#p pa=%#p", va, pa);
-		return;
-	}
 	old = *pte;
 	*pte = pa | PTEVALID|PTEUSER;
 	splx(x);