summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2003-12-14 22:08:03 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2003-12-14 22:08:03 +0000
commit24f501922f769d6a187798fd60429fdb894330a6 (patch)
tree86bc3870aaaa7543d506c3b535837a45cf7b206b /sys/arch/mvme88k
parentf52e5a059a96c9e2974d8a0cf9cdd648ff6a905e (diff)
Replace pmap_testbit/pmap_changebit sequences with a tailor-made pmap_unsetbit
routine, in order to speed up pmap_clear_modify() and pmap_clear_reference().
Diffstat (limited to 'sys/arch/mvme88k')
-rw-r--r--sys/arch/mvme88k/include/pmap.h8
-rw-r--r--sys/arch/mvme88k/mvme88k/pmap.c128
2 files changed, 102 insertions, 34 deletions
diff --git a/sys/arch/mvme88k/include/pmap.h b/sys/arch/mvme88k/include/pmap.h
index 5d5a3948f69..373aa4770f3 100644
--- a/sys/arch/mvme88k/include/pmap.h
+++ b/sys/arch/mvme88k/include/pmap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.31 2003/10/11 22:08:57 miod Exp $ */
+/* $OpenBSD: pmap.h,v 1.32 2003/12/14 22:08:01 miod Exp $ */
/*
* Mach Operating System
* Copyright (c) 1991 Carnegie Mellon University
@@ -65,10 +65,14 @@ extern caddr_t vmmap;
#define pmap_phys_address(frame) ((paddr_t)(ptoa(frame)))
#define pmap_copy(dp,sp,d,l,s) do { /* nothing */ } while (0)
-#define pmap_update(pmap) do { /* nothing (yet) */ } while (0)
+#define pmap_update(pmap) do { /* nothing (yet) */ } while (0)
+
+#define pmap_clear_modify(pg) pmap_unsetbit(pg, PG_M)
+#define pmap_clear_reference(pg) pmap_unsetbit(pg, PG_U)
void pmap_bootstrap(vaddr_t, paddr_t *, paddr_t *, vaddr_t *, vaddr_t *);
void pmap_cache_ctrl(pmap_t, vaddr_t, vaddr_t, u_int);
+boolean_t pmap_unsetbit(struct vm_page *, int);
#endif /* _KERNEL */
diff --git a/sys/arch/mvme88k/mvme88k/pmap.c b/sys/arch/mvme88k/mvme88k/pmap.c
index c37a1edf8a9..f02b6570884 100644
--- a/sys/arch/mvme88k/mvme88k/pmap.c
+++ b/sys/arch/mvme88k/mvme88k/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.93 2003/12/14 22:06:39 miod Exp $ */
+/* $OpenBSD: pmap.c,v 1.94 2003/12/14 22:08:02 miod Exp $ */
/*
* Copyright (c) 2001, 2002, 2003 Miodrag Vallat
* Copyright (c) 1998-2001 Steve Murphree, Jr.
@@ -103,7 +103,7 @@ extern vaddr_t virtual_avail, virtual_end;
#define CD_COL 0x0020000 /* pmap_collect */
#define CD_CBIT 0x0040000 /* pmap_changebit */
#define CD_TBIT 0x0080000 /* pmap_testbit */
-#define CD_CREF 0x0100000 /* pmap_clear_reference */
+#define CD_USBIT 0x0100000 /* pmap_unsetbit */
#define CD_PGMV 0x0200000 /* pagemove */
#define CD_ALL 0x0FFFFFC
@@ -246,6 +246,7 @@ vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t, u_int);
pt_entry_t *pmap_pte(pmap_t, vaddr_t);
void pmap_remove_all(struct vm_page *);
void pmap_changebit(struct vm_page *, int, int);
+boolean_t pmap_unsetbit(struct vm_page *, int);
boolean_t pmap_testbit(struct vm_page *, int);
/*
@@ -2621,22 +2622,6 @@ next:
}
/*
- * Routine: PMAP_CLEAR_MODIFY
- *
- * Function:
- * Clears the modify bits on the specified physical page.
- */
-boolean_t
-pmap_clear_modify(struct vm_page *pg)
-{
- boolean_t rv;
-
- rv = pmap_testbit(pg, PG_M);
- pmap_changebit(pg, 0, ~PG_M);
- return rv;
-}
-
-/*
* Routine: PMAP_TESTBIT
*
* Function:
@@ -2671,8 +2656,8 @@ pmap_testbit(struct vm_page *pg, int bit)
SPLVM(spl);
- pvl = pg_to_pvh(pg);
testbit_Retry:
+ pvl = pg_to_pvh(pg);
if (pvl->pv_flags & bit) {
/* we've already cached this flag for this page,
@@ -2732,32 +2717,111 @@ next:
}
/*
- * Routine: PMAP_IS_MODIFIED
+ * Routine: PMAP_UNSETBIT
*
* Function:
- * Return whether or not the specified physical page is modified
- * by any physical maps.
+ * Clears a pte bit and returns its previous state, for the
+ * specified physical page.
+ * This is an optimized version of:
+ * rv = pmap_testbit(pg, bit);
+ * pmap_changebit(pg, 0, ~bit);
+ * return rv;
*/
boolean_t
-pmap_is_modified(struct vm_page *pg)
+pmap_unsetbit(struct vm_page *pg, int bit)
{
- return pmap_testbit(pg, PG_M);
+ boolean_t rv = FALSE;
+ pv_entry_t pvl, pvep;
+ pt_entry_t *pte, opte;
+ pmap_t pmap;
+ int spl;
+ vaddr_t va;
+ u_int users;
+ boolean_t kflush;
+
+ SPLVM(spl);
+
+unsetbit_Retry:
+ pvl = pg_to_pvh(pg);
+
+ /*
+ * Clear saved attributes
+ */
+ pvl->pv_flags &= ~bit;
+
+ if (pvl->pv_pmap == PMAP_NULL) {
+#ifdef DEBUG
+ if (pmap_con_dbg & CD_USBIT)
+ printf("(pmap_unsetbit: %x) vm page 0x%x not mapped\n",
+ curproc, pg);
+#endif
+ SPLX(spl);
+ return (FALSE);
+ }
+
+ /* for each listed pmap, update the specified bit */
+ for (pvep = pvl; pvep != PV_ENTRY_NULL; pvep = pvep->pv_next) {
+ pmap = pvep->pv_pmap;
+ if (!simple_lock_try(&pmap->pm_lock)) {
+ goto unsetbit_Retry;
+ }
+ users = pmap->pm_cpus;
+ if (pmap == kernel_pmap) {
+ kflush = TRUE;
+ } else {
+ kflush = FALSE;
+ }
+
+ va = pvep->pv_va;
+ pte = pmap_pte(pmap, va);
+
+ /*
+ * Check for existing and valid pte
+ */
+ if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) {
+ goto next; /* no page mapping */
+ }
+#ifdef DIAGNOSTIC
+ if (ptoa(PG_PFNUM(*pte)) != VM_PAGE_TO_PHYS(pg))
+ panic("pmap_unsetbit: pte %x in pmap %x %d doesn't point to page %x %x",
+ *pte, pmap, kflush, pg, VM_PAGE_TO_PHYS(pg));
+#endif
+
+ /*
+ * Update bits
+ */
+ opte = *pte;
+ if (opte & bit) {
+ /*
+ * Flush TLB of which cpus using pmap.
+ *
+ * Invalidate pte temporarily to avoid the specified
+ * bit being written back by any other cpu.
+ */
+ invalidate_pte(pte);
+ *pte = opte ^ bit;
+ flush_atc_entry(users, va, kflush);
+ } else
+ rv = TRUE;
+next:
+ simple_unlock(&pmap->pm_lock);
+ }
+ SPLX(spl);
+
+ return (rv);
}
/*
- * Routine: PMAP_CLEAR_REFERENCE
+ * Routine: PMAP_IS_MODIFIED
*
* Function:
- * Clear the reference bit on the specified physical page.
+ * Return whether or not the specified physical page is modified
+ * by any physical maps.
*/
boolean_t
-pmap_clear_reference(struct vm_page *pg)
+pmap_is_modified(struct vm_page *pg)
{
- boolean_t rv;
-
- rv = pmap_testbit(pg, PG_U);
- pmap_changebit(pg, 0, ~PG_U);
- return rv;
+ return pmap_testbit(pg, PG_M);
}
/*