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