changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: pc64: preallocate mmupool page tables

changeset 7300: 6228acd5dfd1
parent 7299: 2c3cb67101c4
child 7301: e24206b69d32
author: cinap_lenrek@felloff.net
date: Fri, 28 Jun 2019 18:12:13 +0200
files: sys/src/9/pc64/fns.h sys/src/9/pc64/main.c sys/src/9/pc64/mmu.c
description: 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.
     1.1--- a/sys/src/9/pc64/fns.h
     1.2+++ b/sys/src/9/pc64/fns.h
     1.3@@ -157,6 +157,7 @@ void	pcmspecialclose(int);
     1.4 void	(*_pcmspecialclose)(int);
     1.5 void	pcmunmap(int, PCMmap*);
     1.6 void	pmap(uintptr *, uintptr, uintptr, vlong);
     1.7+void	preallocpages(void);
     1.8 void	procrestore(Proc*);
     1.9 void	procsave(Proc*);
    1.10 void	procsetup(Proc*);
     2.1--- a/sys/src/9/pc64/main.c
     2.2+++ b/sys/src/9/pc64/main.c
     2.3@@ -103,45 +103,6 @@ confinit(void)
     2.4 	}
     2.5 }
     2.6 
     2.7-/*
     2.8- * The palloc.pages array can be a large chunk out of the 2GB
     2.9- * window above KZERO, so we allocate the array from
    2.10- * upages and map in the VMAP window before pageinit()
    2.11- */
    2.12-static void
    2.13-preallocpages(void)
    2.14-{
    2.15-	Pallocmem *pm;
    2.16-	uintptr va, base, top;
    2.17-	vlong size;
    2.18-	ulong np;
    2.19-	int i;
    2.20-
    2.21-	np = 0;
    2.22-	for(i=0; i<nelem(palloc.mem); i++){
    2.23-		pm = &palloc.mem[i];
    2.24-		np += pm->npage;
    2.25-	}
    2.26-	size = (uvlong)np * BY2PG;
    2.27-	size += sizeof(Page) + BY2PG;	/* round up */
    2.28-	size = (size / (sizeof(Page) + BY2PG)) * sizeof(Page);
    2.29-	size = ROUND(size, PGLSZ(1));
    2.30-
    2.31-	for(i=0; i<nelem(palloc.mem); i++){
    2.32-		pm = &palloc.mem[i];
    2.33-		base = ROUND(pm->base, PGLSZ(1));
    2.34-		top = pm->base + (uvlong)pm->npage * BY2PG;
    2.35-		if((base + size) <= VMAPSIZE && (vlong)(top - base) >= size){
    2.36-			va = base + VMAP;
    2.37-			pmap(m->pml4, base | PTEGLOBAL|PTEWRITE|PTEVALID, va, size);
    2.38-			palloc.pages = (Page*)va;
    2.39-			pm->base = base + size;
    2.40-			pm->npage = (top - pm->base)/BY2PG;
    2.41-			break;
    2.42-		}
    2.43-	}
    2.44-}
    2.45-
    2.46 void
    2.47 machinit(void)
    2.48 {
     3.1--- a/sys/src/9/pc64/mmu.c
     3.2+++ b/sys/src/9/pc64/mmu.c
     3.3@@ -271,7 +271,11 @@ mmuwalk(uintptr* table, uintptr va, int 
     3.4 		if(pte & PTEVALID){
     3.5 			if(pte & PTESIZE)
     3.6 				return 0;
     3.7-			table = KADDR(PPN(pte));
     3.8+			pte = PPN(pte);
     3.9+			if(pte >= (uintptr)-KZERO)
    3.10+				table = (void*)(pte + VMAP);
    3.11+			else
    3.12+				table = (void*)(pte + KZERO);
    3.13 		} else {
    3.14 			if(!create)
    3.15 				return 0;
    3.16@@ -570,3 +574,62 @@ patwc(void *a, int n)
    3.17 		*pte = (*pte & ~mask) | (attr & mask);
    3.18 	}
    3.19 }
    3.20+
    3.21+/*
    3.22+ * The palloc.pages array and mmupool can be a large chunk
    3.23+ * out of the 2GB window above KZERO, so we allocate from
    3.24+ * upages and map in the VMAP window before pageinit()
    3.25+ */
    3.26+void
    3.27+preallocpages(void)
    3.28+{
    3.29+	Pallocmem *pm;
    3.30+	uintptr va, base, top;
    3.31+	vlong tsize, psize;
    3.32+	ulong np, nt;
    3.33+	int i;
    3.34+
    3.35+	np = 0;
    3.36+	for(i=0; i<nelem(palloc.mem); i++){
    3.37+		pm = &palloc.mem[i];
    3.38+		np += pm->npage;
    3.39+	}
    3.40+	nt = np / 50;	/* 2% for mmupool */
    3.41+	np -= nt;
    3.42+
    3.43+	nt = (uvlong)nt*BY2PG / (sizeof(MMU)+PTSZ);
    3.44+	tsize = (uvlong)nt * (sizeof(MMU)+PTSZ);
    3.45+
    3.46+	psize = (uvlong)np * BY2PG;
    3.47+	psize += sizeof(Page) + BY2PG;
    3.48+	psize = (psize / (sizeof(Page)+BY2PG)) * sizeof(Page);
    3.49+
    3.50+	psize += tsize;
    3.51+	psize = ROUND(psize, PGLSZ(1));
    3.52+
    3.53+	for(i=0; i<nelem(palloc.mem); i++){
    3.54+		pm = &palloc.mem[i];
    3.55+		base = ROUND(pm->base, PGLSZ(1));
    3.56+		top = pm->base + (uvlong)pm->npage * BY2PG;
    3.57+		if((base + psize) <= VMAPSIZE && (vlong)(top - base) >= psize){
    3.58+			pm->base = base + psize;
    3.59+			pm->npage = (top - pm->base)/BY2PG;
    3.60+
    3.61+			va = base + VMAP;
    3.62+			pmap(m->pml4, base | PTEGLOBAL|PTEWRITE|PTEVALID, va, psize);
    3.63+
    3.64+			palloc.pages = (void*)(va + tsize);
    3.65+
    3.66+			mmupool.nfree = mmupool.nalloc = nt;
    3.67+			mmupool.free = (void*)(va + (uvlong)nt*PTSZ);
    3.68+			for(i=0; i<nt; i++){
    3.69+				mmupool.free[i].page = (uintptr*)va;
    3.70+				mmupool.free[i].next = &mmupool.free[i+1];
    3.71+				va += PTSZ;
    3.72+			}
    3.73+			mmupool.free[i-1].next = nil;
    3.74+
    3.75+			break;
    3.76+		}
    3.77+	}
    3.78+}