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 switch sparc pmap lock to the scheme sp...



details:   https://anonhg.NetBSD.org/src/rev/6c46c375bf45
branches:  trunk
changeset: 447497:6c46c375bf45
user:      mrg <mrg%NetBSD.org@localhost>
date:      Sun Jan 13 22:11:11 2019 +0000

description:
switch sparc pmap lock to the scheme sparc64 uses:

- local IPL_NONE mutex for general pmap locking operations, not
  kernel lock.
- for pmap_activate()/pmap_deactivate(), switch to using the
  existing ctx_lock, and push handling of it into ctx_alloc() the
  ctx_free() callers.

fixes easy to trigger deadlocks on systems with >2 cpus.  without
this patch i usually hang during boot.  with it, i was able to
push the machine hard for over 12 hours.

XXX: pullup-8, and maybe -7.

diffstat:

 sys/arch/sparc/sparc/pmap.c |  47 +++++++++++++++++++++++---------------------
 1 files changed, 25 insertions(+), 22 deletions(-)

diffs (212 lines):

diff -r 4a963ad406d2 -r 6c46c375bf45 sys/arch/sparc/sparc/pmap.c
--- a/sys/arch/sparc/sparc/pmap.c       Sun Jan 13 19:21:27 2019 +0000
+++ b/sys/arch/sparc/sparc/pmap.c       Sun Jan 13 22:11:11 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.365 2018/09/03 16:29:27 riastradh Exp $ */
+/*     $NetBSD: pmap.c,v 1.366 2019/01/13 22:11:11 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.365 2018/09/03 16:29:27 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.366 2019/01/13 22:11:11 mrg Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -176,8 +176,8 @@
 paddr_t        vm_last_phys = 0;
 psize_t vm_num_phys;
 
-#define        PMAP_LOCK()     KERNEL_LOCK(1, NULL)
-#define        PMAP_UNLOCK()   KERNEL_UNLOCK_ONE(NULL)
+#define        PMAP_LOCK()     mutex_enter(&pmap_lock)
+#define        PMAP_UNLOCK()   mutex_exit(&pmap_lock)
 
 /*
  * Flags in pvlist.pv_flags.  Note that PV_MOD must be 1 and PV_REF must be 2
@@ -347,6 +347,7 @@
 int    seginval;               /* [4/4c] the invalid segment number */
 int    reginval;               /* [4/3mmu] the invalid region number */
 
+static kmutex_t pmap_lock;
 static kmutex_t demap_lock;
 static bool    lock_available = false; /* demap_lock has been initialized */
 
@@ -372,15 +373,15 @@
        struct  pmap *c_pmap;           /* pmap (if busy) */
 };
 
-static kmutex_t        ctx_lock;               /* lock for below */
+static kmutex_t        ctx_lock;               /* lock for below, and {,de}activate */
 union  ctxinfo *ctxinfo;               /* allocated at in pmap_bootstrap */
 union  ctxinfo *ctx_freelist;          /* context free list */
 int    ctx_kick;                       /* allocation rover when none free */
 int    ctx_kickdir;                    /* ctx_kick roves both directions */
 int    ncontext;                       /* sizeof ctx_freelist */
 
-void   ctx_alloc(struct pmap *);
-void   ctx_free(struct pmap *);
+static void    ctx_alloc(struct pmap *);
+static void    ctx_free(struct pmap *);
 
 /*void *       vdumppages;     -* 32KB worth of reserved dump pages */
 
@@ -2121,7 +2122,7 @@
  * This routine is only ever called from locore.s just after it has
  * saved away the previous process, so there are no active user windows.
  */
-void
+static void
 ctx_alloc(struct pmap *pm)
 {
        union ctxinfo *c;
@@ -2133,6 +2134,8 @@
        struct cpu_info *cpi;
 #endif
 
+       KASSERT(mutex_owned(&ctx_lock));
+
 /*XXX-GCC!*/gap_start=gap_end=0;
 #ifdef DEBUG
        if (pm->pm_ctx)
@@ -2145,7 +2148,6 @@
                gap_end = pm->pm_gap_end;
        }
 
-       mutex_spin_enter(&ctx_lock);
        if ((c = ctx_freelist) != NULL) {
                ctx_freelist = c->c_nextfree;
                cnum = c - ctxinfo;
@@ -2288,13 +2290,12 @@
                setcontext4m(cnum);
 #endif /* SUN4M || SUN4D */
        }
-       mutex_spin_exit(&ctx_lock);
 }
 
 /*
  * Give away a context.
  */
-void
+static void
 ctx_free(struct pmap *pm)
 {
        union ctxinfo *c;
@@ -2303,6 +2304,8 @@
        struct cpu_info *cpi;
 #endif
 
+       KASSERT(mutex_owned(&ctx_lock));
+
        c = pm->pm_ctx;
        ctx = pm->pm_ctxnum;
        pm->pm_ctx = NULL;
@@ -2316,8 +2319,6 @@
        }
 #endif /* SUN4 || SUN4C */
 
-       mutex_spin_enter(&ctx_lock);
-
 #if defined(SUN4M) || defined(SUN4D)
        if (CPU_HAS_SRMMU) {
                CPU_INFO_ITERATOR i;
@@ -2334,7 +2335,6 @@
 
        c->c_nextfree = ctx_freelist;
        ctx_freelist = c;
-       mutex_spin_exit(&ctx_lock);
 }
 
 
@@ -3070,6 +3070,7 @@
        }
 
        pmap_page_upload();
+       mutex_init(&pmap_lock, MUTEX_DEFAULT, IPL_NONE);
        mutex_init(&demap_lock, MUTEX_DEFAULT, IPL_VM);
        mutex_init(&ctx_lock, MUTEX_DEFAULT, IPL_SCHED);
        lock_available = true;
@@ -4392,7 +4393,9 @@
 #endif
 
        if ((c = pm->pm_ctx) != NULL) {
+               mutex_spin_enter(&ctx_lock);
                ctx_free(pm);
+               mutex_spin_exit(&ctx_lock);
        }
 
 #if defined(SUN4M) || defined(SUN4D)
@@ -4662,7 +4665,7 @@
        }
 
        ctx = getcontext();
-       s = splvm();            /* XXX conservative */
+       s = splvm();
        PMAP_LOCK();
        for (; va < endva; va = nva) {
                /* do one virtual segment at a time */
@@ -6022,7 +6025,7 @@
        splx(s);
 }
 
-#if notyet
+#if notyet /* XXXMRG delete */
 void pmap_lockmmu(vaddr_t sva, size_t sz);
 
 void
@@ -6286,7 +6289,7 @@
        sp = &rp->rg_segmap[vs];
 
        kpreempt_disable();
-       s = splvm();            /* XXX way too conservative */
+       s = splvm();
        PMAP_LOCK();
 
        if (rp->rg_seg_ptps == NULL) /* enter new region */
@@ -6372,7 +6375,7 @@
        vr = VA_VREG(va);
        vs = VA_VSEG(va);
        rp = &pm->pm_regmap[vr];
-       s = splvm();                    /* XXX conservative */
+       s = splvm();
        PMAP_LOCK();
 
        if (rp->rg_segmap == NULL) {
@@ -7494,14 +7497,14 @@
                return;
        }
 
-       PMAP_LOCK();
+       mutex_spin_enter(&ctx_lock);
        if (pm->pm_ctx == NULL) {
                ctx_alloc(pm);  /* performs setcontext() */
        } else {
                setcontext(pm->pm_ctxnum);
        }
        PMAP_SET_CPUSET(pm, &cpuinfo);
-       PMAP_UNLOCK();
+       mutex_spin_exit(&ctx_lock);
 }
 
 /*
@@ -7518,7 +7521,7 @@
        }
 
        write_user_windows();
-       PMAP_LOCK();
+       mutex_spin_enter(&ctx_lock);
        if (pm->pm_ctx) {
                (*cpuinfo.pure_vcache_flush)();
 
@@ -7530,7 +7533,7 @@
 
        /* we no longer need broadcast tlb flushes for this pmap. */
        PMAP_CLR_CPUSET(pm, &cpuinfo);
-       PMAP_UNLOCK();
+       mutex_spin_exit(&ctx_lock);
 }
 
 #ifdef DEBUG



Home | Main Index | Thread Index | Old Index