From: Oliver Kurth Date: Fri, 2 Nov 2018 22:28:18 +0000 (-0700) Subject: Solaris: Synchronize between vmxnet3_tx and vmxnet3 X-Git-Tag: stable-11.0.0~345 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f17721b0815a153e8a1d9b95492792c07594309d;p=thirdparty%2Fopen-vm-tools.git Solaris: Synchronize between vmxnet3_tx and vmxnet3 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. --- diff --git a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c index a2675e809..eadae642c 100644 --- a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c +++ b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_main.c @@ -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); diff --git a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c index e0cf2c5ab..34a0c49dc 100644 --- a/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c +++ b/open-vm-tools/modules/solaris/vmxnet3/vmxnet3_tx.c @@ -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;