Subject: bootstrap page allocation - proposed change
To: None <tech-kern@netbsd.org>
From: Matthias Drochner <M.Drochner@fz-juelich.de>
List: tech-kern
Date: 12/01/1999 00:14:27
The problem is quite i386 specific, but it points to a uvm problem.
uvm_page_physget() is used to get memory for vm page structures and
md pmap stuff. It "steals" physical pages from one of the
"vm_physmem[]" banks - the problem is that its search order does not
necesserarily match the port specific notion of how valuable pages
in the individual ranges are.
On i386, the vm_page tables are typically taken from the first 640k
because this is the smallest chunk of physical memory available. With
a large kernel, this might eat up last piece of memory below 16M,
leaving no space for ISA DMA bounce buffers.
The "free_list" attribute of the memory ranges already specifies
a preference, so it could be used to prefer "less valuable" memory
in uvm_page_physget() as well.

any problems with this?

best regards
Matthias


Index: uvm_page.c
===================================================================
RCS file: /cvsroot/syssrc/sys/uvm/uvm_page.c,v
retrieving revision 1.27
diff -u -r1.27 uvm_page.c
--- uvm_page.c	1999/11/30 18:34:23	1.27
+++ uvm_page.c	1999/11/30 22:46:29
@@ -457,9 +457,12 @@
  * => return false if out of memory.
  */
 
-boolean_t
-uvm_page_physget(paddrp)
+static boolean_t uvm_page_physget_freelist __P((paddr_t *, int));
+
+static boolean_t
+uvm_page_physget_freelist(paddrp, freelist)
 	paddr_t *paddrp;
+	int freelist;
 {
 	int lcv, x;
 
@@ -474,6 +477,9 @@
 		if (vm_physmem[lcv].pgs)
 			panic("vm_page_physget: called _after_ bootstrap");
 
+		if (vm_physmem[lcv].free_list != freelist)
+			continue;
+
 		/* try from front */
 		if (vm_physmem[lcv].avail_start == vm_physmem[lcv].start &&
 		    vm_physmem[lcv].avail_start < vm_physmem[lcv].avail_end) {
@@ -543,6 +549,18 @@
 	}
 
 	return (FALSE);        /* whoops! */
+}
+
+boolean_t
+uvm_page_physget(paddrp)
+	paddr_t *paddrp;
+{
+	int i;
+
+	for (i = 0; i < VM_NFREELIST; i++)
+		if (uvm_page_physget_freelist(paddrp, i) == TRUE)
+			return (TRUE);
+	return (FALSE);
 }
 #endif /* PMAP_STEAL_MEMORY */