ref: 74db0f96a8251c01d2b5138f9224b7daab6cc9b6
parent: 22eb04ac6077bbc590f9ae04d037baaa3377240a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Jun 28 14:12:13 EDT 2019
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.
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -157,6 +157,7 @@
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*);
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -103,45 +103,6 @@
}
}
-/*
- * 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)
{--- a/sys/src/9/pc64/mmu.c
+++ b/sys/src/9/pc64/mmu.c
@@ -271,7 +271,11 @@
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;
@@ -568,5 +572,64 @@
mask = l == 0 ? 3<<3 | 1<<7 : 3<<3 | 1<<12;
attr = (((PATWC&3)<<3) | ((PATWC&4)<<5) | ((PATWC&4)<<10));
*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;
+ }
}
}
--
⑨