Subject: m68k (and alpha?) pmap.c bug in pmap_enter_ptpage()?
To: None <port-m68k@NetBSD.ORG>
From: Michael L. Hitch <osymh@gemini.oscs.montana.edu>
List: port-alpha
Date: 09/15/1995 21:38:13
  I think there is a bug in pmap_enter_ptpage() in all the m68k ports
which use the Motorola MMU.  I suspect the same bug may also be present
in the alpha port as well (from the quick glance I took at it).  This
bug will only show up under very low memory conditions (i.e. no free
pages are currently available).

  When pmap_enter_ptpage() is called to enter a new page-table (PT)
page, it will use vm_fault() to fault in a page for a user pmap.  This
may cause some inactive pages to be freed if a free page isn't
available. If all the current PT pages in the current pmap are removed
as a result of freeing up pages, the segment table reference count for
the current pmap will go to zero, resulting in the removal of the
segment table page(s).  When pmap_enter_ptpage() continues after the
vm_fault, the segment table no longer is resident in memory, and results
in an MMU fault when trying to map the new PT page into the segment
table.

  The fix that works for me is to increment the segment table reference
count before trying to allocate the PT page.  This should ensure that
the segment table would not be removed while freeing up pages.  I
haven't seen any problems with this so far, but maybe someone else might
see something I've missed.


diff -c /usr/src/sys/arch/amiga/amiga/pmap.c ./pmap.c
*** /usr/src/sys/arch/amiga/amiga/pmap.c	Sat Aug 19 01:11:41 1995
--- ./pmap.c	Sun Sep 10 08:57:41 1995
***************
*** 2143,2148 ****
--- 2145,2155 ----
  	 * letting the VM system allocate a zero-filled page.
  	 */
  	else {
+ 		/*
+ 		 * Count the segment table reference now so that we won't
+ 		 * lose the segment table when low on memory.
+ 		 */
+ 		pmap->pm_sref++;
  #ifdef DEBUG
  		if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
  			printf("enter: about to fault UPT pg at %x\n", va);
***************
*** 2203,2209 ****
  #endif
  		*(int *)ste = (ptpa & SG_FRAME) | SG_RW | SG_V;
  	if (pmap != pmap_kernel()) {
- 		pmap->pm_sref++;
  #ifdef DEBUG
  		if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
  			printf("enter: stab %x refcnt %d\n",
--- 2210,2215 ----


Michael

-- 
Michael L. Hitch			INTERNET:  osymh@montana.edu
Computer Consultant
Office of Systems and Computing Services
Montana State University	Bozeman, MT	USA