]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Solaris: Synchronize between vmxnet3_tx and vmxnet3
authorOliver Kurth <okurth@vmware.com>
Fri, 2 Nov 2018 22:28:18 +0000 (15:28 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 2 Nov 2018 22:28:18 +0000 (15:28 -0700)
Vmxnet3 driver on Solaris is not properly synchronized
between vmxnet3_tx and vmxnet3_stop. When the driver
receives a stop event from the device, it doesn't
synchronize with the TX function invoked from the
networking stack before it releases the TXQ resources.
Thus, when the TX function vmxnet3_tx() is executed,
and a stop event/interrupt comes in, the TXQ may
suddenly disappear while vmxnet3_tx is still accessing
the descriptors, thus the guest OS crashes.

open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c
open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c

index a2675e8094ff42845493d14a69b4aea5ea1604a8..eadae642c06959bf0dbd8609afbcb952c77fb9a1 100644 (file)
@@ -771,14 +771,16 @@ vmxnet3_stop(void *data)
    VMXNET3_DEBUG(dp, 1, "stop()\n");
 
    /*
-    * Take the 2 locks related to asynchronous events.
+    * Take the 3 locks related to asynchronous events.
     * These events should always check dp->devEnabled before poking dp.
     */
    mutex_enter(&dp->intrLock);
    mutex_enter(&dp->rxPoolLock);
+   mutex_enter(&dp->txLock);
    VMXNET3_BAR0_PUT32(dp, VMXNET3_REG_IMR, 1);
    dp->devEnabled = B_FALSE;
    VMXNET3_BAR1_PUT32(dp, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV);
+   mutex_exit(&dp->txLock);
    mutex_exit(&dp->rxPoolLock);
    mutex_exit(&dp->intrLock);
 
index e0cf2c5ab842f3e2318facfbda082b1b16e952fb..34a0c49dc4f8b214d0f026dd0082abbd5522dd67 100644 (file)
@@ -204,7 +204,7 @@ vmxnet3_tx_one(vmxnet3_softc_t *dp,
    uint8_t sopGen, curGen;
    mblk_t *mblk;
 
-   mutex_enter(&dp->txLock);
+   ASSERT(mutex_owned(&dp->txLock));
 
    sopIdx = eopIdx = cmdRing->next2fill;
    sopGen = cmdRing->gen;
@@ -343,8 +343,6 @@ error:
    }
 
 done:
-   mutex_exit(&dp->txLock);
-
    return ret;
 }
 
@@ -375,6 +373,10 @@ vmxnet3_tx(void *data, mblk_t *mps)
    mblk_t *mp;
 
    ASSERT(mps != NULL);
+   mutex_enter(&dp->txLock);
+   if (!dp->devEnabled) {
+      goto done;
+   }
 
    do {
       vmxnet3_offload_t ol;
@@ -445,11 +447,12 @@ vmxnet3_tx(void *data, mblk_t *mps)
    }
 
    /* Notify the device */
-   mutex_enter(&dp->txLock);
    if (txqCtrl->txNumDeferred >= txqCtrl->txThreshold) {
       txqCtrl->txNumDeferred = 0;
       VMXNET3_BAR0_PUT32(dp, VMXNET3_REG_TXPROD, cmdRing->next2fill);
    }
+
+done:
    mutex_exit(&dp->txLock);
 
    return mps;