Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/x86/x86 - Give pmap uvm_objects an empty pagerops t...



details:   https://anonhg.NetBSD.org/src/rev/c7fb16919154
branches:  trunk
changeset: 969801:c7fb16919154
user:      ad <ad%NetBSD.org@localhost>
date:      Sun Mar 01 21:42:58 2020 +0000

description:
- Give pmap uvm_objects an empty pagerops to avoid special casing in UVM.
  (This use of uvm_object causes a disproportionate amount of work.)

- Undo the pmap_destroy()/pmap_delref() split.  I misunderstood the flow of
  control, and there's no need for this.

- For pmap_remove_pv(), always look up the pv_entry in advance as those
  calls will need to be covered by lock again soon.

diffstat:

 sys/arch/x86/x86/pmap.c |  88 +++++++++++++++++++++---------------------------
 1 files changed, 38 insertions(+), 50 deletions(-)

diffs (252 lines):

diff -r 31757c56f828 -r c7fb16919154 sys/arch/x86/x86/pmap.c
--- a/sys/arch/x86/x86/pmap.c   Sun Mar 01 21:40:45 2020 +0000
+++ b/sys/arch/x86/x86/pmap.c   Sun Mar 01 21:42:58 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.360 2020/02/29 20:17:11 ad Exp $    */
+/*     $NetBSD: pmap.c,v 1.361 2020/03/01 21:42:58 ad Exp $    */
 
 /*
  * Copyright (c) 2008, 2010, 2016, 2017, 2019, 2020 The NetBSD Foundation, Inc.
@@ -130,7 +130,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.360 2020/02/29 20:17:11 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.361 2020/03/01 21:42:58 ad Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -252,6 +252,10 @@
 #define        PMAP_DUMMY_UNLOCK(pm)
 #endif
 
+static const struct uvm_pagerops pmap_pager = {
+       /* nothing */
+};
+
 const vaddr_t ptp_masks[] = PTP_MASK_INITIALIZER;
 const vaddr_t ptp_frames[] = PTP_FRAME_INITIALIZER;
 const int ptp_shifts[] = PTP_SHIFT_INITIALIZER;
@@ -444,7 +448,6 @@
 
 static void pmap_load1(struct lwp *, struct pmap *, struct pmap *);
 static void pmap_reactivate(struct pmap *);
-static void pmap_dropref(struct pmap *);
 
 /*
  * p m a p   h e l p e r   f u n c t i o n s
@@ -677,7 +680,7 @@
 
        /* Toss reference to other pmap taken earlier. */
        if (pmap2 != NULL) {
-               pmap_dropref(pmap2);
+               pmap_destroy(pmap2);
        }
 }
 
@@ -1024,16 +1027,12 @@
         *
         * The kernel pmap's pm_obj is not used for much. However, in user pmaps
         * the pm_obj contains the list of active PTPs.
-        *
-        * The pm_obj currently does not have a pager. It might be possible to
-        * add a pager that would allow a process to read-only mmap its own page
-        * tables (fast user-level vtophys?). This may or may not be useful.
         */
        kpm = pmap_kernel();
        mutex_init(&kpm->pm_lock, MUTEX_DEFAULT, IPL_NONE);
        rw_init(&kpm->pm_dummy_lock);
        for (i = 0; i < PTP_LEVELS - 1; i++) {
-               uvm_obj_init(&kpm->pm_obj[i], NULL, false, 1);
+               uvm_obj_init(&kpm->pm_obj[i], &pmap_pager, false, 1);
                uvm_obj_setlock(&kpm->pm_obj[i], &kpm->pm_dummy_lock);
                kpm->pm_ptphint[i] = NULL;
        }
@@ -1930,7 +1929,7 @@
  * => we return the removed pve
  * => caller can optionally supply pve, if looked up already
  */
-static struct pv_entry *
+static void
 pmap_remove_pv(struct pmap *pmap, struct pmap_page *pp, struct vm_page *ptp,
     vaddr_t va, struct pv_entry *pve)
 {
@@ -1947,19 +1946,13 @@
                pp->pp_flags &= ~PP_EMBEDDED;
                pp->pp_pte.pte_ptp = NULL;
                pp->pp_pte.pte_va = 0;
-               return NULL;
-       }
-
-       if (pve == NULL) {
-               pve = pmap_pvmap_lookup(pmap, va);
+       } else {
                KASSERT(pve != NULL);
-       } else {
                KASSERT(pve == pmap_pvmap_lookup(pmap, va));
-       }
-       KASSERT(pve->pve_pte.pte_ptp == ptp);
-       KASSERT(pve->pve_pte.pte_va == va);
-       LIST_REMOVE(pve, pve_list);
-       return pve;
+               KASSERT(pve->pve_pte.pte_ptp == ptp);
+               KASSERT(pve->pve_pte.pte_va == va);
+               LIST_REMOVE(pve, pve_list);
+       }
 }
 
 /*
@@ -2487,7 +2480,7 @@
 
        /* init uvm_object */
        for (i = 0; i < PTP_LEVELS - 1; i++) {
-               uvm_obj_init(&pmap->pm_obj[i], NULL, false, 1);
+               uvm_obj_init(&pmap->pm_obj[i], &pmap_pager, false, 1);
                uvm_obj_setlock(&pmap->pm_obj[i], &pmap->pm_dummy_lock);
                pmap->pm_ptphint[i] = NULL;
        }
@@ -2545,7 +2538,7 @@
                for (int i = 0; i < PDIR_SLOT_USERLIM; i++) {
                        if (pmap->pm_pdir[i] != 0 &&
                            ci->ci_kpm_pdir[i] == pmap->pm_pdir[i]) {
-                               printf("pmap_dropref(%p) pmap_kernel %p "
+                               printf("pmap_destroy(%p) pmap_kernel %p "
                                    "curcpu %d cpu %d ci_pmap %p "
                                    "ci->ci_kpm_pdir[%d]=%" PRIx64
                                    " pmap->pm_pdir[%d]=%" PRIx64 "\n",
@@ -2562,29 +2555,22 @@
 }
 
 /*
- * pmap_destroy:  pmap is being destroyed by UVM.
- */
-void
-pmap_destroy(struct pmap *pmap)
-{
-
-       /* Undo pmap_remove_all(), then drop the reference. */
-       pmap_update(pmap);
-       pmap_dropref(pmap);
-}
-
-/*
- * pmap_dropref:  drop reference count on pmap.  free pmap if reference
+ * pmap_destroy:  drop reference count on pmap.  free pmap if reference
  * count goes to zero.
  *
  * => we can be called from pmap_unmap_ptes() with a different, unrelated
  *    pmap's lock held.  be careful!
  */
-static void
-pmap_dropref(struct pmap *pmap)
+void
+pmap_destroy(struct pmap *pmap)
 {
        int i;
 
+       /* Undo pmap_remove_all(). */
+       if (pmap->pm_remove_all == curlwp) {
+               pmap_update(pmap);
+       }
+
        /*
         * drop reference count
         */
@@ -2972,7 +2958,7 @@
         * to the old pmap.  if we block, we need to go around again.
         */
 
-       pmap_dropref(oldpmap);
+       pmap_destroy(oldpmap);
        __insn_barrier();
        if (l->l_ncsw != ncsw) {
                goto retry;
@@ -3597,8 +3583,9 @@
        }
 
        /* Sync R/M bits. */
+       pve = pmap_pvmap_lookup(pmap, va);
        pp->pp_attrs |= pmap_pte_to_pp_attrs(opte);
-       pve = pmap_remove_pv(pmap, pp, ptp, va, NULL);
+       pmap_remove_pv(pmap, pp, ptp, va, pve);
 
        if (pve) {
                pve->pve_next = *pv_tofree;
@@ -3868,16 +3855,17 @@
                        KERNEL_UNLOCK_ALL(curlwp, &hold_count);
                        mutex_exit(&pmap->pm_lock);
                        if (ptp != NULL) {
-                               pmap_dropref(pmap);
+                               pmap_destroy(pmap);
                        }
                        SPINLOCK_BACKOFF(count);
                        KERNEL_LOCK(hold_count, curlwp);
                        goto startover;
                }
 
+               va = pvpte->pte_va;
+               pve = pmap_pvmap_lookup(pmap, va);
                pp->pp_attrs |= oattrs;
-               va = pvpte->pte_va;
-               pve = pmap_remove_pv(pmap, pp, ptp, va, NULL);
+               pmap_remove_pv(pmap, pp, ptp, va, pve);
 
                /* Update the PTP reference count. Free if last reference. */
                if (ptp != NULL) {
@@ -3902,7 +3890,7 @@
                }
                mutex_exit(&pmap->pm_lock);
                if (ptp != NULL) {
-                       pmap_dropref(pmap);
+                       pmap_destroy(pmap);
                }
        }
        pmap_tlb_shootnow();
@@ -4345,7 +4333,7 @@
                                return error;
                        }
                        panic("%s: alloc pve failed", __func__);
-               }       
+               }
                error = pmap_pvmap_insert(pmap, va, pve);
                if (error != 0) {
                        if (flags & PMAP_CANFAIL) {
@@ -4445,7 +4433,7 @@
                            __func__, va, oldpa, atop(pa));
                }
 
-               (void)pmap_remove_pv(pmap, old_pp, ptp, va, pve);
+               pmap_remove_pv(pmap, old_pp, ptp, va, pve);
                old_pp->pp_attrs |= pmap_pte_to_pp_attrs(opte);
        }
 
@@ -4797,8 +4785,7 @@
         * removed.
         */
        kpreempt_disable();
-       if (pmap->pm_remove_all != NULL) {
-               KASSERT(pmap->pm_remove_all == curlwp);
+       if (pmap->pm_remove_all == curlwp) {
                pmap->pm_remove_all = NULL;
                pmap_tlb_shootdown(pmap, (vaddr_t)-1LL, 0, TLBSHOOT_UPDATE);
        }
@@ -5324,7 +5311,7 @@
                            __func__, va, oldpa, atop(pa));
                }
 
-               (void)pmap_remove_pv(pmap, old_pp, ptp, va, pve);
+               pmap_remove_pv(pmap, old_pp, ptp, va, pve);
                old_pp->pp_attrs |= pmap_ept_to_pp_attrs(opte);
        }
 
@@ -5490,8 +5477,9 @@
        }
 
        /* Sync R/M bits. */
+       pve = pmap_pvmap_lookup(pmap, va);
        pp->pp_attrs |= pmap_ept_to_pp_attrs(opte);
-       pve = pmap_remove_pv(pmap, pp, ptp, va, NULL);
+       pmap_remove_pv(pmap, pp, ptp, va, pve);
 
        if (pve) {
                pve->pve_next = *pv_tofree;



Home | Main Index | Thread Index | Old Index