Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/sparc/sparc Change locking prerequisites for the pv...



details:   https://anonhg.NetBSD.org/src/rev/ef1127e8a040
branches:  trunk
changeset: 543249:ef1127e8a040
user:      pk <pk%NetBSD.org@localhost>
date:      Thu Feb 20 16:22:49 2003 +0000

description:
Change locking prerequisites for the pv_changepte4m() helper function
to avoid locking recursion.

diffstat:

 sys/arch/sparc/sparc/pmap.c |  95 +++++++++++++++++++++++---------------------
 1 files changed, 49 insertions(+), 46 deletions(-)

diffs (235 lines):

diff -r 31dd902cfe7b -r ef1127e8a040 sys/arch/sparc/sparc/pmap.c
--- a/sys/arch/sparc/sparc/pmap.c       Thu Feb 20 15:39:58 2003 +0000
+++ b/sys/arch/sparc/sparc/pmap.c       Thu Feb 20 16:22:49 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.242 2003/02/19 22:27:08 pk Exp $ */
+/*     $NetBSD: pmap.c,v 1.243 2003/02/20 16:22:49 pk Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -2462,6 +2462,8 @@
  * as long as the process has a context; this is overly conservative.
  * It also copies ref and mod bits to the pvlist, on the theory that
  * this might save work later.  (XXX should test this theory)
+ *
+ * Called with PV lock and pmap main lock held.
  */
 void
 pv_changepte4m(pg, bis, bic)
@@ -2470,26 +2472,20 @@
 {
        struct pvlist *pv;
        struct pmap *pm;
-       int va, vr;
-       int s;
+       vaddr_t va;
        struct regmap *rp;
        struct segmap *sp;
 
        pv = VM_MDPAGE_PVHEAD(pg);
-
-       s = splvm();                    /* paranoid? */
-       PMAP_HEAD_TO_MAP_LOCK();
-       simple_lock(&pg->mdpage.pv_slock);
-       if (pv->pv_pmap == NULL) {
-               goto out;
-       }
+       if (pv->pv_pmap == NULL)
+               return;
 
        for (; pv != NULL; pv = pv->pv_next) {
                int tpte;
                pm = pv->pv_pmap;
+               /* XXXSMP: should lock pm */
                va = pv->pv_va;
-               vr = VA_VREG(va);
-               rp = &pm->pm_regmap[vr];
+               rp = &pm->pm_regmap[VA_VREG(va)];
                sp = &rp->rg_segmap[VA_VSEG(va)];
 
                if (pm->pm_ctx) {
@@ -2512,11 +2508,6 @@
                    &sp->sg_pte[VA_SUN4M_VPG(va)], bic, bis, pm->pm_ctxnum,
                    PMAP_CPUSET(pm)));
        }
-
-out:
-       simple_unlock(&pg->mdpage.pv_slock);
-       PMAP_HEAD_TO_MAP_UNLOCK();
-       splx(s);
 }
 
 /*
@@ -2537,10 +2528,9 @@
        struct segmap *sp;
        boolean_t doflush;
 
+       s = splvm();
+       PMAP_HEAD_TO_MAP_LOCK();
        pv = VM_MDPAGE_PVHEAD(pg);
-
-       s = splvm();                    /* paranoid? */
-       PMAP_HEAD_TO_MAP_LOCK();
        if (pv->pv_pmap == NULL) {      /* paranoid */
                flags = 0;
                goto out;
@@ -2703,7 +2693,7 @@
        vaddr_t va;
        unsigned int *pteprotop;
 {
-       struct pvlist *pv0, *npv;
+       struct pvlist *pv0, *pv, *npv;
        int nc = (*pteprotop & SRMMU_PG_C) == 0 ? PV_NC : 0;
        int error = 0;
 
@@ -2722,16 +2712,15 @@
 
        pmap_stats.ps_enter_secondpv++;
 
+       /*
+        * Allocate the new PV entry now, and, if that fails, bail out 
+        * before changing the cacheable state of the existing mappings.
+        */
        npv = pool_get(&pv_pool, PR_NOWAIT);
        if (npv == NULL) {
                error = ENOMEM;
                goto out;
        }
-       npv->pv_next = pv0->pv_next;
-       npv->pv_pmap = pm;
-       npv->pv_va = va;
-       npv->pv_flags = nc;
-       pv0->pv_next = npv;
 
        /*
         * See if the new mapping will cause old mappings to
@@ -2743,8 +2732,8 @@
                goto out;
        }
 
-       for (npv = pv0; npv != NULL; npv = npv->pv_next) {
-               if ((npv->pv_flags & PV_NC) != 0) {
+       for (pv = pv0; pv != NULL; pv = pv->pv_next) {
+               if ((pv->pv_flags & PV_NC) != 0) {
                        *pteprotop &= ~SRMMU_PG_C;
 #ifdef DEBUG
                        /* Check currently illegal condition */
@@ -2752,16 +2741,16 @@
                                printf("pv_link: proc %s, va=0x%lx: "
                                "unexpected uncached mapping at 0x%lx\n",
                                    curproc ? curproc->p_comm : "--",
-                                   va, npv->pv_va);
+                                   va, pv->pv_va);
 #endif
                }
-               if (BADALIAS(va, npv->pv_va)) {
+               if (BADALIAS(va, pv->pv_va)) {
 #ifdef DEBUG
                        if (pmapdebug & PDB_CACHESTUFF)
                                printf(
                        "pv_link: badalias: proc %s, 0x%lx<=>0x%lx, pg %p\n",
                                curproc ? curproc->p_comm : "--",
-                               va, npv->pv_va, pg);
+                               va, pv->pv_va, pg);
 #endif
                        /* Mark list head `uncached due to aliases' */
                        pv0->pv_flags |= PV_ANC;
@@ -2771,6 +2760,13 @@
                }
        }
 
+       /* Now link in the new PV entry */
+       npv->pv_next = pv0->pv_next;
+       npv->pv_pmap = pm;
+       npv->pv_va = va;
+       npv->pv_flags = nc;
+       pv0->pv_next = npv;
+
 out:
        simple_unlock(&pg->mdpage.pv_slock);
        return (0);
@@ -2786,10 +2782,15 @@
 static void pv_uncache(struct vm_page *pg)
 {
        struct pvlist *pv;
+       int s;
 
        for (pv = VM_MDPAGE_PVHEAD(pg); pv != NULL; pv = pv->pv_next)
                pv->pv_flags |= PV_NC;
 
+       s = splvm();
+       PMAP_HEAD_TO_MAP_LOCK();
+       simple_lock(&pg->mdpage.pv_slock);
+
 #if defined(SUN4M) || defined(SUN4D)
        if (CPU_HAS_SRMMU)
                pv_changepte4m(pg, 0, SRMMU_PG_C);
@@ -2798,6 +2799,9 @@
        if (CPU_ISSUN4 || CPU_ISSUN4C)
                pv_changepte4_4c(pg, PG_NC, 0);
 #endif
+       simple_unlock(&pg->mdpage.pv_slock);
+       PMAP_HEAD_TO_MAP_UNLOCK();
+       splx(s);
 }
 
 /*
@@ -5083,30 +5087,27 @@
        if (pg == NULL || prot & VM_PROT_WRITE)
                return;
 
+       s = splvm();
+       PMAP_HEAD_TO_MAP_LOCK();
+       simple_lock(&pg->mdpage.pv_slock);
+
        if (prot & VM_PROT_READ) {
                pv_changepte4m(pg, 0, PPROT_WRITE);
-               return;
+               goto out;
        }
 
        /*
         * Remove all access to all people talking to this page.
-        * Walk down PV list, removing all mappings.
-        * The logic is much like that for pmap_remove,
-        * but we know we are removing exactly one page.
+        * Walk down PV list, removing all mappings. The logic is much
+        * like that for pmap_remove, but we know we are removing exactly
+        * one page.
         */
-       s = splvm();
        pv = VM_MDPAGE_PVHEAD(pg);
-       if (pv->pv_pmap == NULL) {
-               splx(s);
-               return;
-       }
+       if (pv->pv_pmap == NULL)
+               goto out;
 
        /* This pv head will become empty, so clear caching state flags */
        flags = pv->pv_flags & ~(PV_NC|PV_ANC);
-
-       PMAP_HEAD_TO_MAP_LOCK();
-       simple_lock(&pg->mdpage.pv_slock);
-
        while (pv != NULL) {
                pm = pv->pv_pmap;
                simple_lock(&pm->pm_lock);
@@ -5150,13 +5151,15 @@
                simple_unlock(&pm->pm_lock);
                pv = npv;
        }
-       simple_unlock(&pg->mdpage.pv_slock);
-       PMAP_HEAD_TO_MAP_UNLOCK();
 
        /* Finally, update pv head */
        VM_MDPAGE_PVHEAD(pg)->pv_pmap = NULL;
        VM_MDPAGE_PVHEAD(pg)->pv_next = NULL;
        VM_MDPAGE_PVHEAD(pg)->pv_flags = flags;
+
+out:
+       simple_unlock(&pg->mdpage.pv_slock);
+       PMAP_HEAD_TO_MAP_UNLOCK();
        splx(s);
 }
 



Home | Main Index | Thread Index | Old Index