Subject: pmap_do_remove and pmap_collect
To: None <port-amd64@netbsd.org>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: port-amd64
Date: 08/08/2004 18:49:12
--NextPart-20040808182752-0245000
Content-Type: Text/Plain; charset=us-ascii

hi,

the attached diff is to speed up pmap_do_remove on a large range
by skipping regions corresponding to invalid pdes.

it's only tested on i386.
can anyone test on amd64 and commit if it's worth?  thanks.

YAMAMOTO Takashi

--NextPart-20040808182752-0245000
Content-Type: Text/Plain; charset=us-ascii
Content-Disposition: attachment; filename="a.diff"

Index: arch/amd64/amd64/pmap.c
===================================================================
--- arch/amd64/amd64/pmap.c	(revision 826)
+++ arch/amd64/amd64/pmap.c	(revision 827)
@@ -567,8 +567,9 @@ static void		 pmap_tmpunmap_pa __P((void
 static void		 pmap_tmpunmap_pvepte __P((struct pv_entry *));
 static void		pmap_unmap_ptes __P((struct pmap *));
 static boolean_t	pmap_get_physpage __P((vaddr_t, int, paddr_t *));
-static boolean_t	pmap_pdes_valid __P((vaddr_t, pd_entry_t **,
-					     pd_entry_t *));
+static int		pmap_pdes_invalid(vaddr_t, pd_entry_t **, pd_entry_t *);
+#define	pmap_pdes_valid(va, pdes, lastpde)	\
+	(pmap_pdes_invalid((va), (pdes), (lastpde)) == 0)
 static void		pmap_alloc_level __P((pd_entry_t **, vaddr_t, int,
 					      long *));
 
@@ -2223,8 +2224,8 @@ pmap_deactivate(l)
  * some misc. functions
  */
 
-static boolean_t
-pmap_pdes_valid(vaddr_t va, pd_entry_t **pdes, pd_entry_t *lastpde)
+static int
+pmap_pdes_invalid(vaddr_t va, pd_entry_t **pdes, pd_entry_t *lastpde)
 {
 	int i;
 	unsigned long index;
@@ -2234,11 +2235,11 @@ pmap_pdes_valid(vaddr_t va, pd_entry_t *
 		index = pl_i(va, i);
 		pde = pdes[i - 2][index];
 		if ((pde & PG_V) == 0)
-			return FALSE;
+			return i;
 	}
 	if (lastpde != NULL)
 		*lastpde = pde;
-	return TRUE;
+	return 0;
 }
 
 /*
@@ -2255,7 +2256,7 @@ pmap_extract(pmap, va, pap)
 	pd_entry_t pde, **pdes;
 
 	pmap_map_ptes(pmap, &ptes, &pdes);
-	if (pmap_pdes_valid(va, pdes, &pde) == FALSE) {
+	if (!pmap_pdes_valid(va, pdes, &pde)) {
 		pmap_unmap_ptes(pmap);
 		return FALSE;
 	}
@@ -2700,6 +2701,7 @@ pmap_do_remove(pmap, sva, eva, flags)
 	cpumask = 0;
 
 	for (/* null */ ; sva < eva ; sva = blkendva) {
+		int lvl;
 
 		/* determine range of block */
 		blkendva = x86_round_pdr(sva+1);
@@ -2724,8 +2726,14 @@ pmap_do_remove(pmap, sva, eva, flags)
 			/* XXXCDC: ugly hack to avoid freeing PDP here */
 			continue;
 
-		if (!pmap_pdes_valid(sva, pdes, &pde))
+		lvl = pmap_pdes_invalid(sva, pdes, &pde);
+		if (lvl != 0) {
+			/*
+			 * skip a range corresponding to an invalid pde.
+			 */
+			blkendva = (sva & ptp_masks[lvl - 1]) + nbpd[lvl - 1]; 
 			continue;
+		}
 
 		/* PA of the PTP */
 		ptppa = pde & PG_FRAME;
@@ -3117,11 +3125,7 @@ void
 pmap_collect(pmap)
 	struct pmap *pmap;
 {
-	/* Because of the multiple page table levels, this will cause a system
-	 * pause lasting up to three minutes while scanning for valid PTEs.
-	 * Since it is an optional function, disable for now.
-	 */
-#if 0
+
 	/*
 	 * free all of the pt pages by removing the physical mappings
 	 * for its entire address space.
@@ -3129,7 +3133,6 @@ pmap_collect(pmap)
 
 	pmap_do_remove(pmap, VM_MIN_ADDRESS, VM_MAX_ADDRESS,
 	    PMAP_REMOVE_SKIPWIRED);
-#endif
 }
 
 /*

--NextPart-20040808182752-0245000--