pmap - Missing critical section when calling lwkt_ipiq_process().
authorAntonio Huete Jimenez <tuxillo@quantumachine.net>
Mon, 17 Oct 2011 19:26:22 +0000 (12:26 -0700)
committerAntonio Huete Jimenez <tuxillo@quantumachine.net>
Tue, 18 Oct 2011 14:40:14 +0000 (16:40 +0200)
- pmap_interlock_wait() explicitly calls lwkt_process_ipiq() which expects to
be in a critical section. We still need cpu_ccfence() to guarantee that
pmap->pm_active is always read inside the loop.

- Sync pmap_interlock_wait's comment for both i386 and x86_64.

DragonFly-bug: <http://bugs.dragonflybsd.org/issue2152>

Reviewed by: @dillon, @vsrinivas

sys/platform/pc32/i386/pmap.c
sys/platform/pc64/x86_64/pmap.c

index 3bb09b8..f7c7921 100644 (file)
@@ -3489,11 +3489,12 @@ pmap_interlock_wait(struct vmspace *vm)
 
        if (pmap->pm_active & CPUMASK_LOCK) {
                DEBUG_PUSH_INFO("pmap_interlock_wait");
+               crit_enter();
                while (pmap->pm_active & CPUMASK_LOCK) {
-                       cpu_pause();
                        cpu_ccfence();
                        lwkt_process_ipiq();
                }
+               crit_exit();
                DEBUG_POP_INFO();
        }
 }
index 1f2a59f..ac06c70 100644 (file)
@@ -3876,7 +3876,13 @@ pmap_setlwpvm(struct lwp *lp, struct vmspace *newvm)
 #ifdef SMP
 
 /*
- * Called when switching to a locked pmap
+ * Called when switching to a locked pmap, used to interlock against pmaps
+ * undergoing modifications to prevent us from activating the MMU for the
+ * target pmap until all such modifications have completed.  We have to do
+ * this because the thread making the modifications has already set up its
+ * SMP synchronization mask.
+ *
+ * No requirements.
  */
 void
 pmap_interlock_wait(struct vmspace *vm)
@@ -3885,11 +3891,12 @@ pmap_interlock_wait(struct vmspace *vm)
 
        if (pmap->pm_active & CPUMASK_LOCK) {
                DEBUG_PUSH_INFO("pmap_interlock_wait");
+               crit_enter();
                while (pmap->pm_active & CPUMASK_LOCK) {
-                       cpu_pause();
                        cpu_ccfence();
                        lwkt_process_ipiq();
                }
+               crit_exit();
                DEBUG_POP_INFO();
        }
 }