summaryrefslogtreecommitdiff
path: root/open-vm-tools/modules/linux/vmci/common/vmciContext.c
diff options
context:
space:
mode:
Diffstat (limited to 'open-vm-tools/modules/linux/vmci/common/vmciContext.c')
-rw-r--r--open-vm-tools/modules/linux/vmci/common/vmciContext.c171
1 files changed, 159 insertions, 12 deletions
diff --git a/open-vm-tools/modules/linux/vmci/common/vmciContext.c b/open-vm-tools/modules/linux/vmci/common/vmciContext.c
index 513e93d4..5ebd28ab 100644
--- a/open-vm-tools/modules/linux/vmci/common/vmciContext.c
+++ b/open-vm-tools/modules/linux/vmci/common/vmciContext.c
@@ -1,5 +1,5 @@
/*********************************************************
- * Copyright (C) 2006-2012 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006-2012,2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -577,8 +577,9 @@ VMCIContext_PendingDatagrams(VMCIId cid, // IN
*/
int
-VMCIContext_EnqueueDatagram(VMCIId cid, // IN: Target VM
- VMCIDatagram *dg) // IN:
+VMCIContext_EnqueueDatagram(VMCIId cid, // IN: Target VM
+ VMCIDatagram *dg, // IN:
+ Bool notify) // IN:
{
DatagramQueueEntry *dqEntry;
VMCIContext *context;
@@ -648,8 +649,12 @@ VMCIContext_EnqueueDatagram(VMCIId cid, // IN: Target VM
VMCIList_Insert(&dqEntry->listItem, &context->datagramQueue);
context->pendingDatagrams++;
context->datagramQueueSize += vmciDgSize;
- VMCIContextSignalNotify(context);
- VMCIHost_SignalCall(&context->hostContext);
+
+ if (notify) {
+ VMCIContextSignalNotify(context);
+ VMCIHost_SignalCall(&context->hostContext);
+ }
+
VMCI_ReleaseLock(&context->lock, flags);
VMCIContext_Release(context);
@@ -809,7 +814,7 @@ VMCIContext_Release(VMCIContext *context) // IN
{
uint32 refCount;
ASSERT(context);
- refCount = Atomic_FetchAndDec(&context->refCount);
+ refCount = Atomic_ReadDec32(&context->refCount);
if (refCount == 1) {
VMCIContextFreeContext(context);
}
@@ -1489,6 +1494,143 @@ VMCIContextFireNotification(VMCIId contextID, // IN
return VMCI_SUCCESS;
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContextDgHypervisorSaveStateSize --
+ *
+ * Calculate the size for the hypervisor datagram checkpoint
+ * save data.
+ *
+ * The format is as follows:
+ *
+ * uint32 count - number of entries
+ * uint32 size - size of first entry
+ * char bytes[] - contents of first entry
+ * uint32 size - size of second entry
+ * char bytes[] - contents of second entry
+ * ...
+ *
+ * Results:
+ * VMCI_SUCCESS on success, error code otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+VMCIContextDgHypervisorSaveStateSize(VMCIContext *context, // IN
+ uint32 *bufSize, // IN/OUT
+ char **cptBufPtr) // UNUSED
+{
+ uint32 total;
+ VMCIListItem *iter;
+
+ *bufSize = total = 0;
+
+ VMCIList_Scan(iter, &context->datagramQueue) {
+ DatagramQueueEntry *dqEntry =
+ VMCIList_Entry(iter, DatagramQueueEntry, listItem);
+
+ if (dqEntry->dg->src.context == VMCI_HYPERVISOR_CONTEXT_ID) {
+ /* Size of the datagram followed by the contents of the datagram. */
+ total += sizeof(uint32) + dqEntry->dgSize;
+ }
+ }
+
+ if (total > 0) {
+ /* Don't forget the datagram count. */
+ *bufSize = total + sizeof(uint32);
+ }
+
+ return VMCI_SUCCESS;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContextDgHypervisorSaveState --
+ *
+ * Get the hypervisor datagram checkpoint save data.
+ *
+ * Results:
+ * VMCI_SUCCESS on success, error code otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+VMCIContextDgHypervisorSaveState(VMCIContext *context, // IN
+ uint32 *bufSize, // IN/OUT
+ char **cptBufPtr) // OUT
+{
+ uint8 *p;
+ uint32 total;
+ uint32 count;
+ VMCIListItem *iter;
+
+ /* Need at least the count field and the size of one entry. */
+ if (*bufSize < sizeof(uint32) * 2) {
+ return VMCI_ERROR_INVALID_ARGS;
+ }
+
+ p = VMCI_AllocKernelMem(*bufSize, VMCI_MEMORY_NORMAL);
+ if (p == NULL) {
+ return VMCI_ERROR_NO_MEM;
+ }
+
+ *cptBufPtr = p;
+
+ /* Leave space for the datagram count at the start. */
+ total = sizeof(uint32);
+ p += sizeof(uint32);
+
+ count = 0;
+ VMCIList_Scan(iter, &context->datagramQueue) {
+ DatagramQueueEntry *dqEntry =
+ VMCIList_Entry(iter, DatagramQueueEntry, listItem);
+
+ if (dqEntry->dg->src.context == VMCI_HYPERVISOR_CONTEXT_ID) {
+
+ /*
+ * VMX might have capped the amount of space we can use to checkpoint
+ * hypervisor datagrams. Respect that here. Those that are not written
+ * to the buffer will get dropped.
+ */
+
+ if (total + sizeof(uint32) + dqEntry->dgSize > *bufSize) {
+ break;
+ }
+
+ total += sizeof(uint32) + dqEntry->dgSize;
+
+ /*
+ * Write in the size of the datagram followed by the contents of the
+ * datagram itself.
+ */
+
+ *(uint32 *)p = dqEntry->dgSize;
+ p += sizeof(uint32);
+
+ memcpy(p, dqEntry->dg, dqEntry->dgSize);
+ p += dqEntry->dgSize;
+
+ count++;
+ }
+ }
+
+ /* Now rollback and write the count at the start of the block. */
+ *(uint32 *)(*cptBufPtr) = count;
+
+ return VMCI_SUCCESS;
+}
+
/*
*----------------------------------------------------------------------
@@ -1546,6 +1688,12 @@ VMCIContext_GetCheckpointState(VMCIId contextID, // IN:
ASSERT(context->doorbellArray);
array = context->doorbellArray;
getContextID = FALSE;
+ } else if (cptType == VMCI_DG_HYPERVISOR_SAVE_STATE_SIZE) {
+ result = VMCIContextDgHypervisorSaveStateSize(context, bufSize, cptBufPtr);
+ goto release;
+ } else if (cptType == VMCI_DG_HYPERVISOR_SAVE_STATE) {
+ result = VMCIContextDgHypervisorSaveState(context, bufSize, cptBufPtr);
+ goto release;
} else {
VMCI_DEBUG_LOG(4, (LGPFX"Invalid cpt state (type=%d).\n", cptType));
result = VMCI_ERROR_INVALID_ARGS;
@@ -1589,10 +1737,9 @@ VMCIContext_GetCheckpointState(VMCIId contextID, // IN:
}
result = VMCI_SUCCESS;
- release:
+release:
VMCI_ReleaseLock(&context->lock, flags);
VMCIContext_Release(context);
-
return result;
}
@@ -2081,7 +2228,7 @@ VMCIContext_SignalPendingDoorbells(VMCIId contextID)
VMCI_ReleaseLock(&context->lock, flags);
if (pending) {
- VMCIHost_SignalBitmap(&context->hostContext);
+ VMCIHost_SignalBitmapAlways(&context->hostContext);
}
VMCIContext_Release(context);
@@ -2125,7 +2272,7 @@ VMCIContext_SignalPendingDatagrams(VMCIId contextID)
VMCI_ReleaseLock(&context->lock, flags);
if (pending) {
- VMCIHost_SignalCall(&context->hostContext);
+ VMCIHost_SignalCallAlways(&context->hostContext);
}
VMCIContext_Release(context);
@@ -2207,7 +2354,7 @@ VMCI_EXPORT_SYMBOL(vmci_is_context_owner)
#if defined(linux) && !defined(VMKERNEL)
int
vmci_is_context_owner(VMCIId contextID, // IN
- uid_t uid) // IN
+ VMCIHostUser uid) // IN
{
int isOwner = 0;
@@ -2215,7 +2362,7 @@ vmci_is_context_owner(VMCIId contextID, // IN
VMCIContext *context = VMCIContext_Get(contextID);
if (context) {
if (context->validUser) {
- if (VMCIHost_CompareUser((VMCIHostUser *)&uid,
+ if (VMCIHost_CompareUser(&uid,
&context->user) == VMCI_SUCCESS) {
isOwner = 1;
}