code: plan9front

Download patch

ref: 295acd7e0d711cfd2c7c6a1bd45d00c9727f5786
parent: c77b3ba143da491f020a1c2871a57d10d5b8bf8f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Apr 2 14:23:25 EDT 2021

kernel: get rid of physical page bank array and use conf.mem[] instead

We can take advantage of the fact that xinit() allocates
kernel memory from conf.mem[] banks always at the beginning
of a bank, so the separate palloc.mem[] array can be eleminated
as we can calculate the amount of non-kernel memory like:

upages = cm->npage - (PGROUND(cm->klimit - cm->kbase)/BY2PG)

for the number of reserved kernel pages,
we provide the new function: ulong nkpages(Confmem*)

This eleminates the error case of running out of slots in
the array and avoids wasting memory in ports that have simple
memory configurations (compared to pc/pc64).

--- a/sys/src/9/pc64/mmu.c
+++ b/sys/src/9/pc64/mmu.c
@@ -652,7 +652,7 @@
 void
 preallocpages(void)
 {
-	Pallocmem *pm;
+	Confmem *cm;
 	uintptr va, base, top;
 	vlong tsize, psize;
 	ulong np, nt;
@@ -659,9 +659,9 @@
 	int i;
 
 	np = 0;
-	for(i=0; i<nelem(palloc.mem); i++){
-		pm = &palloc.mem[i];
-		np += pm->npage;
+	for(i=0; i<nelem(conf.mem); i++){
+		cm = &conf.mem[i];
+		np += cm->npage - nkpages(cm);
 	}
 	nt = np / 50;	/* 2% for mmupool */
 	np -= nt;
@@ -676,16 +676,19 @@
 	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;
+	for(i=0; i<nelem(conf.mem); i++){
+		cm = &conf.mem[i];
+		base = cm->base;
+		top = base + (uvlong)cm->npage * BY2PG;
+		base += (uvlong)nkpages(cm) * BY2PG;
+		top &= -PGLSZ(1);
+		if(top <= VMAPSIZE && (vlong)(top - base) >= psize){
+			/* steal memory from the end of the bank */
+			top -= psize;
+			cm->npage = (top - cm->base) / BY2PG;
 
-			va = base + VMAP;
-			pmap(base | PTEGLOBAL|PTEWRITE|PTENOEXEC|PTEVALID, va, psize);
+			va = top + VMAP;
+			pmap(top | PTEGLOBAL|PTEWRITE|PTENOEXEC|PTEVALID, va, psize);
 
 			palloc.pages = (void*)(va + tsize);
 
--- a/sys/src/9/port/page.c
+++ b/sys/src/9/port/page.c
@@ -7,12 +7,18 @@
 
 Palloc palloc;
 
+ulong
+nkpages(Confmem *cm)
+{
+	return ((cm->klimit - cm->kbase) + BY2PG-1) / BY2PG;
+}
+
 void
 pageinit(void)
 {
 	int color, i, j;
 	Page *p, **t;
-	Pallocmem *pm;
+	Confmem *cm;
 	vlong m, v, u;
 
 	if(palloc.pages == nil){
@@ -19,9 +25,9 @@
 		ulong np;
 
 		np = 0;
-		for(i=0; i<nelem(palloc.mem); i++){
-			pm = &palloc.mem[i];
-			np += pm->npage;
+		for(i=0; i<nelem(conf.mem); i++){
+			cm = &conf.mem[i];
+			np += cm->npage - nkpages(cm);
 		}
 		palloc.pages = xalloc(np*sizeof(Page));
 		if(palloc.pages == nil)
@@ -35,11 +41,11 @@
 	t = &palloc.head;
 	p = palloc.pages;
 
-	for(i=0; i<nelem(palloc.mem); i++){
-		pm = &palloc.mem[i];
-		for(j=0; j<pm->npage; j++){
+	for(i=0; i<nelem(conf.mem); i++){
+		cm = &conf.mem[i];
+		for(j=nkpages(cm); j<cm->npage; j++){
 			memset(p, 0, sizeof *p);
-			p->pa = pm->base+j*BY2PG;
+			p->pa = cm->base+j*BY2PG;
 			if(cankaddr(p->pa) && (KADDR(p->pa) == nil || KADDR(p->pa) == (void*)-BY2PG))
 				continue;
 			p->color = color;
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -25,7 +25,6 @@
 typedef struct Page	Page;
 typedef struct Path	Path;
 typedef struct Palloc	Palloc;
-typedef struct Pallocmem	Pallocmem;
 typedef struct Perf	Perf;
 typedef struct PhysUart	PhysUart;
 typedef struct Pgrp	Pgrp;
@@ -519,12 +518,6 @@
 	DELTAFD	= 20		/* incremental increase in Fgrp.fd's */
 };
 
-struct Pallocmem
-{
-	uintptr	base;
-	ulong	npage;
-};
-
 struct Palloc
 {
 	Lock;
@@ -533,7 +526,6 @@
 	Page	*pages;			/* array of all pages */
 	ulong	user;			/* how many user pages */
 	Rendezq		pwait[2];	/* Queues of procs waiting for memory */
-	Pallocmem	mem[16];	/* physical user page banks */
 };
 
 struct Waitq
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -213,6 +213,7 @@
 Proc*		newproc(void);
 void		nexterror(void);
 int		notify(Ureg*);
+ulong		nkpages(Confmem*);
 uvlong		ns2fastticks(uvlong);
 int		okaddr(uintptr, ulong, int);
 int		openmode(ulong);
--- a/sys/src/9/port/xalloc.c
+++ b/sys/src/9/port/xalloc.c
@@ -43,10 +43,8 @@
 xinit(void)
 {
 	ulong maxpages, kpages, n;
-	uintptr size;
-	Confmem *m;
-	Pallocmem *pm;
 	Hole *h, *eh;
+	Confmem *cm;
 	int i;
 
 	eh = &xlists.hole[Nhole-1];
@@ -57,36 +55,28 @@
 
 	kpages = conf.npage - conf.upages;
 
-	pm = palloc.mem;
 	for(i=0; i<nelem(conf.mem); i++){
-		m = &conf.mem[i];
-		n = m->npage;
+		cm = &conf.mem[i];
+		n = cm->npage;
 		if(n > kpages)
 			n = kpages;
 		/* don't try to use non-KADDR-able memory for kernel */
-		maxpages = cankaddr(m->base)/BY2PG;
+		maxpages = cankaddr(cm->base)/BY2PG;
 		if(n > maxpages)
 			n = maxpages;
-		size = (uintptr)n*BY2PG;
-		/* first give to kernel */
+		/* give to kernel */
 		if(n > 0){
-			m->kbase = (uintptr)KADDR(m->base);
-			m->klimit = (uintptr)m->kbase+size;
-			if(m->klimit == 0)
-				m->klimit = (uintptr)-BY2PG;
-			xhole(m->base, m->klimit - m->kbase);
+			cm->kbase = (uintptr)KADDR(cm->base);
+			cm->klimit = (uintptr)cm->kbase+(uintptr)n*BY2PG;
+			if(cm->klimit == 0)
+				cm->klimit = (uintptr)-BY2PG;
+			xhole(cm->base, cm->klimit - cm->kbase);
 			kpages -= n;
 		}
-		/* if anything left over, give to user */
-		if(n < m->npage){
-			if(pm >= palloc.mem+nelem(palloc.mem)){
-				print("xinit: losing %lud pages\n", m->npage-n);
-				continue;
-			}
-			pm->base = m->base+size;
-			pm->npage = m->npage - n;
-			pm++;
-		}
+		/*
+		 * anything left over: cm->npage - nkpages(cm)
+		 * will be given to user by pageinit()
+		 */
 	}
 	xsummary();
 }