+++ /dev/null
-/*********************************************************
- * Copyright (C) 2007 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
- * Free Software Foundation version 2 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- *********************************************************/
-
-/*
- * vmciGuestDs.c
- *
- * Implements the client-access API to the VMCI discovery service in
- * the guest kernel.
- *
- */
-
-#ifdef __linux__
-# include "driver-config.h"
-
-# define EXPORT_SYMTAB
-
-# include <linux/module.h>
-# include "compat_kernel.h"
-# include "compat_pci.h"
-#elif defined(_WIN32)
-# include <ntddk.h>
-#elif defined(SOLARIS)
-# include <sys/ddi.h>
-# include <sys/sunddi.h>
-#elif defined(__APPLE__)
-# include <IOKit/IOLib.h>
-#else
-# error "Platform not support by VMCI datagram API."
-#endif // linux
-
-#include "vm_basic_types.h"
-#include "vm_atomic.h"
-#include "vm_assert.h"
-#include "vmci_defs.h"
-#include "vmci_kernel_if.h"
-#include "vmci_infrastructure.h"
-#include "vmciInt.h"
-#include "vmciUtil.h"
-#include "vmciDatagram.h"
-#include "vmciKernelAPI.h"
-
-static Atomic_uint32 MsgIdCounter = { 0 };
-
-typedef struct VMCIDsRecvData {
- VMCIHost context;
- VMCILock lock;
- int status;
- uint8 buffer[VMCI_DS_MAX_MSG_SIZE];
-} VMCIDsRecvData;
-
-static int VMCIDsDoCall(int action, const char *name, VMCIHandle handle,
- VMCIHandle *handleOut);
-static int VMCIDsRecvCB(void *clientData, struct VMCIDatagram *msg);
-
-/*
- *-------------------------------------------------------------------------
- *
- * VMCIDs_Lookup --
- *
- * Look up a handle in the VMCI discovery service based on
- * the given name.
- *
- * Results:
- * Error code. 0 if success.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-
-VMCI_EXPORT_SYMBOL(VMCIDs_Lookup)
-int
-VMCIDs_Lookup(const char *name, // IN
- VMCIHandle *out) //
-{
- return VMCIDsDoCall(VMCI_DS_ACTION_LOOKUP, name, VMCI_INVALID_HANDLE, out);
-}
-
-
-/*
- *-------------------------------------------------------------------------
- *
- * VMCIDsDoCall --
- *
- * Serialize a call into the CDS wire-format, send it across
- * the VMCI device, wait for a response, and return
- * the results.
- *
- * Results:
- * Error code. 0 if success.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-
-
-static int
-VMCIDsDoCall(int action, // IN
- const char *name, // IN
- VMCIHandle handle, // IN: For the "register" action
- VMCIHandle *handleOut) // OUT: For the "lookup" action
-{
- int8 *sendBuffer = NULL;
- const size_t sendBufferSize = VMCI_DS_MAX_MSG_SIZE + sizeof(VMCIDatagram);
- int nameLen, requestSize, res;
- uint32 savedMsgIdCounter;
- VMCIDsReplyHeader *reply;
- VMCIHandle dsHandle = VMCI_INVALID_HANDLE;
- VMCIDsRecvData *recvData = NULL;
- VMCIDatagram *dgram;
- VMCIDsRequestHeader *request;
- VMCILockFlags flags;
-
- nameLen = strlen(name);
- if (nameLen + sizeof *request > sendBufferSize) {
- res = VMCI_ERROR_INVALID_ARGS;
- goto out;
- }
-
- sendBuffer = VMCI_AllocKernelMem(sendBufferSize, VMCI_MEMORY_NONPAGED);
- if (sendBuffer == NULL) {
- res = VMCI_ERROR_NO_MEM;
- goto out;
- }
-
- recvData = VMCI_AllocKernelMem(sizeof *recvData, VMCI_MEMORY_NONPAGED);
- if (recvData == NULL) {
- res = VMCI_ERROR_NO_MEM;
- goto out;
- }
-
- VMCIHost_InitContext(&recvData->context, (uintptr_t) recvData);
- VMCI_InitLock(&recvData->lock, "VMCIDsRecvHandler", VMCI_LOCK_RANK_MIDDLE_BH);
-
- savedMsgIdCounter = Atomic_FetchAndInc(&MsgIdCounter);
-
- dgram = (VMCIDatagram *) sendBuffer;
- request = (VMCIDsRequestHeader *) (sendBuffer + sizeof *dgram);
-
- /* Serialize request. */
- request->action = action;
- request->msgid = savedMsgIdCounter;
- request->handle = handle;
- request->nameLen = nameLen;
- memcpy(request->name, name, nameLen + 1);
-
- requestSize = sizeof *request + nameLen;
-
- if (VMCIDatagram_CreateHnd(VMCI_INVALID_ID, 0, VMCIDsRecvCB,
- recvData, &dsHandle) != VMCI_SUCCESS) {
- res = VMCI_ERROR_NO_HANDLE;
- goto out;
- }
-
- dgram->dst = VMCI_DS_HANDLE;
- dgram->src = dsHandle;
- dgram->payloadSize = requestSize;
-
- /* Send the datagram to CDS. */
- res = VMCIDatagram_Send(dgram);
- if (res <= 0) {
- goto out;
- }
-
- /* Block here waiting for the reply */
- VMCI_GrabLock_BH(&recvData->lock, &flags);
- VMCIHost_WaitForCallLocked(&recvData->context, &recvData->lock, &flags, TRUE);
- VMCI_ReleaseLock_BH(&recvData->lock, flags);
-
- if (recvData->status != VMCI_SUCCESS) {
- res = recvData->status;
- goto out;
- }
-
- reply = (VMCIDsReplyHeader *) recvData->buffer;
- /* Check that the msgid matches what we expect. */
- if (reply->msgid != savedMsgIdCounter) {
- res = VMCI_ERROR_GENERIC;
- goto out;
- }
-
- if (handleOut != NULL) {
- *handleOut = reply->handle;
- }
-
- res = reply->code;
-
-out:
- if (!VMCI_HANDLE_EQUAL(dsHandle, VMCI_INVALID_HANDLE)) {
- VMCIDatagram_DestroyHnd(dsHandle);
- }
- if (recvData) {
- VMCI_CleanupLock(&recvData->lock);
- VMCIHost_ReleaseContext(&recvData->context);
- VMCI_FreeKernelMem(recvData, sizeof *recvData);
- }
- if (sendBuffer) {
- VMCI_FreeKernelMem(sendBuffer, sendBufferSize);
- }
- return res;
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * VMCIDsRecvCB --
- *
- * Receive callback for the Discovery Service query datagram
- * handle.
- *
- * Results:
- * If the received payload is not larger than the MAX, it is
- * copied into clientData.
- *
- * Side effects:
- * Signals the thread waiting for the reply.
- *
- *-----------------------------------------------------------------------------
- */
-
-
-static int
-VMCIDsRecvCB(void *clientData, // IN: client data for handler
- struct VMCIDatagram *msg) // IN
-{
- VMCIDsRecvData *recvData = clientData;
- VMCILockFlags flags;
-
- ASSERT(msg->payloadSize <= VMCI_DS_MAX_MSG_SIZE);
- if (msg->payloadSize <= VMCI_DS_MAX_MSG_SIZE) {
- memcpy(recvData->buffer, VMCI_DG_PAYLOAD(msg), (size_t)msg->payloadSize);
- recvData->status = VMCI_SUCCESS;
- } else {
- recvData->status = VMCI_ERROR_PAYLOAD_TOO_LARGE;
- }
-
- VMCI_GrabLock_BH(&recvData->lock, &flags);
- VMCIHost_SignalCall(&recvData->context);
- VMCI_ReleaseLock_BH(&recvData->lock, flags);
- return 0;
-}