ref: bfbc5ab1970bbf9307e03a42e69b0d55eb92f2ef
parent: f029ea1694b4f0f8ec0cc848b936b0122bd17347
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;