]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
VMCI queue pair quiesce support
authorVMware, Inc <>
Mon, 26 Sep 2011 18:41:03 +0000 (11:41 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Mon, 26 Sep 2011 18:41:03 +0000 (11:41 -0700)
This change allows the host side of a queue pair to deal with a VM
being temporarily stunned in two ways; it may either block in the
queue pair enqueue or dequeue operation until the VM becomes available
or it can use a non-blocking behaviour, where the operation will
return a would block error message.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/vmci_defs.h
open-vm-tools/modules/linux/shared/vmci_call_defs.h
open-vm-tools/modules/linux/shared/vmci_defs.h
open-vm-tools/modules/linux/vmci/common/vmciContext.c
open-vm-tools/modules/linux/vmci/common/vmciContext.h
open-vm-tools/modules/linux/vmci/common/vmciQPair.c
open-vm-tools/modules/linux/vmci/common/vmciQueuePair.c
open-vm-tools/modules/linux/vmci/common/vmciQueuePair.h
open-vm-tools/modules/linux/vmci/linux/vmciKernelIf.c
open-vm-tools/modules/linux/vmci/linux/vmci_version.h
open-vm-tools/modules/linux/vmci/shared/vmciQueue.h

index 0c96ea34aeda7fe47a23e4374fdea9dc5fcf2840..5a9c966b04d1624bfc88f107bc4c51c1c2f82caf 100644 (file)
@@ -296,6 +296,8 @@ static const VMCIHandle VMCI_INVALID_HANDLE = {VMCI_INVALID_ID,
 #define VMCI_ERROR_BUSMEM_INVALIDATION   (-37)
 #define VMCI_ERROR_MODULE_NOT_LOADED     (-38)
 #define VMCI_ERROR_DEVICE_NOT_FOUND      (-39)
+#define VMCI_ERROR_QUEUEPAIR_NOT_READY   (-40)
+#define VMCI_ERROR_WOULD_BLOCK           (-41)
 
 /* VMCI clients should return error code withing this range */
 #define VMCI_ERROR_CLIENT_MIN     (-500)
index e85807c59b68da901e4c45d6cf31487ab9a04f09..b3d70a08b060aab9ad5b4ab7400a624d3d7e3347 100644 (file)
@@ -279,8 +279,10 @@ VMCIEventMsgPayload(VMCIEventMsg *eMsg) // IN:
 /* Flags for VMCI QueuePair API. */
 #define VMCI_QPFLAG_ATTACH_ONLY 0x1 /* Fail alloc if QP not created by peer. */
 #define VMCI_QPFLAG_LOCAL       0x2 /* Only allow attaches from local context. */
+#define VMCI_QPFLAG_NONBLOCK    0x4 /* Host won't block when guest is quiesced. */
 /* Update the following (bitwise OR flags) while adding new flags. */
-#define VMCI_QP_ALL_FLAGS       (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QPFLAG_LOCAL)
+#define VMCI_QP_ALL_FLAGS       (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QPFLAG_LOCAL | \
+                                 VMCI_QPFLAG_NONBLOCK)
 
 /*
  * Structs used for QueuePair alloc and detach messages.  We align fields of
index b07d7e85ad9228d2d04368ebfb4b51c489149b48..68b2273a54ad2f7866c5accd68c01efb49bf0114 100644 (file)
@@ -296,6 +296,8 @@ static const VMCIHandle VMCI_INVALID_HANDLE = {VMCI_INVALID_ID,
 #define VMCI_ERROR_BUSMEM_INVALIDATION   (-37)
 #define VMCI_ERROR_MODULE_NOT_LOADED     (-38)
 #define VMCI_ERROR_DEVICE_NOT_FOUND      (-39)
+#define VMCI_ERROR_QUEUEPAIR_NOT_READY   (-40)
+#define VMCI_ERROR_WOULD_BLOCK           (-41)
 
 /* VMCI clients should return error code withing this range */
 #define VMCI_ERROR_CLIENT_MIN     (-500)
index 5a7a7d62cd9cd18acff818b9a58e79e29bf7294e..c89e462bfee38c2bff5012e210bf4d9aa6f68d45 100644 (file)
@@ -2435,6 +2435,51 @@ VMCIContext_SupportsHostQP(VMCIContext *context)    // IN: Context structure
 }
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContext_RegisterGuestMem --
+ *
+ *      Tells the context that guest memory is available for access.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      Notifies host side endpoints of queue pairs that the queue pairs
+ *      can be accessed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+VMCIContext_RegisterGuestMem(VMCIContext *context) // IN: Context structure
+{
+#ifdef VMKERNEL
+   uint32 numQueuePairs;
+   uint32 cur;
+
+   VMCIQPBroker_Lock();
+   numQueuePairs = VMCIHandleArray_GetSize(context->queuePairArray);
+   for (cur = 0; cur < numQueuePairs; cur++) {
+      VMCIHandle handle;
+      handle = VMCIHandleArray_GetEntry(context->queuePairArray, cur);
+      if (!VMCI_HANDLE_EQUAL(handle, VMCI_INVALID_HANDLE)) {
+         int res;
+
+         res = VMCIQPBroker_Map(handle, context, NULL);
+         if (res < VMCI_SUCCESS) {
+            VMCI_WARNING(("Failed to map guest memory for queue pair "
+                          "(handle=0x%x:0x%x, res=%d).\n",
+                          handle.context, handle.resource, res));
+         }
+      }
+   }
+   VMCIQPBroker_Unlock();
+#endif
+}
+
+
 /*
  *----------------------------------------------------------------------
  *
index 60bcdf610b3f300f95e9db3e3a73e8bdeb585bce..6cc781092cf365640b89987cb6ccd5e093a4e60c 100644 (file)
@@ -91,6 +91,7 @@ int VMCIContext_GetCheckpointState(VMCIId contextID, uint32 cptType,
                                    uint32 *numCIDs, char **cptBufPtr);
 int VMCIContext_SetCheckpointState(VMCIId contextID, uint32 cptType,
                                    uint32 numCIDs, char *cptBuf);
+void VMCIContext_RegisterGuestMem(VMCIContext *context);
 void VMCIContext_ReleaseGuestMem(VMCIContext *context, VMCIGuestMemID gid);
 
 #ifndef VMX86_SERVER
index 4c7ebedc752e8e0103cb1b4752938a3335651d2d..b48d85e58ab70d05b1971b1ac74156bdb91126d6 100644 (file)
@@ -69,6 +69,7 @@
 #include "vmciQueuePair.h"
 #include "vmciRoute.h"
 
+
 /*
  * VMCIQPair
  *
@@ -85,12 +86,110 @@ struct VMCIQPair {
    uint32 flags;
    VMCIPrivilegeFlags privFlags;
    Bool guestEndpoint;
+   uint32 blocked;
+   VMCIEvent event;
 };
 
 static int VMCIQPairMapQueueHeaders(VMCIQueue *produceQ, VMCIQueue *consumeQ);
+static int VMCIQPairGetQueueHeaders(const VMCIQPair *qpair,
+                                    VMCIQueueHeader **produceQHeader,
+                                    VMCIQueueHeader **consumeQHeader);
+static int VMCIQPairWakeupCB(void *clientData);
+static int VMCIQPairReleaseMutexCB(void *clientData);
+static Bool VMCIQPairWaitForReadyQueue(VMCIQPair *qpair);
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMCIQPair_Lock --
+ *
+ *      Helper routine that will lock the QPair before subsequent operations.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      May block.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+VMCIQPairLock(const VMCIQPair *qpair) // IN
+{
+#if !defined VMX86_VMX
+   VMCI_AcquireQueueMutex(qpair->produceQ);
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMCIQPair_Unlock --
+ *
+ *      Helper routine that will unlock the QPair after various operations.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+VMCIQPairUnlock(const VMCIQPair *qpair) // IN
+{
+#if !defined VMX86_VMX
+   VMCI_ReleaseQueueMutex(qpair->produceQ);
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMCIQPairGetQueueHeaders --
+ *
+ *      Helper routine that will retrieve the produce and consume
+ *      headers of a given queue pair. If the guest memory of the
+ *      queue pair is currently not available, the saved queue headers
+ *      will be returned, if these are available.
+ *
+ * Results:
+ *      VMCI_SUCCESS if either current or saved queue headers are found.
+ *      Appropriate error code otherwise.
+ *
+ * Side effects:
+ *      May block.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMCIQPairGetQueueHeaders(const VMCIQPair *qpair,            // IN
+                         VMCIQueueHeader **produceQHeader,  // OUT
+                         VMCIQueueHeader **consumeQHeader)  // OUT
+{
+   int result;
+
+   result = VMCIQPairMapQueueHeaders(qpair->produceQ, qpair->consumeQ);
+   if (result == VMCI_SUCCESS) {
+      *produceQHeader = qpair->produceQ->qHeader;
+      *consumeQHeader = qpair->consumeQ->qHeader;
+   } else if (qpair->produceQ->savedHeader && qpair->consumeQ->savedHeader) {
+      ASSERT(!qpair->guestEndpoint);
+      *produceQHeader = qpair->produceQ->savedHeader;
+      *consumeQHeader = qpair->consumeQ->savedHeader;
+      result = VMCI_SUCCESS;
+   }
+
+   return result;
+}
 
-#define VMCI_QPAIR_NO_QUEUE(_qp) (VMCIQPairMapQueueHeaders(_qp->produceQ, \
-                                  _qp->consumeQ) != VMCI_SUCCESS)
 
 /*
  *-----------------------------------------------------------------------------
@@ -104,7 +203,7 @@ static int VMCIQPairMapQueueHeaders(VMCIQueue *produceQ, VMCIQueue *consumeQ);
  *      VMCI_SUCCESS if queues were validated, appropriate error code otherwise.
  *
  * Side effects:
- *      Windows blocking call.
+ *      May attempt to map in guest memory.
  *
  *-----------------------------------------------------------------------------
  */
@@ -118,7 +217,11 @@ VMCIQPairMapQueueHeaders(VMCIQueue *produceQ, // IN
    if (NULL == produceQ->qHeader || NULL == consumeQ->qHeader) {
       result = VMCIHost_MapQueueHeaders(produceQ, consumeQ);
       if (result < VMCI_SUCCESS) {
-         return result;
+         if (produceQ->savedHeader && consumeQ->savedHeader) {
+            return VMCI_ERROR_QUEUEPAIR_NOT_READY;
+         } else {
+            return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
+         }
       }
    }
 
@@ -126,6 +229,103 @@ VMCIQPairMapQueueHeaders(VMCIQueue *produceQ, // IN
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMCIQPairWakeupCB --
+ *
+ *      Callback from VMCI queue pair broker indicating that a queue
+ *      pair that was previously not ready, now either is ready or
+ *      gone forever.
+ *
+ * Results:
+ *      VMCI_SUCCESS always.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMCIQPairWakeupCB(void *clientData)
+{
+   VMCIQPair *qpair = (VMCIQPair *)clientData;
+   ASSERT(qpair);
+
+   VMCIQPairLock(qpair);
+   while (qpair->blocked > 0) {
+      qpair->blocked--;
+      VMCI_SignalEvent(&qpair->event);
+   }
+   VMCIQPairUnlock(qpair);
+
+   return VMCI_SUCCESS;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMCIQPairReleaseMutexCB --
+ *
+ *      Callback from VMCI_WaitOnEvent releasing the queue pair mutex
+ *      protecting the queue pair header state.
+ *
+ * Results:
+ *      0 always.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMCIQPairReleaseMutexCB(void *clientData)
+{
+   VMCIQPair *qpair = (VMCIQPair *)clientData;
+   ASSERT(qpair);
+   VMCIQPairUnlock(qpair);
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMCIQPairWaitForReadyQueue --
+ *
+ *      Makes the calling thread wait for the queue pair to become
+ *      ready for host side access.
+ *
+ * Results:
+ *     TRUE when thread is woken up after queue pair state change.
+ *     FALSE otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+VMCIQPairWaitForReadyQueue(VMCIQPair *qpair)
+{
+   if (UNLIKELY(qpair->guestEndpoint)) {
+      ASSERT(FALSE);
+      return FALSE;
+   }
+   if (qpair->flags & VMCI_QPFLAG_NONBLOCK) {
+      return FALSE;
+   }
+   qpair->blocked++;
+   VMCI_WaitOnEvent(&qpair->event, VMCIQPairReleaseMutexCB, qpair);
+   VMCIQPairLock(qpair);
+   return TRUE;
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -162,6 +362,8 @@ VMCIQPair_Alloc(VMCIQPair **qpair,            // OUT
    VMCIHandle src = VMCI_INVALID_HANDLE;
    VMCIHandle dst = VMCI_MAKE_HANDLE(peer, VMCI_INVALID_ID);
    VMCIRoute route;
+   VMCIEventReleaseCB wakeupCB;
+   void *clientData;
 
    /*
     * Restrict the size of a queuepair.  The device already enforces a limit
@@ -195,7 +397,6 @@ VMCIQPair_Alloc(VMCIQPair **qpair,            // OUT
    myQPair->peer = peer;
    myQPair->flags = flags;
    myQPair->privFlags = privFlags;
-
    retval = VMCI_Route(&src, &dst, FALSE, &route);
    if (retval < VMCI_SUCCESS) {
       if (VMCI_GuestPersonalityActive()) {
@@ -205,8 +406,15 @@ VMCIQPair_Alloc(VMCIQPair **qpair,            // OUT
       }
    }
 
+   wakeupCB = clientData = NULL;
    if (VMCI_ROUTE_AS_HOST == route) {
       myQPair->guestEndpoint = FALSE;
+      if (!(flags & VMCI_QPFLAG_LOCAL)) {
+         myQPair->blocked = 0;
+         VMCI_CreateEvent(&myQPair->event);
+         wakeupCB = VMCIQPairWakeupCB;
+         clientData = (void *)myQPair;
+      }
    } else {
       myQPair->guestEndpoint = TRUE;
    }
@@ -219,9 +427,14 @@ VMCIQPair_Alloc(VMCIQPair **qpair,            // OUT
                                 myQPair->peer,
                                 myQPair->flags,
                                 myQPair->privFlags,
-                                myQPair->guestEndpoint);
+                                myQPair->guestEndpoint,
+                                wakeupCB,
+                                clientData);
 
    if (retval < VMCI_SUCCESS) {
+      if (VMCI_ROUTE_AS_HOST == route && !(flags & VMCI_QPFLAG_LOCAL)) {
+         VMCI_DestroyEvent(&myQPair->event);
+      }
       VMCI_FreeKernelMem(myQPair, sizeof *myQPair);
       return retval;
    }
@@ -273,6 +486,9 @@ VMCIQPair_Detach(VMCIQPair **qpair) // IN/OUT
     * there isn't much the caller can do, and we don't want to leak.
     */
 
+   if (!(oldQPair->guestEndpoint || (oldQPair->flags & VMCI_QPFLAG_LOCAL))) {
+      VMCI_DestroyEvent(&oldQPair->event);
+   }
    memset(oldQPair, 0, sizeof *oldQPair);
    oldQPair->handle = VMCI_INVALID_HANDLE;
    oldQPair->peer = VMCI_INVALID_ID;
@@ -283,68 +499,6 @@ VMCIQPair_Detach(VMCIQPair **qpair) // IN/OUT
 }
 
 
-/*
- * "Windows blocking call."
- *
- *      Note that on the Windows platform, kernel module clients may
- *      block when calling into any these rouintes.  The reason is
- *      that a mutex has to be acquired in order to view/modify the
- *      VMCIQueue structure fields: pointers, handle, and buffer data.
- *      However, other platforms don't require the acquisition of a
- *      mutex and thus don't block.
- */
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * VMCIQPair_Lock --
- *
- *      Helper routine that will lock the QPair before subsequent operations.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      Windows blocking call.
- *
- *-----------------------------------------------------------------------------
- */
-
-static INLINE void
-VMCIQPairLock(const VMCIQPair *qpair) // IN
-{
-#if !defined VMX86_VMX
-   VMCI_AcquireQueueMutex(qpair->produceQ);
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * VMCIQPair_Unlock --
- *
- *      Helper routine that will unlock the QPair after various operations.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static INLINE void
-VMCIQPairUnlock(const VMCIQPair *qpair) // IN
-{
-#if !defined VMX86_VMX
-   VMCI_ReleaseQueueMutex(qpair->produceQ);
-#endif
-}
-
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -369,6 +523,8 @@ VMCIQPair_GetProduceIndexes(const VMCIQPair *qpair, // IN
                             uint64 *producerTail,   // OUT
                             uint64 *consumerHead)   // OUT
 {
+   VMCIQueueHeader *produceQHeader;
+   VMCIQueueHeader *consumeQHeader;
    int result;
 
    if (!qpair) {
@@ -376,17 +532,11 @@ VMCIQPair_GetProduceIndexes(const VMCIQPair *qpair, // IN
    }
 
    VMCIQPairLock(qpair);
-
-   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
-      result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
-   } else {
-      VMCIQueueHeader_GetPointers(qpair->produceQ->qHeader,
-                                  qpair->consumeQ->qHeader,
-                                  producerTail,
-                                  consumerHead);
-      result = VMCI_SUCCESS;
+   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
+   if (result == VMCI_SUCCESS) {
+      VMCIQueueHeader_GetPointers(produceQHeader, consumeQHeader,
+                                  producerTail, consumerHead);
    }
-
    VMCIQPairUnlock(qpair);
 
    if (result == VMCI_SUCCESS &&
@@ -423,6 +573,8 @@ VMCIQPair_GetConsumeIndexes(const VMCIQPair *qpair, // IN
                             uint64 *consumerTail,   // OUT
                             uint64 *producerHead)   // OUT
 {
+   VMCIQueueHeader *produceQHeader;
+   VMCIQueueHeader *consumeQHeader;
    int result;
 
    if (!qpair) {
@@ -430,17 +582,11 @@ VMCIQPair_GetConsumeIndexes(const VMCIQPair *qpair, // IN
    }
 
    VMCIQPairLock(qpair);
-
-   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
-      result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
-   } else {
-      VMCIQueueHeader_GetPointers(qpair->consumeQ->qHeader,
-                                  qpair->produceQ->qHeader,
-                                  consumerTail,
-                                  producerHead);
-      result = VMCI_SUCCESS;
+   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
+   if (result == VMCI_SUCCESS) {
+      VMCIQueueHeader_GetPointers(consumeQHeader, produceQHeader,
+                                  consumerTail, producerHead);
    }
-
    VMCIQPairUnlock(qpair);
 
    if (result == VMCI_SUCCESS &&
@@ -477,6 +623,8 @@ VMCI_EXPORT_SYMBOL(VMCIQPair_ProduceFreeSpace)
 int64
 VMCIQPair_ProduceFreeSpace(const VMCIQPair *qpair) // IN
 {
+   VMCIQueueHeader *produceQHeader;
+   VMCIQueueHeader *consumeQHeader;
    int64 result;
 
    if (!qpair) {
@@ -484,15 +632,13 @@ VMCIQPair_ProduceFreeSpace(const VMCIQPair *qpair) // IN
    }
 
    VMCIQPairLock(qpair);
-
-   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
-      result = 0;
-   } else {
-      result = VMCIQueueHeader_FreeSpace(qpair->produceQ->qHeader,
-                                         qpair->consumeQ->qHeader,
+   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
+   if (result == VMCI_SUCCESS) {
+      result = VMCIQueueHeader_FreeSpace(produceQHeader, consumeQHeader,
                                          qpair->produceQSize);
+   } else {
+      result = 0;
    }
-
    VMCIQPairUnlock(qpair);
 
    return result;
@@ -524,6 +670,8 @@ VMCI_EXPORT_SYMBOL(VMCIQPair_ConsumeFreeSpace)
 int64
 VMCIQPair_ConsumeFreeSpace(const VMCIQPair *qpair) // IN
 {
+   VMCIQueueHeader *produceQHeader;
+   VMCIQueueHeader *consumeQHeader;
    int64 result;
 
    if (!qpair) {
@@ -531,15 +679,13 @@ VMCIQPair_ConsumeFreeSpace(const VMCIQPair *qpair) // IN
    }
 
    VMCIQPairLock(qpair);
-
-   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
-      result = 0;
-   } else {
-      result = VMCIQueueHeader_FreeSpace(qpair->consumeQ->qHeader,
-                                         qpair->produceQ->qHeader,
+   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
+   if (result == VMCI_SUCCESS) {
+      result = VMCIQueueHeader_FreeSpace(consumeQHeader, produceQHeader,
                                          qpair->consumeQSize);
+   } else {
+      result = 0;
    }
-
    VMCIQPairUnlock(qpair);
 
    return result;
@@ -571,6 +717,8 @@ VMCI_EXPORT_SYMBOL(VMCIQPair_ProduceBufReady)
 int64
 VMCIQPair_ProduceBufReady(const VMCIQPair *qpair) // IN
 {
+   VMCIQueueHeader *produceQHeader;
+   VMCIQueueHeader *consumeQHeader;
    int64 result;
 
    if (!qpair) {
@@ -578,15 +726,13 @@ VMCIQPair_ProduceBufReady(const VMCIQPair *qpair) // IN
    }
 
    VMCIQPairLock(qpair);
-
-   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
-      result = 0;
-   } else {
-      result = VMCIQueueHeader_BufReady(qpair->produceQ->qHeader,
-                                        qpair->consumeQ->qHeader,
+   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
+   if (result == VMCI_SUCCESS) {
+      result = VMCIQueueHeader_BufReady(produceQHeader, consumeQHeader,
                                         qpair->produceQSize);
+   } else {
+      result = 0;
    }
-
    VMCIQPairUnlock(qpair);
 
    return result;
@@ -617,6 +763,8 @@ VMCI_EXPORT_SYMBOL(VMCIQPair_ConsumeBufReady)
 int64
 VMCIQPair_ConsumeBufReady(const VMCIQPair *qpair) // IN
 {
+   VMCIQueueHeader *produceQHeader;
+   VMCIQueueHeader *consumeQHeader;
    int64 result;
 
    if (!qpair) {
@@ -624,15 +772,13 @@ VMCIQPair_ConsumeBufReady(const VMCIQPair *qpair) // IN
    }
 
    VMCIQPairLock(qpair);
-
-   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
-      result = 0;
-   } else {
-      result = VMCIQueueHeader_BufReady(qpair->consumeQ->qHeader,
-                                        qpair->produceQ->qHeader,
+   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
+   if (result == VMCI_SUCCESS) {
+      result = VMCIQueueHeader_BufReady(consumeQHeader, produceQHeader,
                                         qpair->consumeQSize);
+   } else {
+      result = 0;
    }
-
    VMCIQPairUnlock(qpair);
 
    return result;
@@ -684,8 +830,9 @@ EnqueueLocked(VMCIQueue *produceQ,                   // IN
       return (ssize_t) bufSize;
    }
 
-   if (UNLIKELY(VMCIQPairMapQueueHeaders(produceQ, consumeQ) != VMCI_SUCCESS)) {
-      return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
+   result = VMCIQPairMapQueueHeaders(produceQ, consumeQ);
+   if (UNLIKELY(result != VMCI_SUCCESS)) {
+      return result;
    }
 #endif
 
@@ -763,8 +910,9 @@ DequeueLocked(VMCIQueue *produceQ,                        // IN
    ssize_t result;
 
 #if !defined VMX86_VMX
-   if (UNLIKELY(VMCIQPairMapQueueHeaders(produceQ, consumeQ) != VMCI_SUCCESS)) {
-      return VMCI_ERROR_QUEUEPAIR_NODATA;
+   result = VMCIQPairMapQueueHeaders(produceQ, consumeQ);
+   if (UNLIKELY(result != VMCI_SUCCESS)) {
+      return result;
    }
 #endif
 
@@ -839,13 +987,20 @@ VMCIQPair_Enqueue(VMCIQPair *qpair,        // IN
 
    VMCIQPairLock(qpair);
 
-   result = EnqueueLocked(qpair->produceQ,
-                          qpair->consumeQ,
-                          qpair->produceQSize,
-                          buf, bufSize, bufType,
-                          qpair->flags & VMCI_QPFLAG_LOCAL?
-                          VMCIMemcpyToQueueLocal:
-                          VMCIMemcpyToQueue);
+   do {
+      result = EnqueueLocked(qpair->produceQ,
+                             qpair->consumeQ,
+                             qpair->produceQSize,
+                             buf, bufSize, bufType,
+                             qpair->flags & VMCI_QPFLAG_LOCAL?
+                             VMCIMemcpyToQueueLocal:
+                             VMCIMemcpyToQueue);
+      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
+         if (!VMCIQPairWaitForReadyQueue(qpair)) {
+            result = VMCI_ERROR_WOULD_BLOCK;
+         }
+      }
+   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
 
    VMCIQPairUnlock(qpair);
 
@@ -885,14 +1040,21 @@ VMCIQPair_Dequeue(VMCIQPair *qpair,        // IN
 
    VMCIQPairLock(qpair);
 
-   result = DequeueLocked(qpair->produceQ,
-                          qpair->consumeQ,
-                          qpair->consumeQSize,
-                          buf, bufSize, bufType,
-                          qpair->flags & VMCI_QPFLAG_LOCAL?
-                          VMCIMemcpyFromQueueLocal:
-                          VMCIMemcpyFromQueue,
-                          TRUE);
+   do {
+      result = DequeueLocked(qpair->produceQ,
+                             qpair->consumeQ,
+                             qpair->consumeQSize,
+                             buf, bufSize, bufType,
+                             qpair->flags & VMCI_QPFLAG_LOCAL?
+                             VMCIMemcpyFromQueueLocal:
+                             VMCIMemcpyFromQueue,
+                             TRUE);
+      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
+         if (!VMCIQPairWaitForReadyQueue(qpair)) {
+            result = VMCI_ERROR_WOULD_BLOCK;
+         }
+      }
+   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
 
    VMCIQPairUnlock(qpair);
 
@@ -933,14 +1095,21 @@ VMCIQPair_Peek(VMCIQPair *qpair,    // IN
 
    VMCIQPairLock(qpair);
 
-   result = DequeueLocked(qpair->produceQ,
-                          qpair->consumeQ,
-                          qpair->consumeQSize,
-                          buf, bufSize, bufType,
-                          qpair->flags & VMCI_QPFLAG_LOCAL?
-                          VMCIMemcpyFromQueueLocal:
-                          VMCIMemcpyFromQueue,
-                          FALSE);
+   do {
+      result = DequeueLocked(qpair->produceQ,
+                             qpair->consumeQ,
+                             qpair->consumeQSize,
+                             buf, bufSize, bufType,
+                             qpair->flags & VMCI_QPFLAG_LOCAL?
+                             VMCIMemcpyFromQueueLocal:
+                             VMCIMemcpyFromQueue,
+                             FALSE);
+      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
+         if (!VMCIQPairWaitForReadyQueue(qpair)) {
+            result = VMCI_ERROR_WOULD_BLOCK;
+         }
+      }
+   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
 
    VMCIQPairUnlock(qpair);
 
@@ -984,11 +1153,18 @@ VMCIQPair_EnqueueV(VMCIQPair *qpair,        // IN
 
    VMCIQPairLock(qpair);
 
-   result = EnqueueLocked(qpair->produceQ,
-                          qpair->consumeQ,
-                          qpair->produceQSize,
-                          iov, iovSize, bufType,
-                          VMCIMemcpyToQueueV);
+   do {
+      result = EnqueueLocked(qpair->produceQ,
+                             qpair->consumeQ,
+                             qpair->produceQSize,
+                             iov, iovSize, bufType,
+                             VMCIMemcpyToQueueV);
+      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
+         if (!VMCIQPairWaitForReadyQueue(qpair)) {
+            result = VMCI_ERROR_WOULD_BLOCK;
+         }
+      }
+   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
 
    VMCIQPairUnlock(qpair);
 
@@ -1028,12 +1204,19 @@ VMCIQPair_DequeueV(VMCIQPair *qpair,         // IN
       return VMCI_ERROR_INVALID_ARGS;
    }
 
-   result = DequeueLocked(qpair->produceQ,
-                          qpair->consumeQ,
-                          qpair->consumeQSize,
-                          iov, iovSize, bufType,
-                          VMCIMemcpyFromQueueV,
-                          TRUE);
+   do {
+      result = DequeueLocked(qpair->produceQ,
+                             qpair->consumeQ,
+                             qpair->consumeQSize,
+                             iov, iovSize, bufType,
+                             VMCIMemcpyFromQueueV,
+                             TRUE);
+      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
+         if (!VMCIQPairWaitForReadyQueue(qpair)) {
+            result = VMCI_ERROR_WOULD_BLOCK;
+         }
+      }
+   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
 
    VMCIQPairUnlock(qpair);
 
@@ -1074,12 +1257,19 @@ VMCIQPair_PeekV(VMCIQPair *qpair,           // IN
 
    VMCIQPairLock(qpair);
 
-   result = DequeueLocked(qpair->produceQ,
-                          qpair->consumeQ,
-                          qpair->consumeQSize,
-                          iov, iovSize, bufType,
-                          VMCIMemcpyFromQueueV,
-                          FALSE);
+   do {
+      result = DequeueLocked(qpair->produceQ,
+                             qpair->consumeQ,
+                             qpair->consumeQSize,
+                             iov, iovSize, bufType,
+                             VMCIMemcpyFromQueueV,
+                             FALSE);
+      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
+         if (!VMCIQPairWaitForReadyQueue(qpair)) {
+            result = VMCI_ERROR_WOULD_BLOCK;
+         }
+      }
+   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
 
    VMCIQPairUnlock(qpair);
 
index cb988fab726cae1c4540c24a51dd85557628435a..80f9760d108954bb8fec7e199d22ea25eb2da479 100644 (file)
@@ -158,6 +158,10 @@ typedef struct QPBrokerEntry {
    Bool                 vmciPageFiles;  // Created by VMX using VMCI page files
    VMCIQueue           *produceQ;
    VMCIQueue           *consumeQ;
+   VMCIQueueHeader      savedProduceQ;
+   VMCIQueueHeader      savedConsumeQ;
+   VMCIEventReleaseCB   wakeupCB;
+   void                *clientData;
    void                *localMem; // Kernel memory for local queue pair
 } QPBrokerEntry;
 
@@ -206,6 +210,8 @@ static int VMCIQPBrokerAllocInt(VMCIHandle handle, VMCIId peer,
                                 uint64 consumeSize,
                                 QueuePairPageStore *pageStore,
                                 VMCIContext *context,
+                                VMCIEventReleaseCB wakeupCB,
+                                void *clientData,
                                 QPBrokerEntry **ent,
                                 Bool *swap);
 static int VMCIQPBrokerAttach(QPBrokerEntry *entry,
@@ -216,6 +222,8 @@ static int VMCIQPBrokerAttach(QPBrokerEntry *entry,
                               uint64 consumeSize,
                               QueuePairPageStore *pageStore,
                               VMCIContext *context,
+                              VMCIEventReleaseCB wakeupCB,
+                              void *clientData,
                               QPBrokerEntry **ent);
 static int VMCIQPBrokerCreate(VMCIHandle handle,
                               VMCIId peer,
@@ -225,14 +233,21 @@ static int VMCIQPBrokerCreate(VMCIHandle handle,
                               uint64 consumeSize,
                               QueuePairPageStore *pageStore,
                               VMCIContext *context,
+                              VMCIEventReleaseCB wakeupCB,
+                              void *clientData,
                               QPBrokerEntry **ent);
 static int VMCIQueuePairAllocHostWork(VMCIHandle *handle, VMCIQueue **produceQ,
                                       uint64 produceSize, VMCIQueue **consumeQ,
                                       uint64 consumeSize,
                                       VMCIId peer, uint32 flags,
-                                      VMCIPrivilegeFlags privFlags);
+                                      VMCIPrivilegeFlags privFlags,
+                                      VMCIEventReleaseCB wakeupCB,
+                                      void *clientData);
 static int VMCIQueuePairDetachHostWork(VMCIHandle handle);
 
+static int QueuePairSaveHeaders(QPBrokerEntry *entry);
+static void QueuePairResetSavedHeaders(QPBrokerEntry *entry);
+
 #if !defined(VMKERNEL)
 
 static int QueuePairNotifyPeerLocal(Bool attach, VMCIHandle handle);
@@ -286,7 +301,9 @@ VMCIQueuePair_Alloc(VMCIHandle *handle,           // IN/OUT
                     VMCIId     peer,              // IN
                     uint32     flags,             // IN
                     VMCIPrivilegeFlags privFlags, // IN
-                    Bool       guestEndpoint)     // IN
+                    Bool       guestEndpoint,     // IN
+                    VMCIEventReleaseCB wakeupCB,  // IN
+                    void *clientData)             // IN
 {
    if (!handle || !produceQ || !consumeQ || (!produceSize && !consumeSize) ||
        (flags & ~VMCI_QP_ALL_FLAGS)) {
@@ -302,7 +319,8 @@ VMCIQueuePair_Alloc(VMCIHandle *handle,           // IN/OUT
 #endif
    } else {
       return VMCIQueuePairAllocHostWork(handle, produceQ, produceSize, consumeQ,
-                                        consumeSize, peer, flags, privFlags);
+                                        consumeSize, peer, flags, privFlags,
+                                        wakeupCB, clientData);
    }
 }
 
@@ -699,7 +717,8 @@ VMCIQPBroker_Alloc(VMCIHandle handle,             // IN
 {
    return VMCIQPBrokerAllocInt(handle, peer, flags, privFlags,
                                produceSize, consumeSize,
-                               pageStore, context, NULL, NULL);
+                               pageStore, context, NULL, NULL,
+                               NULL, NULL);
 }
 
 
@@ -801,7 +820,9 @@ VMCIQueuePairAllocHostWork(VMCIHandle *handle,           // IN/OUT
                            uint64 consumeSize,           // IN
                            VMCIId peer,                  // IN
                            uint32 flags,                 // IN
-                           VMCIPrivilegeFlags privFlags) // IN
+                           VMCIPrivilegeFlags privFlags, // IN
+                           VMCIEventReleaseCB wakeupCB,  // IN
+                           void *clientData)             // IN
 {
    VMCIContext *context;
    QPBrokerEntry *entry;
@@ -822,7 +843,8 @@ VMCIQueuePairAllocHostWork(VMCIHandle *handle,           // IN/OUT
    entry = NULL;
    VMCIQPBroker_Lock();
    result = VMCIQPBrokerAllocInt(*handle, peer, flags, privFlags, produceSize,
-                                 consumeSize, NULL, context, &entry, &swap);
+                                 consumeSize, NULL, context, wakeupCB, clientData,
+                                 &entry, &swap);
    if (result == VMCI_SUCCESS) {
       if (swap) {
          /*
@@ -908,6 +930,8 @@ VMCIQPBrokerAllocInt(VMCIHandle handle,             // IN
                      uint64 consumeSize,            // IN
                      QueuePairPageStore *pageStore, // IN/OUT
                      VMCIContext *context,          // IN: Caller
+                     VMCIEventReleaseCB wakeupCB,   // IN
+                     void *clientData,              // IN
                      QPBrokerEntry **ent,           // OUT
                      Bool *swap)                    // OUT: swap queues?
 {
@@ -949,11 +973,13 @@ VMCIQPBrokerAllocInt(VMCIHandle handle,             // IN
    if (!entry) {
       create = TRUE;
       result = VMCIQPBrokerCreate(handle, peer, flags, privFlags, produceSize,
-                                  consumeSize, pageStore, context, ent);
+                                  consumeSize, pageStore, context, wakeupCB,
+                                  clientData, ent);
    } else {
       create = FALSE;
       result = VMCIQPBrokerAttach(entry, peer, flags, privFlags, produceSize,
-                                  consumeSize, pageStore, context, ent);
+                                  consumeSize, pageStore, context, wakeupCB,
+                                  clientData, ent);
    }
 
    if (swap) {
@@ -1004,6 +1030,8 @@ VMCIQPBrokerCreate(VMCIHandle handle,             // IN
                    uint64 consumeSize,            // IN
                    QueuePairPageStore *pageStore, // IN
                    VMCIContext *context,          // IN: Caller
+                   VMCIEventReleaseCB wakeupCB,   // IN
+                   void *clientData,              // IN
                    QPBrokerEntry **ent)           // OUT
 {
    QPBrokerEntry *entry = NULL;
@@ -1057,12 +1085,13 @@ VMCIQPBrokerCreate(VMCIHandle handle,             // IN
    entry->createdByTrusted =
       (privFlags & VMCI_PRIVILEGE_FLAG_TRUSTED) ? TRUE : FALSE;
    entry->vmciPageFiles = FALSE;
+   entry->wakeupCB = wakeupCB;
+   entry->clientData = clientData;
    entry->produceQ = VMCIHost_AllocQueue(produceSize);
    if (entry->produceQ == NULL) {
       result = VMCI_ERROR_NO_MEM;
       goto error;
    }
-
    entry->consumeQ = VMCIHost_AllocQueue(consumeSize);
    if (entry->consumeQ == NULL) {
       result = VMCI_ERROR_NO_MEM;
@@ -1181,6 +1210,8 @@ VMCIQPBrokerAttach(QPBrokerEntry *entry,          // IN
                    uint64 consumeSize,            // IN
                    QueuePairPageStore *pageStore, // IN/OUT
                    VMCIContext *context,          // IN: Caller
+                   VMCIEventReleaseCB wakeupCB,   // IN
+                   void *clientData,              // IN
                    QPBrokerEntry **ent)           // OUT
 {
    const VMCIId contextId = VMCIContext_GetId(context);
@@ -1335,6 +1366,11 @@ VMCIQPBrokerAttach(QPBrokerEntry *entry,          // IN
 
    entry->attachId = contextId;
    entry->qp.refCount++;
+   if (wakeupCB) {
+      ASSERT(!entry->wakeupCB);
+      entry->wakeupCB = wakeupCB;
+      entry->clientData = clientData;
+   }
 
    /*
     * When attaching to local queue pairs, the context already has
@@ -1581,6 +1617,18 @@ VMCIQPBroker_Detach(VMCIHandle  handle,   // IN
             VMCIHost_UnregisterUserMemory(entry->produceQ, entry->consumeQ);
          }
          VMCI_ReleaseQueueMutex(entry->produceQ);
+      } else {
+         VMCI_AcquireQueueMutex(entry->produceQ);
+         QueuePairResetSavedHeaders(entry);
+         VMCI_ReleaseQueueMutex(entry->produceQ);
+         if (entry->wakeupCB) {
+            entry->wakeupCB(entry->clientData);
+         }
+      }
+   } else {
+      if (entry->wakeupCB) {
+         entry->wakeupCB = NULL;
+         entry->clientData = NULL;
       }
    }
 
@@ -1642,11 +1690,6 @@ VMCIQPBroker_Map(VMCIHandle  handle,      // IN
    Bool isLocal = FALSE;
    int result;
 
-   if (vmkernel) {
-      ASSERT(FALSE);
-      return VMCI_ERROR_UNAVAILABLE;
-   }
-
    if (VMCI_HANDLE_INVALID(handle) || !context || contextId == VMCI_INVALID_ID) {
       return VMCI_ERROR_INVALID_ARGS;
    }
@@ -1672,7 +1715,20 @@ VMCIQPBroker_Map(VMCIHandle  handle,      // IN
 
    isLocal = entry->qp.flags & VMCI_QPFLAG_LOCAL;
 
-   if (contextId != VMCI_HOST_CONTEXT_ID) {
+   if (vmkernel) {
+      /*
+       * On vmkernel, the readiness of the queue pair can be signalled
+       * immediately since the guest memory is already registered.
+       */
+
+      VMCI_AcquireQueueMutex(entry->produceQ);
+      QueuePairResetSavedHeaders(entry);
+      VMCI_ReleaseQueueMutex(entry->produceQ);
+      if (entry->wakeupCB) {
+         entry->wakeupCB(entry->clientData);
+      }
+      result = VMCI_SUCCESS;
+   } else  if (contextId != VMCI_HOST_CONTEXT_ID) {
       QueuePairPageStore pageStore;
 
       ASSERT(entry->state == VMCIQPB_CREATED_NO_MEM ||
@@ -1684,8 +1740,9 @@ VMCIQPBroker_Map(VMCIHandle  handle,      // IN
       pageStore.len = QPE_NUM_PAGES(entry->qp);
 
       VMCI_AcquireQueueMutex(entry->produceQ);
-
+      QueuePairResetSavedHeaders(entry);
       result = VMCIHost_RegisterUserMemory(&pageStore, entry->produceQ, entry->consumeQ);
+      VMCI_ReleaseQueueMutex(entry->produceQ);
       if (result == VMCI_SUCCESS) {
          /*
           * Move state from *_NO_MEM to *_MEM.
@@ -1696,8 +1753,11 @@ VMCIQPBroker_Map(VMCIHandle  handle,      // IN
          ASSERT(entry->state == VMCIQPB_CREATED_MEM ||
                 entry->state == VMCIQPB_SHUTDOWN_MEM ||
                 entry->state == VMCIQPB_ATTACHED_MEM);
+
+         if (entry->wakeupCB) {
+            entry->wakeupCB(entry->clientData);
+         }
       }
-      VMCI_ReleaseQueueMutex(entry->produceQ);
    } else {
       result = VMCI_SUCCESS;
    }
@@ -1705,6 +1765,71 @@ VMCIQPBroker_Map(VMCIHandle  handle,      // IN
    return result;
 }
 
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * QueuePairSaveHeaders --
+ *
+ *      Saves a snapshot of the queue headers for the given QP broker
+ *      entry. Should be used when guest memory is unmapped.
+ *
+ * Results:
+ *      VMCI_SUCCESS on success, appropriate error code if guest memory
+ *      can't be accessed..
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+QueuePairSaveHeaders(QPBrokerEntry *entry) // IN
+{
+   int result;
+
+   if (NULL == entry->produceQ->qHeader || NULL == entry->consumeQ->qHeader) {
+      result = VMCIHost_MapQueueHeaders(entry->produceQ, entry->consumeQ);
+      if (result < VMCI_SUCCESS) {
+         return result;
+      }
+   }
+   memcpy(&entry->savedProduceQ, entry->produceQ->qHeader, sizeof entry->savedProduceQ);
+   entry->produceQ->savedHeader = &entry->savedProduceQ;
+   memcpy(&entry->savedConsumeQ, entry->consumeQ->qHeader, sizeof entry->savedConsumeQ);
+   entry->consumeQ->savedHeader = &entry->savedConsumeQ;
+
+   return VMCI_SUCCESS;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * QueuePairResetSavedHeaders --
+ *
+ *      Resets saved queue headers for the given QP broker
+ *      entry. Should be used when guest memory becomes available
+ *      again, or the guest detaches.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+QueuePairResetSavedHeaders(QPBrokerEntry *entry) // IN
+{
+   entry->produceQ->savedHeader = NULL;
+   entry->consumeQ->savedHeader = NULL;
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -1759,13 +1884,20 @@ VMCIQPBroker_Unmap(VMCIHandle  handle,   // IN
    isLocal = entry->qp.flags & VMCI_QPFLAG_LOCAL;
 
    if (contextId != VMCI_HOST_CONTEXT_ID) {
+      int result;
+
       ASSERT(entry->state != VMCIQPB_CREATED_NO_MEM &&
              entry->state != VMCIQPB_SHUTDOWN_NO_MEM &&
              entry->state != VMCIQPB_ATTACHED_NO_MEM);
       ASSERT(!isLocal);
 
       VMCI_AcquireQueueMutex(entry->produceQ);
-
+      result = QueuePairSaveHeaders(entry);
+      if (result < VMCI_SUCCESS) {
+         VMCI_WARNING((LGPFX"Failed to save queue headers for queue pair "
+                       "(handle=0x%x:0x%x,result=%d).\n", handle.context,
+                       handle.resource, result));
+      }
       VMCIHost_UnmapQueueHeaders(gid,
                                  entry->produceQ,
                                  entry->consumeQ);
index 8b473572a278d4a1c238ca943b09a3bef00c3ca9..524f4e189f428d2ba260d9c8c8ba21a482926cf3 100644 (file)
@@ -95,7 +95,8 @@ void VMCIQPGuestEndpoints_Convert(Bool toLocal, Bool deviceReset);
 int VMCIQueuePair_Alloc(VMCIHandle *handle, VMCIQueue **produceQ,
                         uint64 produceSize, VMCIQueue **consumeQ,
                         uint64 consumeSize, VMCIId peer, uint32 flags,
-                        VMCIPrivilegeFlags privFlags, Bool guestEndpoint);
+                        VMCIPrivilegeFlags privFlags, Bool guestEndpoint,
+                        VMCIEventReleaseCB wakeupCB, void *clientData);
 int VMCIQueuePair_Detach(VMCIHandle handle, Bool guestEndpoint);
 int VMCIQPBroker_Map(VMCIHandle  handle, VMCIContext *context, VMCIQPGuestMem guestMem);
 int VMCIQPBroker_Unmap(VMCIHandle  handle, VMCIContext *context, VMCIGuestMemID gid);
index 3344a4002c9a7adbfaf1ea54865d0e3e965c9243..ab883ec31a46a629a5aa66b340bd8a25e3cb889d 100644 (file)
@@ -914,6 +914,7 @@ VMCI_AllocQueue(uint64 size) // IN: size of queue (not including header)
 
    queue = (VMCIQueue *)((uint8 *)qHeader + PAGE_SIZE);
    queue->qHeader = qHeader;
+   queue->savedHeader = NULL;
    queue->kernelIf = (VMCIQueueKernelIf *)((uint8 *)queue + sizeof *queue);
    queue->kernelIf->headerPage = NULL; // Unused in guest.
    queue->kernelIf->page = (struct page **)((uint8 *)queue->kernelIf +
@@ -1513,6 +1514,7 @@ VMCIHost_AllocQueue(uint64 size) // IN:
    queue = VMCI_AllocKernelMem(queueSize + queuePageSize, VMCI_MEMORY_NORMAL);
    if (queue) {
       queue->qHeader = NULL;
+      queue->savedHeader = NULL;
       queue->kernelIf = (VMCIQueueKernelIf *)((uint8 *)queue + sizeof *queue);
       queue->kernelIf->host = TRUE;
       queue->kernelIf->mutex = NULL;
index e1939f29db0feae81ddecdb5335b4833bed190e2..bda4ae566c94b630c703d5764f34172b867fe68f 100644 (file)
@@ -25,8 +25,8 @@
 #ifndef _VMCI_VERSION_H_
 #define _VMCI_VERSION_H_
 
-#define VMCI_DRIVER_VERSION          9.3.4.0
-#define VMCI_DRIVER_VERSION_COMMAS   9,3,4,0
-#define VMCI_DRIVER_VERSION_STRING   "9.3.4.0"
+#define VMCI_DRIVER_VERSION          9.3.5.0
+#define VMCI_DRIVER_VERSION_COMMAS   9,3,5,0
+#define VMCI_DRIVER_VERSION_STRING   "9.3.5.0"
 
 #endif /* _VMCI_VERSION_H_ */
index 81a5ffd9fba95458e7c43e08c247eb3d813070ff..78a57d32f7d89d8e607c4ddfd631e78d643fd473 100644 (file)
@@ -64,6 +64,7 @@ typedef struct VMCIQueueKernelIf VMCIQueueKernelIf;
 
 typedef struct VMCIQueue {
    VMCIQueueHeader *qHeader;
+   VMCIQueueHeader *savedHeader;
    VMCIQueueKernelIf *kernelIf;
 } VMCIQueue;