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 - Share common code between pmap_load() and...



details:   https://anonhg.NetBSD.org/src/rev/cacd8f50c7d1
branches:  trunk
changeset: 847253:cacd8f50c7d1
user:      ad <ad%NetBSD.org@localhost>
date:      Sun Dec 15 20:33:22 2019 +0000

description:
- Share common code between pmap_load() and pmap_map_ptes().
- Make pmap_map_ptes() better tolerate recovery from blocking.

diffstat:

 sys/arch/x86/x86/pmap.c |  94 +++++++++++++++++++++++++-----------------------
 1 files changed, 49 insertions(+), 45 deletions(-)

diffs (171 lines):

diff -r 9be31be5ef06 -r cacd8f50c7d1 sys/arch/x86/x86/pmap.c
--- a/sys/arch/x86/x86/pmap.c   Sun Dec 15 20:30:56 2019 +0000
+++ b/sys/arch/x86/x86/pmap.c   Sun Dec 15 20:33:22 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.344 2019/12/15 19:24:11 ad Exp $    */
+/*     $NetBSD: pmap.c,v 1.345 2019/12/15 20:33:22 ad Exp $    */
 
 /*
  * Copyright (c) 2008, 2010, 2016, 2017, 2019 The NetBSD Foundation, Inc.
@@ -130,7 +130,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.344 2019/12/15 19:24:11 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.345 2019/12/15 20:33:22 ad Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -470,6 +470,7 @@
 
 static void pmap_alloc_level(struct pmap *, vaddr_t, long *);
 
+static void pmap_load1(struct lwp *, struct pmap *, struct pmap *);
 static void pmap_reactivate(struct pmap *);
 
 /*
@@ -642,20 +643,12 @@
                pmap_reactivate(pmap);
        } else {
                /*
-                * Toss current pmap from CPU, but keep a reference to it.
-                * The reference will be dropped by pmap_unmap_ptes().
-                * Can happen if we block during exit().
+                * Toss current pmap from CPU and install new pmap, but keep
+                * a reference to the old one - dropping the reference can
+                * block, so we'll defer to pmap_unmap_ptes().
                 */
-               const cpuid_t cid = cpu_index(ci);
-
-               kcpuset_atomic_clear(curpmap->pm_cpus, cid);
-               kcpuset_atomic_clear(curpmap->pm_kernel_cpus, cid);
-               ci->ci_pmap = pmap;
-               ci->ci_tlbstate = TLBSTATE_VALID;
-               ci->ci_want_pmapload = 0;
-               kcpuset_atomic_set(pmap->pm_cpus, cid);
-               kcpuset_atomic_set(pmap->pm_kernel_cpus, cid);
-               cpu_load_pmap(pmap, curpmap);
+               pmap_reference(pmap);
+               pmap_load1(l, pmap, curpmap);
        }
        pmap->pm_ncsw = lwp_pctr();
        *pmap2 = curpmap;
@@ -714,7 +707,7 @@
         * Mark whatever's on the CPU now as lazy and unlock.
         * If the pmap was already installed, we are done.
         */
-       if (ci->ci_tlbstate == TLBSTATE_VALID) {
+       if (ci->ci_pmap != mypmap && ci->ci_tlbstate == TLBSTATE_VALID) {
                ci->ci_tlbstate = TLBSTATE_LAZY;
                ci->ci_want_pmapload = (mypmap != pmap_kernel());
        } else {
@@ -722,21 +715,17 @@
                 * This can happen when undoing after pmap_get_ptp blocked.
                 */ 
        }
+
        /* Now safe to free PTPs, with the pmap still locked. */
        if (ptp_tofree != NULL) {
                pmap_freepages(pmap, ptp_tofree);
        }
        mutex_exit(&pmap->pm_lock);
-       if (pmap == pmap2) {
-               return;
-       }
-
-       /*
-        * We installed another pmap on the CPU.  Grab a reference to
-        * it and leave in place.  Toss the evicted pmap (can block).
-        */
-       pmap_reference(pmap);
-       pmap_destroy(pmap2);
+
+       /* Toss the pmap we evicted earlier (can block). */
+       if (pmap != pmap2) {
+               pmap_destroy(pmap2);
+       }
 }
 
 inline static void
@@ -2884,8 +2873,6 @@
        struct cpu_info *ci;
        struct pmap *pmap, *oldpmap;
        struct lwp *l;
-       struct pcb *pcb;
-       cpuid_t cid;
        uint64_t ncsw;
 
        kpreempt_disable();
@@ -2912,7 +2899,6 @@
        pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map);
        KASSERT(pmap != pmap_kernel());
        oldpmap = ci->ci_pmap;
-       pcb = lwp_getpcb(l);
 
        if (pmap == oldpmap) {
                pmap_reactivate(pmap);
@@ -2926,8 +2912,41 @@
         */
 
        pmap_reference(pmap);
-
+       pmap_load1(l, pmap, oldpmap);
+       ci->ci_want_pmapload = 0;
+
+       /*
+        * we're now running with the new pmap.  drop the reference
+        * to the old pmap.  if we block, we need to go around again.
+        */
+
+       pmap_destroy(oldpmap);
+       __insn_barrier();
+       if (l->l_ncsw != ncsw) {
+               goto retry;
+       }
+
+       kpreempt_enable();
+}
+
+/*
+ * pmap_load1: the guts of pmap load, shared by pmap_map_ptes() and
+ * pmap_load().  It's critically important that this function does not
+ * block.
+ */
+static void
+pmap_load1(struct lwp *l, struct pmap *pmap, struct pmap *oldpmap)
+{
+       struct cpu_info *ci;
+       struct pcb *pcb;
+       cpuid_t cid;
+
+       KASSERT(kpreempt_disabled());
+
+       pcb = lwp_getpcb(l);
+       ci = l->l_cpu;
        cid = cpu_index(ci);
+
        kcpuset_atomic_clear(oldpmap->pm_cpus, cid);
        kcpuset_atomic_clear(oldpmap->pm_kernel_cpus, cid);
 
@@ -2970,21 +2989,6 @@
        lldt(pmap->pm_ldt_sel);
 
        cpu_load_pmap(pmap, oldpmap);
-
-       ci->ci_want_pmapload = 0;
-
-       /*
-        * we're now running with the new pmap.  drop the reference
-        * to the old pmap.  if we block, we need to go around again.
-        */
-
-       pmap_destroy(oldpmap);
-       __insn_barrier();
-       if (l->l_ncsw != ncsw) {
-               goto retry;
-       }
-
-       kpreempt_enable();
 }
 
 /*



Home | Main Index | Thread Index | Old Index