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--