summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2019-06-28 18:12:13 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2019-06-28 18:12:13 +0200
commitb2c7a8d84a0075fea104009115d0c34bffc39e06 (patch)
tree915ff021b261043e3b04b695418f1fe86d4ea52f
parent6118d778581b44e5c41a04a60d4aa8e6cad4a37c (diff)
downloadplan9front-b2c7a8d84a0075fea104009115d0c34bffc39e06.tar.xz
pc64: preallocate mmupool page tables
preallocate 2% of user pages for page tables and MMU structures and keep them mapped in the VMAP range. this leaves more space in the KZERO window and avoids running out of kernel memory on machines with large amounts of memory.
-rw-r--r--sys/src/9/pc64/fns.h1
-rw-r--r--sys/src/9/pc64/main.c39
-rw-r--r--sys/src/9/pc64/mmu.c65
3 files changed, 65 insertions, 40 deletions
diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h
index e993e60b1..d0d585ef3 100644
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -157,6 +157,7 @@ void pcmspecialclose(int);
void (*_pcmspecialclose)(int);
void pcmunmap(int, PCMmap*);
void pmap(uintptr *, uintptr, uintptr, vlong);
+void preallocpages(void);
void procrestore(Proc*);
void procsave(Proc*);
void procsetup(Proc*);
diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c
index e61840ea0..c8e705f49 100644
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -103,45 +103,6 @@ confinit(void)
}
}
-/*
- * The palloc.pages array can be a large chunk out of the 2GB
- * window above KZERO, so we allocate the array from
- * upages and map in the VMAP window before pageinit()
- */
-static void
-preallocpages(void)
-{
- Pallocmem *pm;
- uintptr va, base, top;
- vlong size;
- ulong np;
- int i;
-
- np = 0;
- for(i=0; i<nelem(palloc.mem); i++){
- pm = &palloc.mem[i];
- np += pm->npage;
- }
- size = (uvlong)np * BY2PG;
- size += sizeof(Page) + BY2PG; /* round up */
- size = (size / (sizeof(Page) + BY2PG)) * sizeof(Page);
- size = ROUND(size, PGLSZ(1));
-
- for(i=0; i<nelem(palloc.mem); i++){
- pm = &palloc.mem[i];
- base = ROUND(pm->base, PGLSZ(1));
- top = pm->base + (uvlong)pm->npage * BY2PG;
- if((base + size) <= VMAPSIZE && (vlong)(top - base) >= size){
- va = base + VMAP;
- pmap(m->pml4, base | PTEGLOBAL|PTEWRITE|PTEVALID, va, size);
- palloc.pages = (Page*)va;
- pm->base = base + size;
- pm->npage = (top - pm->base)/BY2PG;
- break;
- }
- }
-}
-
void
machinit(void)
{
diff --git a/sys/src/9/pc64/mmu.c b/sys/src/9/pc64/mmu.c
index 9261354e8..dfb165ef5 100644
--- a/sys/src/9/pc64/mmu.c
+++ b/sys/src/9/pc64/mmu.c
@@ -271,7 +271,11 @@ mmuwalk(uintptr* table, uintptr va, int level, int create)
if(pte & PTEVALID){
if(pte & PTESIZE)
return 0;
- table = KADDR(PPN(pte));
+ pte = PPN(pte);
+ if(pte >= (uintptr)-KZERO)
+ table = (void*)(pte + VMAP);
+ else
+ table = (void*)(pte + KZERO);
} else {
if(!create)
return 0;
@@ -570,3 +574,62 @@ patwc(void *a, int n)
*pte = (*pte & ~mask) | (attr & mask);
}
}
+
+/*
+ * The palloc.pages array and mmupool can be a large chunk
+ * out of the 2GB window above KZERO, so we allocate from
+ * upages and map in the VMAP window before pageinit()
+ */
+void
+preallocpages(void)
+{
+ Pallocmem *pm;
+ uintptr va, base, top;
+ vlong tsize, psize;
+ ulong np, nt;
+ int i;
+
+ np = 0;
+ for(i=0; i<nelem(palloc.mem); i++){
+ pm = &palloc.mem[i];
+ np += pm->npage;
+ }
+ nt = np / 50; /* 2% for mmupool */
+ np -= nt;
+
+ nt = (uvlong)nt*BY2PG / (sizeof(MMU)+PTSZ);
+ tsize = (uvlong)nt * (sizeof(MMU)+PTSZ);
+
+ psize = (uvlong)np * BY2PG;
+ psize += sizeof(Page) + BY2PG;
+ psize = (psize / (sizeof(Page)+BY2PG)) * sizeof(Page);
+
+ psize += tsize;
+ psize = ROUND(psize, PGLSZ(1));
+
+ for(i=0; i<nelem(palloc.mem); i++){
+ pm = &palloc.mem[i];
+ base = ROUND(pm->base, PGLSZ(1));
+ top = pm->base + (uvlong)pm->npage * BY2PG;
+ if((base + psize) <= VMAPSIZE && (vlong)(top - base) >= psize){
+ pm->base = base + psize;
+ pm->npage = (top - pm->base)/BY2PG;
+
+ va = base + VMAP;
+ pmap(m->pml4, base | PTEGLOBAL|PTEWRITE|PTEVALID, va, psize);
+
+ palloc.pages = (void*)(va + tsize);
+
+ mmupool.nfree = mmupool.nalloc = nt;
+ mmupool.free = (void*)(va + (uvlong)nt*PTSZ);
+ for(i=0; i<nt; i++){
+ mmupool.free[i].page = (uintptr*)va;
+ mmupool.free[i].next = &mmupool.free[i+1];
+ va += PTSZ;
+ }
+ mmupool.free[i-1].next = nil;
+
+ break;
+ }
+ }
+}