Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sh3 Rewrite how mod/ref emulation is done. In part...
details: https://anonhg.NetBSD.org/src/rev/5f8ab5aa2975
branches: trunk
changeset: 503154:5f8ab5aa2975
user: thorpej <thorpej%NetBSD.org@localhost>
date: Fri Feb 02 02:28:18 2001 +0000
description:
Rewrite how mod/ref emulation is done. In particular, make
modified attribute checking actually work. Previously, a
page could be reported as modified even if it wasn't! This
is very bad, and e.g. caused the VM system to attempt to
"clean" pages of read-only files.
Only lip-services is paid to referenced attribute emulation.
This could be improved.
diffstat:
sys/arch/sh3/include/pmap.h | 41 +----
sys/arch/sh3/sh3/pmap.c | 297 +++++++++++++++++++++++++++++--------------
2 files changed, 208 insertions(+), 130 deletions(-)
diffs (truncated from 474 to 300 lines):
diff -r 51ef09196809 -r 5f8ab5aa2975 sys/arch/sh3/include/pmap.h
--- a/sys/arch/sh3/include/pmap.h Fri Feb 02 01:55:52 2001 +0000
+++ b/sys/arch/sh3/include/pmap.h Fri Feb 02 02:28:18 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.6 2000/09/28 14:03:38 is Exp $ */
+/* $NetBSD: pmap.h,v 1.7 2001/02/02 02:28:18 thorpej Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -279,6 +279,10 @@
struct pv_entry *pvh_list; /* head of list (locked by pvh_lock) */
};
+/* These are kept in the vm_physseg array. */
+#define PGA_REFERENCED 0x01 /* page is referenced */
+#define PGA_MODIFIED 0x02 /* page is modified */
+
struct pv_entry { /* locked by its list's pvh_lock */
struct pv_entry *pv_next; /* next entry */
struct pmap *pv_pmap; /* the pmap */
@@ -364,15 +368,10 @@
#define pmap_update() tlbflush()
#endif
-#define pmap_clear_modify(pg) pmap_change_attrs(pg, 0, PG_M)
-#define pmap_clear_reference(pg) pmap_change_attrs(pg, 0, PG_U)
+#define pmap_is_referenced(pg) pmap_test_attrs(pg, PGA_REFERENCED)
+#define pmap_is_modified(pg) pmap_test_attrs(pg, PGA_MODIFIED)
+
#define pmap_copy(DP,SP,D,L,S) pmap_transfer(DP,SP,D,L,S, FALSE)
-#define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M)
-#ifdef notyet
-#define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U)
-#else
-#define pmap_is_referenced(pg) 1
-#endif
#define pmap_move(DP,SP,D,L,S) pmap_transfer(DP,SP,D,L,S, TRUE)
#define pmap_phys_address(ppn) sh3_ptob(ppn)
#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */
@@ -386,7 +385,6 @@
void pmap_bootstrap __P((vaddr_t));
boolean_t pmap_change_attrs __P((struct vm_page *, int, int));
void pmap_deactivate __P((struct proc *));
-static void pmap_page_protect __P((struct vm_page *, vm_prot_t));
void pmap_page_remove __P((struct vm_page *));
static void pmap_protect __P((struct pmap *, vaddr_t,
vaddr_t, vm_prot_t));
@@ -460,29 +458,6 @@
}
/*
- * pmap_page_protect: change the protection of all recorded mappings
- * of a managed page
- *
- * => this function is a frontend for pmap_page_remove/pmap_change_attrs
- * => we only have to worry about making the page more protected.
- * unprotecting a page is done on-demand at fault time.
- */
-
-__inline static void
-pmap_page_protect(pg, prot)
- struct vm_page *pg;
- vm_prot_t prot;
-{
- if ((prot & VM_PROT_WRITE) == 0) {
- if (prot & (VM_PROT_READ|VM_PROT_EXECUTE)) {
- (void) pmap_change_attrs(pg, PG_RO, PG_RW);
- } else {
- pmap_page_remove(pg);
- }
- }
-}
-
-/*
* pmap_protect: change the protection of pages in a pmap
*
* => this function is a frontend for pmap_remove/pmap_write_protect
diff -r 51ef09196809 -r 5f8ab5aa2975 sys/arch/sh3/sh3/pmap.c
--- a/sys/arch/sh3/sh3/pmap.c Fri Feb 02 01:55:52 2001 +0000
+++ b/sys/arch/sh3/sh3/pmap.c Fri Feb 02 02:28:18 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.13 2001/01/14 03:25:46 thorpej Exp $ */
+/* $NetBSD: pmap.c,v 1.14 2001/02/02 02:28:18 thorpej Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -395,6 +395,8 @@
void pmap_pinit __P((pmap_t));
void pmap_release __P((pmap_t));
+void pmap_changebit(struct pv_head *, pt_entry_t,
+ pt_entry_t);
/*
* p m a p i n l i n e h e l p e r f u n c t i o n s
@@ -2318,7 +2320,7 @@
/*
* pmap_test_attrs: test a page's attributes
*
- * => we set pv_head => pmap locking
+ * => no need for any locking here
*/
boolean_t
@@ -2326,11 +2328,7 @@
struct vm_page *pg;
int testbits;
{
- int bank, off;
- char *myattrs;
- struct pv_head *pvh;
- struct pv_entry *pve;
- pt_entry_t *ptes, pte;
+ int bank, off, attr;
/* XXX: vm_page should either contain pv_head or have a pointer to it */
bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
@@ -2339,68 +2337,30 @@
return(FALSE);
}
- /*
- * before locking: see if attributes are already set and if so,
- * return!
- */
-
- myattrs = &vm_physmem[bank].pmseg.attrs[off];
- if (*myattrs & testbits)
- return(TRUE);
-
- /* test to see if there is a list before bothering to lock */
- pvh = &vm_physmem[bank].pmseg.pvhead[off];
- if (pvh->pvh_list == NULL) {
- return(FALSE);
- }
-
- /* nope, gonna have to do it the hard way */
- PMAP_HEAD_TO_MAP_LOCK();
- /* XXX: needed if we hold head->map lock? */
- simple_lock(&pvh->pvh_lock);
-
- for (pve = pvh->pvh_list; pve != NULL && (*myattrs & testbits) == 0;
- pve = pve->pv_next) {
- ptes = pmap_map_ptes(pve->pv_pmap);
- pte = ptes[sh3_btop(pve->pv_va)];
- pmap_unmap_ptes(pve->pv_pmap);
- *myattrs |= pte;
- }
-
- /*
- * note that we will exit the for loop with a non-null pve if
- * we have found the bits we are testing for.
- */
-
- simple_unlock(&pvh->pvh_lock);
- PMAP_HEAD_TO_MAP_UNLOCK();
- return((*myattrs & testbits) != 0);
+ attr = vm_physmem[bank].pmseg.attrs[off];
+
+ return ((attr & testbits) != 0 ? TRUE : FALSE);
}
/*
- * pmap_change_attrs: change a page's attributes
+ * pmap_clear_modify: clear the "modified" attribute on a page.
*
* => we set pv_head => pmap locking
- * => we return TRUE if we cleared one of the bits we were asked to
+ * => we return TRUE if the page was marked "modified".
*/
boolean_t
-pmap_change_attrs(pg, setbits, clearbits)
- struct vm_page *pg;
- int setbits, clearbits;
+pmap_clear_modify(vm_page_t pg)
{
- u_int32_t result;
int bank, off;
struct pv_head *pvh;
- struct pv_entry *pve;
- pt_entry_t *ptes, npte;
- char *myattrs;
+ boolean_t rv;
/* XXX: vm_page should either contain pv_head or have a pointer to it */
bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
if (bank == -1) {
- printf("pmap_change_attrs: unmanaged page?\n");
- return(FALSE);
+ printf("pmap_clear_modify: unmanged page?\n");
+ return (FALSE);
}
PMAP_HEAD_TO_MAP_LOCK();
@@ -2408,24 +2368,87 @@
/* XXX: needed if we hold head->map lock? */
simple_lock(&pvh->pvh_lock);
- myattrs = &vm_physmem[bank].pmseg.attrs[off];
- result = *myattrs & clearbits;
- *myattrs = (*myattrs | setbits) & ~clearbits;
+ if (vm_physmem[bank].pmseg.attrs[off] & PGA_MODIFIED) {
+ rv = TRUE;
+ pmap_changebit(pvh, 0, ~PG_M);
+ vm_physmem[bank].pmseg.attrs[off] &= ~PGA_MODIFIED;
+ } else
+ rv = FALSE;
+
+ simple_unlock(&pvh->pvh_lock);
+ PMAP_HEAD_TO_MAP_UNLOCK();
+
+ return (rv);
+}
+
+/*
+ * pmap_clear_reference: clear the "referenced" attribute on a page.
+ *
+ * => we set pv_head => pmap locking
+ * => we return TRUE if the page was marked "modified".
+ * => XXX Note, referenced emulation isn't complete.
+ */
+
+boolean_t
+pmap_clear_reference(vm_page_t pg)
+{
+ int bank, off;
+ struct pv_head *pvh;
+ boolean_t rv;
+
+ /* XXX: vm_page should either contain pv_head or have a pointer to it */
+ bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
+ if (bank == -1) {
+ printf("pmap_clear_modify: unmanged page?\n");
+ return (FALSE);
+ }
+
+ PMAP_HEAD_TO_MAP_LOCK();
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ /* XXX: needed if we hold head->map lock? */
+ simple_lock(&pvh->pvh_lock);
+
+ if (vm_physmem[bank].pmseg.attrs[off] & PGA_REFERENCED) {
+ rv = TRUE;
+#if 0 /* XXX notyet */
+ pmap_changebit(pvh, 0, ~PG_V);
+#endif
+ vm_physmem[bank].pmseg.attrs[off] &= ~PGA_REFERENCED;
+ } else
+ rv = FALSE;
+
+ simple_unlock(&pvh->pvh_lock);
+ PMAP_HEAD_TO_MAP_UNLOCK();
+
+ return (rv);
+}
+
+/*
+ * pmap_changebit: set or clear the specified PTEL bits for all
+ * mappings on the specified page.
+ *
+ * => We expect the pv_head -> map lock to be held
+ */
+
+void
+pmap_changebit(struct pv_head *pvh, pt_entry_t set, pt_entry_t mask)
+{
+ struct pv_entry *pve;
+ pt_entry_t *ptes, npte;
for (pve = pvh->pvh_list; pve != NULL; pve = pve->pv_next) {
-#ifdef DIAGNOSTIC
- if (pve->pv_va >= uvm.pager_sva && pve->pv_va < uvm.pager_eva) {
- printf("pmap_change_attrs: found pager VA on pv_list\n");
+ /*
+ * XXX Don't write protect pager mappings.
+ */
+ if (pve->pv_pmap == pmap_kernel() &&
+/* XXX */ (mask == ~(PG_RW))) {
+ if (pve->pv_va >= uvm.pager_sva &&
+ pve->pv_va < uvm.pager_eva)
+ continue;
}
- if (!pmap_valid_entry(pve->pv_pmap->pm_pdir[pdei(pve->pv_va)]))
- panic("pmap_change_attrs: mapping without PTP "
- "detected");
-#endif
ptes = pmap_map_ptes(pve->pv_pmap); /* locks pmap */
- npte = ptes[sh3_btop(pve->pv_va)];
- result |= (npte & clearbits);
- npte = (npte | setbits) & ~clearbits;
+ npte = (ptes[sh3_btop(pve->pv_va)] | set) & mask;
if (ptes[sh3_btop(pve->pv_va)] != npte) {
ptes[sh3_btop(pve->pv_va)] = npte; /* zap! */
@@ -2435,11 +2458,6 @@
}
pmap_unmap_ptes(pve->pv_pmap); /* unlocks pmap */
}
Home |
Main Index |
Thread Index |
Old Index