Subject: Multiple free list support in UVM
To: None <tech-kern@NetBSD.ORG>
From: Jason Thorpe <thorpej@nas.nasa.gov>
List: tech-kern
Date: 06/27/1998 11:42:12
[ I've brought this subject up before in private communication with some
  folks, but some work I'm doing in the arm32 port actually necessitates
  these changes somewhat, so I'm bringing it up again, in public. ]

Hi folks...

What follows is a proposal for multiple page free list support in UVM.

Motivation: There are several reasons why one might want to prioritize
pools of memory for allocation.  For example, on the Amiga and MVME-147,
there are two classes of memory, one of which is significantly slower than
the other.  You would want the slower memory to take a back seat to the
faster memory when handling page faults, etc.  Or, take the PC platform.
ISA can only DMA to the first 16M of RAM.  It would be nice to be able
to specify a preference for where the memory comes from when handling
faults for mapped files with PROT_WRITE or for the buffer cache, and
otherwise have that memory take a back seat.  My motivation is the fact
that the Shark only has a 4M range for ISA DMA, and I want that memory
left alone unless it's either explcitly asked for or is the only memory
left on the system.

Implementation: Very simple.  Machine-dependent code specifies how many
free lists are on the system w/ VM_NFREELIST, and provides at least one
symbol VM_FREELIST_DEFAULT (although it is currently not used by MI
code).  The vm_page_t has a "free_list" member now, which specifies which
free list the page is supposed to be placed on (sigh, growing the
vm_page_t)[*].  A new function, uvm_pagealloc_strat() is provided for
allocating pages (uvm_pagealloc() is defined in terms of this function
for normal use).  Three strategies are provided:

	UVM_PGA_STRAT_NORMAL	normal use - walk free lists in descending
				priority, take first free page

	UVM_PGA_STRAT_ONLY	only allocate a page from the specified
				free list

	UVM_PGA_STRAT_FALLBACK	try the specified free list first, but
				fall back on NORMAL if that fails

uvm_page_physload() has also been given an additional argument to specify
which free list those pages to be added to.

[*] One could use the vm_physseg[] array to filter the pages into
the appropriate free list when they're freed, and this should be
used in lieu of the free_list member in the vm_page_t if it doesn't
have a noticeable performance impact.

The diffs below implement this, and I have changed the i386 and alpha
ports to use the new interface.  The i386 gains an additional "first 16M"
free list, and the alpha remains unchanged.

Thoughts?

Jason R. Thorpe                                       thorpej@nas.nasa.gov
NASA Ames Research Center                            Home: +1 408 866 1912
NAS: M/S 258-5                                       Work: +1 650 604 0935
Moffett Field, CA 94035                             Pager: +1 650 428 6939

Index: uvm/uvm.h
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm.h,v
retrieving revision 1.8
diff -c -r1.8 uvm.h
*** uvm.h	1998/05/20 01:32:29	1.8
--- uvm.h	1998/06/27 18:25:42
***************
*** 67,72 ****
--- 67,77 ----
  #include <uvm/uvm_swap.h>
  
  /*
+  * pull in VM_NFREELIST
+  */
+ #include <machine/vmparam.h>
+ 
+ /*
   * uvm structure (vm global state: collected in one structure for ease
   * of reference...)
   */
***************
*** 74,80 ****
  struct uvm {
  	/* vm_page related parameters */
  		/* vm_page queues */
! 	struct pglist page_free;	/* unallocated pages */
  	struct pglist page_active;	/* allocated pages, in use */
  	struct pglist page_inactive_swp;/* pages inactive (reclaim or free) */
  	struct pglist page_inactive_obj;/* pages inactive (reclaim or free) */
--- 79,85 ----
  struct uvm {
  	/* vm_page related parameters */
  		/* vm_page queues */
! 	struct pglist page_free[VM_NFREELIST];	/* unallocated pages */
  	struct pglist page_active;	/* allocated pages, in use */
  	struct pglist page_inactive_swp;/* pages inactive (reclaim or free) */
  	struct pglist page_inactive_obj;/* pages inactive (reclaim or free) */
Index: uvm/uvm_extern.h
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_extern.h,v
retrieving revision 1.13
diff -c -r1.13 uvm_extern.h
*** uvm_extern.h	1998/05/09 15:04:40	1.13
--- uvm_extern.h	1998/06/27 18:25:42
***************
*** 128,133 ****
--- 128,140 ----
  #define UVM_KMF_TRYLOCK	UVM_FLAG_TRYLOCK	/* try locking only */
  
  /*
+  * the following defines the strategies for uvm_pagealloc_strat()
+  */
+ #define	UVM_PGA_STRAT_NORMAL	0	/* high -> low free list walk */
+ #define	UVM_PGA_STRAT_ONLY	1	/* only specified free list */
+ #define	UVM_PGA_STRAT_FALLBACK	2	/* ONLY falls back on NORMAL */
+ 
+ /*
   * structures
   */
  
***************
*** 341,352 ****
  				caddr_t, vm_offset_t));
  
  /* uvm_page.c */
! struct vm_page		*uvm_pagealloc __P((struct uvm_object *, vm_offset_t,
! 					    struct vm_anon *));
  void			uvm_pagerealloc __P((struct vm_page *, 
  					     struct uvm_object *, vm_offset_t));
  void			uvm_page_physload __P((vm_offset_t, vm_offset_t,
! 					       vm_offset_t, vm_offset_t));
  void			uvm_setpagesize __P((void));
  
  /* uvm_pdaemon.c */
--- 348,361 ----
  				caddr_t, vm_offset_t));
  
  /* uvm_page.c */
! struct vm_page		*uvm_pagealloc_strat __P((struct uvm_object *,
! 				vm_offset_t, struct vm_anon *, int, int));
! #define	uvm_pagealloc(obj, off, anon) \
! 	    uvm_pagealloc_strat((obj), (off), (anon), UVM_PGA_STRAT_NORMAL, 0)
  void			uvm_pagerealloc __P((struct vm_page *, 
  					     struct uvm_object *, vm_offset_t));
  void			uvm_page_physload __P((vm_offset_t, vm_offset_t,
! 					       vm_offset_t, vm_offset_t, int));
  void			uvm_setpagesize __P((void));
  
  /* uvm_pdaemon.c */
Index: uvm/uvm_map.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_map.c,v
retrieving revision 1.20
diff -c -r1.20 uvm_map.c
*** uvm_map.c	1998/05/22 02:01:54	1.20
--- uvm_map.c	1998/06/27 18:25:43
***************
*** 3251,3257 ****
  
  	/* cross-verify page queue */
  	if (pg->pqflags & PQ_FREE)
! 		pgl = &uvm.page_free;
  	else if (pg->pqflags & PQ_INACTIVE)
  		pgl = (pg->pqflags & PQ_SWAPBACKED) ? 
  		    &uvm.page_inactive_swp : &uvm.page_inactive_obj;
--- 3251,3257 ----
  
  	/* cross-verify page queue */
  	if (pg->pqflags & PQ_FREE)
! 		pgl = &uvm.page_free[pg->free_list];
  	else if (pg->pqflags & PQ_INACTIVE)
  		pgl = (pg->pqflags & PQ_SWAPBACKED) ? 
  		    &uvm.page_inactive_swp : &uvm.page_inactive_obj;
Index: uvm/uvm_page.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_page.c,v
retrieving revision 1.11
diff -c -r1.11 uvm_page.c
*** uvm_page.c	1998/05/28 15:31:31	1.11
--- uvm_page.c	1998/06/27 18:25:44
***************
*** 224,230 ****
  	 * step 1: init the page queues and page queue locks
  	 */
  
! 	TAILQ_INIT(&uvm.page_free);
  	TAILQ_INIT(&uvm.page_active);
  	TAILQ_INIT(&uvm.page_inactive_swp);
  	TAILQ_INIT(&uvm.page_inactive_obj);
--- 224,231 ----
  	 * step 1: init the page queues and page queue locks
  	 */
  
! 	for (lcv = 0; lcv < VM_NFREELIST; lcv++)
! 	  TAILQ_INIT(&uvm.page_free[lcv]);
  	TAILQ_INIT(&uvm.page_active);
  	TAILQ_INIT(&uvm.page_inactive_swp);
  	TAILQ_INIT(&uvm.page_inactive_obj);
***************
*** 309,314 ****
--- 310,317 ----
  		paddr = ptoa(vm_physmem[lcv].start);
  		for (i = 0 ; i < n ; i++, paddr += PAGE_SIZE) {
  			vm_physmem[lcv].pgs[i].phys_addr = paddr;
+ 			vm_physmem[lcv].pgs[i].free_list =
+ 			    vm_physmem[lcv].free_list;
  			if (atop(paddr) >= vm_physmem[lcv].avail_start &&
  			    atop(paddr) <= vm_physmem[lcv].avail_end) {
  				uvmexp.npages++;
***************
*** 548,555 ****
   */
  
  void
! uvm_page_physload(start, end, avail_start, avail_end)
  	vm_offset_t start, end, avail_start, avail_end;
  {
  	int preload, lcv, npages;
  	struct vm_page *pgs;
--- 551,559 ----
   */
  
  void
! uvm_page_physload(start, end, avail_start, avail_end, free_list)
  	vm_offset_t start, end, avail_start, avail_end;
+ 	int free_list;
  {
  	int preload, lcv, npages;
  	struct vm_page *pgs;
***************
*** 597,607 ****
  			printf("\tignoring 0x%lx -> 0x%lx\n", start, end);
  			return;
  		}
! 		/* zero data, init phys_addr, and free pages */
  		bzero(pgs, sizeof(struct vm_page) * npages);
  		for (lcv = 0, paddr = ptoa(start) ;
  				 lcv < npages ; lcv++, paddr += PAGE_SIZE) {
  			pgs[lcv].phys_addr = paddr;
  			if (atop(paddr) >= avail_start &&
  			    atop(paddr) <= avail_end)
  				uvm_pagefree(&pgs[lcv]);
--- 601,612 ----
  			printf("\tignoring 0x%lx -> 0x%lx\n", start, end);
  			return;
  		}
! 		/* zero data, init phys_addr and free_list, and free pages */
  		bzero(pgs, sizeof(struct vm_page) * npages);
  		for (lcv = 0, paddr = ptoa(start) ;
  				 lcv < npages ; lcv++, paddr += PAGE_SIZE) {
  			pgs[lcv].phys_addr = paddr;
+ 			pgs[lcv].free_list = free_list;
  			if (atop(paddr) >= avail_start &&
  			    atop(paddr) <= avail_end)
  				uvm_pagefree(&pgs[lcv]);
***************
*** 673,678 ****
--- 678,684 ----
  		ps->pgs = pgs;
  		ps->lastpg = pgs + npages - 1;
  	}
+ 	ps->free_list = free_list;
  	vm_nphysseg++;
  
  	/*
***************
*** 794,800 ****
  #endif
  
  /*
!  * uvm_pagealloc: allocate vm_page.   
   *
   * => return null if no pages free
   * => wake up pagedaemon if number of free pages drops below low water mark
--- 800,806 ----
  #endif
  
  /*
!  * uvm_pagealloc_strat: allocate vm_page from a particular free list.
   *
   * => return null if no pages free
   * => wake up pagedaemon if number of free pages drops below low water mark
***************
*** 802,817 ****
   * => if anon != NULL, anon must be locked (to put in anon)
   * => only one of obj or anon can be non-null
   * => caller must activate/deactivate page if it is not wired.
   */
  
  struct vm_page *
! uvm_pagealloc(obj, off, anon)
  	struct uvm_object *obj;
  	vm_offset_t off;
  	struct vm_anon *anon;
  {
! 	int s;
  	struct vm_page *pg;
  
  #ifdef DIAGNOSTIC
  	/* sanity check */
--- 808,826 ----
   * => if anon != NULL, anon must be locked (to put in anon)
   * => only one of obj or anon can be non-null
   * => caller must activate/deactivate page if it is not wired.
+  * => free_list is ignored if strat == UVM_PGA_STRAT_NORMAL.
   */
  
  struct vm_page *
! uvm_pagealloc_strat(obj, off, anon, strat, free_list)
  	struct uvm_object *obj;
  	vm_offset_t off;
  	struct vm_anon *anon;
+ 	int strat, free_list;
  {
! 	int lcv, s;
  	struct vm_page *pg;
+ 	struct pglist *freeq;
  
  #ifdef DIAGNOSTIC
  	/* sanity check */
***************
*** 841,858 ****
  	 *        the requestor isn't the pagedaemon.
  	 */
  
! 	pg = uvm.page_free.tqh_first;
! 	if (pg == NULL || 
! 	    (uvmexp.free <= uvmexp.reserve_kernel &&
  	     !(obj && obj->uo_refs == UVM_OBJ_KERN)) ||
  	    (uvmexp.free <= uvmexp.reserve_pagedaemon &&
! 	     !(obj == uvmexp.kmem_object && curproc == uvm.pagedaemon_proc))) {
! 		uvm_unlock_fpageq();
! 		splx(s);
! 		return(NULL);
  	}
  
! 	TAILQ_REMOVE(&uvm.page_free, pg, pageq);
  	uvmexp.free--;
  
  	uvm_unlock_fpageq();		/* unlock free page queue */
--- 850,902 ----
  	 *        the requestor isn't the pagedaemon.
  	 */
  
! 	if ((uvmexp.free <= uvmexp.reserve_kernel &&
  	     !(obj && obj->uo_refs == UVM_OBJ_KERN)) ||
  	    (uvmexp.free <= uvmexp.reserve_pagedaemon &&
! 	     !(obj == uvmexp.kmem_object && curproc == uvm.pagedaemon_proc)))
! 		goto fail;
! 
!  again:
! 	switch (strat) {
! 	case UVM_PGA_STRAT_NORMAL:
! 		/* Check all freelists in descending priority order. */
! 		for (lcv = 0; lcv < VM_NFREELIST; lcv++) {
! 			freeq = &uvm.page_free[lcv];
! 			if ((pg = freeq->tqh_first) != NULL)
! 				goto gotit;
! 		}
! 
! 		/* No pages free! */
! 		goto fail;
! 
! 	case UVM_PGA_STRAT_ONLY:
! 	case UVM_PGA_STRAT_FALLBACK:
! 		/* Attempt to allocate from the specified free list. */
! #ifdef DIAGNOSTIC
! 		if (free_list >= VM_NFREELIST || free_list < 0)
! 			panic("uvm_pagealloc_strat: bad free list %d",
! 			    free_list);
! #endif
! 		freeq = &uvm.page_free[free_list];
! 		if ((pg = freeq->tqh_first) != NULL)
! 			goto gotit;
! 
! 		/* Fall back, if possible. */
! 		if (strat == UVM_PGA_STRAT_FALLBACK) {
! 			strat = UVM_PGA_STRAT_NORMAL;
! 			goto again;
! 		}
! 
! 		/* No pages free! */
! 		goto fail;
! 
! 	default:
! 		panic("uvm_pagealloc_strat: bad strat %d", strat);
! 		/* NOTREACHED */
  	}
  
!  gotit:
! 	TAILQ_REMOVE(freeq, pg, pageq);
  	uvmexp.free--;
  
  	uvm_unlock_fpageq();		/* unlock free page queue */
***************
*** 879,884 ****
--- 923,933 ----
  	UVM_PAGE_OWN(pg, "new alloc");
  
  	return(pg);
+ 
+  fail:
+ 	uvm_unlock_fpageq();
+ 	splx(s);
+ 	return (NULL);
  }
  
  /*
***************
*** 1021,1027 ****
  
  	s = splimp();
  	uvm_lock_fpageq();
! 	TAILQ_INSERT_TAIL(&uvm.page_free, pg, pageq);
  	pg->pqflags = PQ_FREE;
  #ifdef DEBUG
  	pg->uobject = (void *)0xdeadbeef;
--- 1070,1076 ----
  
  	s = splimp();
  	uvm_lock_fpageq();
! 	TAILQ_INSERT_TAIL(&uvm.page_free[pg->free_list], pg, pageq);
  	pg->pqflags = PQ_FREE;
  #ifdef DEBUG
  	pg->uobject = (void *)0xdeadbeef;
Index: uvm/uvm_pglist.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_pglist.c,v
retrieving revision 1.4
diff -c -r1.4 uvm_pglist.c
*** uvm_pglist.c	1998/05/05 20:51:07	1.4
--- uvm_pglist.c	1998/06/27 18:25:44
***************
*** 140,146 ****
  	uvm_lock_fpageq();            /* lock free page queue */
  
  	/* Are there even any free pages? */
! 	if (uvm.page_free.tqh_first == NULL)
  		goto out;
  
  	for (;; try += alignment) {
--- 140,149 ----
  	uvm_lock_fpageq();            /* lock free page queue */
  
  	/* Are there even any free pages? */
! 	for (idx = 0; idx < VM_NFREELIST; idx++)
! 		if (uvm.page_free[idx].tqh_first != NULL)
! 			break;
! 	if (idx == VM_NFREELIST)
  		goto out;
  
  	for (;; try += alignment) {
***************
*** 211,217 ****
  	while (idx < end) {
  		m = &pgs[idx];
  #ifdef DEBUG
! 		for (tp = uvm.page_free.tqh_first; tp != NULL;
  		    tp = tp->pageq.tqe_next) {
  			if (tp == m)
  				break;
--- 214,220 ----
  	while (idx < end) {
  		m = &pgs[idx];
  #ifdef DEBUG
! 		for (tp = uvm.page_free[m->free_list].tqh_first; tp != NULL;
  		    tp = tp->pageq.tqe_next) {
  			if (tp == m)
  				break;
***************
*** 219,225 ****
  		if (tp == NULL)
  			panic("uvm_pglistalloc: page not on freelist");
  #endif
! 		TAILQ_REMOVE(&uvm.page_free, m, pageq);
  		uvmexp.free--;
  		m->flags = PG_CLEAN;
  		m->pqflags = 0;
--- 222,228 ----
  		if (tp == NULL)
  			panic("uvm_pglistalloc: page not on freelist");
  #endif
! 		TAILQ_REMOVE(&uvm.page_free[m->free_list], m, pageq);
  		uvmexp.free--;
  		m->flags = PG_CLEAN;
  		m->pqflags = 0;
***************
*** 277,283 ****
  #endif
  		TAILQ_REMOVE(list, m, pageq);
  		m->pqflags = PQ_FREE;
! 		TAILQ_INSERT_TAIL(&uvm.page_free, m, pageq);
  		uvmexp.free++;
  		STAT_DECR(uvm_pglistalloc_npages);
  	}
--- 280,286 ----
  #endif
  		TAILQ_REMOVE(list, m, pageq);
  		m->pqflags = PQ_FREE;
! 		TAILQ_INSERT_TAIL(&uvm.page_free[m->free_list], m, pageq);
  		uvmexp.free++;
  		STAT_DECR(uvm_pglistalloc_npages);
  	}
Index: vm/vm_page.h
===================================================================
RCS file: /cvsroot/src/sys/vm/vm_page.h,v
retrieving revision 1.26
diff -c -r1.26 vm_page.h
*** vm_page.h	1998/03/12 06:25:53	1.26
--- vm_page.h	1998/06/27 18:25:44
***************
*** 139,144 ****
--- 139,145 ----
    u_int			loan_count;	/* number of active loans
  					 * to read: [O or P]
  					 * to modify: [O _and_ P] */
+   int			free_list;	/* which freelist are we on? */
  #else
    u_short		wire_count;	/* wired down maps refs (P) */
    u_short		flags;		/* see below */
***************
*** 243,248 ****
--- 244,252 ----
  	vm_offset_t end;		/* (PF# of last page in segment) + 1 */
  	vm_offset_t avail_start;	/* PF# of first free page in segment */
  	vm_offset_t avail_end;		/* (PF# of last free page in segment) +1  */
+ #if defined(UVM)
+ 	int	free_list;		/* which free list they belong on */
+ #endif
  	struct	vm_page *pgs;		/* vm_page structures (from start) */
  	struct	vm_page *lastpg;	/* vm_page structure for end */
  	struct	pmap_physseg pmseg;	/* pmap specific (MD) data */
Index: arch/i386/i386/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.308
diff -c -r1.308 machdep.c
*** machdep.c	1998/06/09 01:57:43	1.308
--- machdep.c	1998/06/27 18:30:16
***************
*** 579,585 ****
  		curbufsize = CLBYTES * ((i < residual) ? (base+1) : base);
  
  		while (curbufsize) {
! 			pg = uvm_pagealloc(NULL, 0, NULL);
  			if (pg == NULL)
  				panic("cpu_startup: not enough memory for "
  				    "buffer cache");
--- 579,591 ----
  		curbufsize = CLBYTES * ((i < residual) ? (base+1) : base);
  
  		while (curbufsize) {
! 			/*
! 			 * Attempt to allocate buffers from the first
! 			 * 16M of RAM to avoid bouncing file system
! 			 * transfers.
! 			 */
! 			pg = uvm_pagealloc_strat(NULL, 0, NULL,
! 			    UVM_PGA_STRAT_FALLBACK, VM_FREELIST_FIRST16);
  			if (pg == NULL)
  				panic("cpu_startup: not enough memory for "
  				    "buffer cache");
Index: arch/i386/i386/pmap.new.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/pmap.new.c,v
retrieving revision 1.13
diff -c -r1.13 pmap.new.c
*** pmap.new.c	1998/06/09 05:20:11	1.13
--- pmap.new.c	1998/06/27 18:30:17
***************
*** 734,739 ****
--- 734,740 ----
    struct pmap *kpm;
    vm_offset_t kva;
    pt_entry_t *pte;
+   int first16q;
  
    /*
     * set the page size (default value is 4K which is ok)
***************
*** 887,901 ****
     * we must call uvm_page_physload() after we are done playing with
     * virtual_avail but before we call pmap_steal_memory.  [i.e. here]
     * this call tells the VM system how much physical memory it
!    * controls.
     */
  
    if (avail_start < hole_start)   /* any free memory before the hole? */
      uvm_page_physload(atop(avail_start), atop(hole_start),
! 		      atop(avail_start), atop(hole_start));
  
!   uvm_page_physload(atop(hole_end), atop(avail_end), 
! 		    atop(hole_end), atop(avail_end));
    
    /*
     * ensure the TLB is sync'd with reality by flushing it...
--- 888,918 ----
     * we must call uvm_page_physload() after we are done playing with
     * virtual_avail but before we call pmap_steal_memory.  [i.e. here]
     * this call tells the VM system how much physical memory it
!    * controls.  If we have 16M of RAM or less, just put it all on
!    * the default free list.  Otherwise, put the first 16M of RAM
!    * on a lower priority free list (so that all of the ISA DMA'able
!    * memory won't be eaten up first-off).
     */
  
+   if (avail_end <= (16 * 1024 * 1024))
+     first16q = VM_FREELIST_DEFAULT;
+   else
+     first16q = VM_FREELIST_FIRST16;
+ 
    if (avail_start < hole_start)   /* any free memory before the hole? */
      uvm_page_physload(atop(avail_start), atop(hole_start),
! 		      atop(avail_start), atop(hole_start), first16q);
  
!   if (first16q == VM_FREELIST_FIRST16) {
!     uvm_page_physload(atop(hole_end), atop(16 * 1024 * 1024),
! 		      atop(hole_end), atop(16 * 1024 * 1024), first16q);
!     uvm_page_physload(atop(16 * 1024 * 1024), atop(avail_end),
! 		      atop(16 * 1024 * 1024), atop(avail_end),
! 		      VM_FREELIST_DEFAULT);
!   } else {
!     uvm_page_physload(atop(hole_end), atop(avail_end), 
! 		      atop(hole_end), atop(avail_end), first16q);
!   }
    
    /*
     * ensure the TLB is sync'd with reality by flushing it...
Index: arch/i386/include/vmparam.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/include/vmparam.h,v
retrieving revision 1.27
diff -c -r1.27 vmparam.h
*** vmparam.h	1998/05/04 06:09:35	1.27
--- vmparam.h	1998/06/27 18:30:21
***************
*** 153,161 ****
  
  #define	MACHINE_NEW_NONCONTIG	/* VM <=> pmap interface modifier */
  
! #define VM_PHYSSEG_MAX		2	/* we only have one "hole" */
  #define VM_PHYSSEG_STRAT	VM_PSTRAT_BIGFIRST
  #define VM_PHYSSEG_NOADD		/* can't add RAM after vm_mem_init */
  
  /*
   * pmap specific data stored in the vm_physmem[] array
--- 153,165 ----
  
  #define	MACHINE_NEW_NONCONTIG	/* VM <=> pmap interface modifier */
  
! #define VM_PHYSSEG_MAX		3	/* 1 "hole" + 2 free lists */
  #define VM_PHYSSEG_STRAT	VM_PSTRAT_BIGFIRST
  #define VM_PHYSSEG_NOADD		/* can't add RAM after vm_mem_init */
+ 
+ #define	VM_NFREELIST		2
+ #define	VM_FREELIST_DEFAULT	0
+ #define	VM_FREELIST_FIRST16	1
  
  /*
   * pmap specific data stored in the vm_physmem[] array
Index: arch/alpha/alpha/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/alpha/machdep.c,v
retrieving revision 1.127
diff -c -r1.127 machdep.c
*** machdep.c	1998/06/26 00:01:32	1.127
--- machdep.c	1998/06/27 18:34:55
***************
*** 586,592 ****
  #endif
  #if defined(UVM)
  				uvm_page_physload(pfn0, kernstartpfn,
! 				    pfn0, kernstartpfn);
  #else
  				vm_page_physload(pfn0, kernstartpfn,
  				    pfn0, kernstartpfn);
--- 586,592 ----
  #endif
  #if defined(UVM)
  				uvm_page_physload(pfn0, kernstartpfn,
! 				    pfn0, kernstartpfn, VM_FREELIST_DEFAULT);
  #else
  				vm_page_physload(pfn0, kernstartpfn,
  				    pfn0, kernstartpfn);
***************
*** 605,611 ****
  #endif
  #if defined(UVM)
  				uvm_page_physload(kernendpfn, pfn1,
! 				    kernendpfn, pfn1);
  #else
  				vm_page_physload(kernendpfn, pfn1,
  				    kernendpfn, pfn1);
--- 605,611 ----
  #endif
  #if defined(UVM)
  				uvm_page_physload(kernendpfn, pfn1,
! 				    kernendpfn, pfn1, VM_FREELIST_DEFAULT);
  #else
  				vm_page_physload(kernendpfn, pfn1,
  				    kernendpfn, pfn1);
***************
*** 620,626 ****
  			    pfn0, pfn1);
  #endif
  #if defined(UVM)
! 			uvm_page_physload(pfn0, pfn1, pfn0, pfn1);
  #else
  			vm_page_physload(pfn0, pfn1, pfn0, pfn1);
  #endif
--- 620,627 ----
  			    pfn0, pfn1);
  #endif
  #if defined(UVM)
! 			uvm_page_physload(pfn0, pfn1, pfn0, pfn1,
! 			    VM_FREELIST_DEFAULT);
  #else
  			vm_page_physload(pfn0, pfn1, pfn0, pfn1);
  #endif
Index: arch/alpha/include/vmparam.h
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/include/vmparam.h,v
retrieving revision 1.10
diff -c -r1.10 vmparam.h
*** vmparam.h	1998/03/12 01:25:52	1.10
--- vmparam.h	1998/06/27 18:34:58
***************
*** 169,174 ****
--- 169,177 ----
  #define	VM_PHYSSEG_STRAT	VM_PSTRAT_BSEARCH
  #define	VM_PHYSSEG_NOADD			/* no more after vm_mem_init */
  
+ #define	VM_NFREELIST		1
+ #define	VM_FREELIST_DEFAULT	0
+ 
  /*
   * pmap-specific data stored in the vm_physmem[] array.
   */