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.
This commit is contained in:
cinap_lenrek 2019-06-28 18:12:13 +02:00
parent 6118d77858
commit b2c7a8d84a
3 changed files with 65 additions and 40 deletions

View file

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

View file

@ -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)
{

View file

@ -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;
}
}
}