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);