lkml.org 
[lkml]   [2012]   [Feb]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 12/14] Add misc header files used by VMCI
    Date
    ---
    drivers/misc/vmw_vmci/vmci_call_defs.h | 264 +++++++++
    drivers/misc/vmw_vmci/vmci_defs.h | 772 +++++++++++++++++++++++++++
    drivers/misc/vmw_vmci/vmci_handle_array.h | 339 ++++++++++++
    drivers/misc/vmw_vmci/vmci_infrastructure.h | 119 ++++
    drivers/misc/vmw_vmci/vmci_iocontrols.h | 411 ++++++++++++++
    drivers/misc/vmw_vmci/vmci_kernel_if.h | 111 ++++
    6 files changed, 2016 insertions(+), 0 deletions(-)
    create mode 100644 drivers/misc/vmw_vmci/vmci_call_defs.h
    create mode 100644 drivers/misc/vmw_vmci/vmci_defs.h
    create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.h
    create mode 100644 drivers/misc/vmw_vmci/vmci_infrastructure.h
    create mode 100644 drivers/misc/vmw_vmci/vmci_iocontrols.h
    create mode 100644 drivers/misc/vmw_vmci/vmci_kernel_if.h

    diff --git a/drivers/misc/vmw_vmci/vmci_call_defs.h b/drivers/misc/vmw_vmci/vmci_call_defs.h
    new file mode 100644
    index 0000000..480c0dc
    --- /dev/null
    +++ b/drivers/misc/vmw_vmci/vmci_call_defs.h
    @@ -0,0 +1,264 @@
    +/*
    + *
    + * VMware VMCI Driver
    + *
    + * Copyright (C) 2012 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
    + */
    +
    +#ifndef _VMCI_CALL_DEFS_H_
    +#define _VMCI_CALL_DEFS_H_
    +
    +#include "vmci_defs.h"
    +
    +/*
    + * All structs here are an integral size of their largest member, ie. a struct
    + * with at least one 8-byte member will have a size that is an integral of 8.
    + * A struct which has a largest member of size 4 will have a size that is an
    + * integral of 4. This is because Windows CL enforces this rule. 32 bit gcc
    + * doesn't e.g. 32 bit gcc can misalign an 8 byte member if it is preceeded by
    + * a 4 byte member.
    + */
    +
    +/* Base struct for vmci datagrams. */
    +struct vmci_datagram {
    + struct vmci_handle dst;
    + struct vmci_handle src;
    + uint64_t payloadSize;
    +};
    +
    +/*
    + * Second flag is for creating a well-known handle instead of a per context
    + * handle. Next flag is for deferring datagram delivery, so that the
    + * datagram callback is invoked in a delayed context (not interrupt context).
    + */
    +#define VMCI_FLAG_DG_NONE 0
    +#define VMCI_FLAG_WELLKNOWN_DG_HND 0x1
    +#define VMCI_FLAG_ANYCID_DG_HND 0x2
    +#define VMCI_FLAG_DG_DELAYED_CB 0x4
    +
    +/* Event callback should fire in a delayed context (not interrupt context.) */
    +#define VMCI_FLAG_EVENT_NONE 0
    +#define VMCI_FLAG_EVENT_DELAYED_CB 0x1
    +
    +/*
    + * Maximum supported size of a VMCI datagram for routable datagrams.
    + * Datagrams going to the hypervisor are allowed to be larger.
    + */
    +#define VMCI_MAX_DG_SIZE (17 * 4096)
    +#define VMCI_MAX_DG_PAYLOAD_SIZE (VMCI_MAX_DG_SIZE - sizeof(struct vmci_datagram))
    +#define VMCI_DG_PAYLOAD(_dg) (void *)((char *)(_dg) + sizeof(struct vmci_datagram))
    +#define VMCI_DG_HEADERSIZE sizeof(struct vmci_datagram)
    +#define VMCI_DG_SIZE(_dg) (VMCI_DG_HEADERSIZE + (size_t)(_dg)->payloadSize)
    +#define VMCI_DG_SIZE_ALIGNED(_dg) ((VMCI_DG_SIZE(_dg) + 7) & (size_t)CONST64U(0xfffffffffffffff8))
    +#define VMCI_MAX_DATAGRAM_QUEUE_SIZE (VMCI_MAX_DG_SIZE * 2)
    +
    +/*
    + * We allow at least 1024 more event datagrams from the hypervisor past the
    + * normally allowed datagrams pending for a given context. We define this
    + * limit on event datagrams from the hypervisor to guard against DoS attack
    + * from a malicious VM which could repeatedly attach to and detach from a queue
    + * pair, causing events to be queued at the destination VM. However, the rate
    + * at which such events can be generated is small since it requires a VM exit
    + * and handling of queue pair attach/detach call at the hypervisor. Event
    + * datagrams may be queued up at the destination VM if it has interrupts
    + * disabled or if it is not draining events for some other reason. 1024
    + * datagrams is a grossly conservative estimate of the time for which
    + * interrupts may be disabled in the destination VM, but at the same time does
    + * not exacerbate the memory pressure problem on the host by much (size of each
    + * event datagram is small).
    + */
    +#define VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE \
    + (VMCI_MAX_DATAGRAM_QUEUE_SIZE + \
    + 1024 * (sizeof(struct vmci_datagram) + sizeof(struct vmci_event_data_max)))
    +
    +/*
    + * Struct used for querying, via VMCI_RESOURCES_QUERY, the availability of
    + * hypervisor resources.
    + * Struct size is 16 bytes. All fields in struct are aligned to their natural
    + * alignment.
    + */
    +struct vmci_rsrc_query_hdr {
    + struct vmci_datagram hdr;
    + uint32_t numResources;
    + uint32_t _padding;
    +};
    +
    +/*
    + * Convenience struct for negotiating vectors. Must match layout of
    + * VMCIResourceQueryHdr minus the struct vmci_datagram header.
    + */
    +struct vmci_rscs_query_msg {
    + uint32_t numResources;
    + uint32_t _padding;
    + uint32_t resources[1];
    +};
    +
    +/*
    + * The maximum number of resources that can be queried using
    + * VMCI_RESOURCE_QUERY is 31, as the result is encoded in the lower 31
    + * bits of a positive return value. Negative values are reserved for
    + * errors.
    + */
    +#define VMCI_RESOURCE_QUERY_MAX_NUM 31
    +
    +/* Maximum size for the VMCI_RESOURCE_QUERY request. */
    +#define VMCI_RESOURCE_QUERY_MAX_SIZE sizeof(struct vmci_rsrc_query_hdr) \
    + + VMCI_RESOURCE_QUERY_MAX_NUM * sizeof(uint32_t)
    +
    +/*
    + * Struct used for setting the notification bitmap. All fields in
    + * struct are aligned to their natural alignment.
    + */
    +struct vmci_ntfy_bm_set_msg {
    + struct vmci_datagram hdr;
    + uint32_t bitmapPPN;
    + uint32_t _pad;
    +};
    +
    +/*
    + * Struct used for linking a doorbell handle with an index in the
    + * notify bitmap. All fields in struct are aligned to their natural
    + * alignment.
    + */
    +struct vmci_doorbell_link_msg {
    + struct vmci_datagram hdr;
    + struct vmci_handle handle;
    + uint64_t notifyIdx;
    +};
    +
    +/*
    + * Struct used for unlinking a doorbell handle from an index in the
    + * notify bitmap. All fields in struct are aligned to their natural
    + * alignment.
    + */
    +struct vmci_doorbell_unlink_msg {
    + struct vmci_datagram hdr;
    + struct vmci_handle handle;
    +};
    +
    +/*
    + * Struct used for generating a notification on a doorbell handle. All
    + * fields in struct are aligned to their natural alignment.
    + */
    +struct vmci_doorbell_ntfy_msg {
    + struct vmci_datagram hdr;
    + struct vmci_handle handle;
    +};
    +
    +/*
    + * This struct is used to contain data for events. Size of this struct is a
    + * multiple of 8 bytes, and all fields are aligned to their natural alignment.
    + */
    +struct vmci_event_data {
    + uint32_t event; /* 4 bytes. */
    + uint32_t _pad;
    + /* Event payload is put here. */
    +};
    +
    +/* Callback needed for correctly waiting on events. */
    +typedef int
    + (*VMCIDatagramRecvCB) (void *clientData, // IN: client data for handler
    + struct vmci_datagram * msg); // IN:
    +
    +/*
    + * We use the following inline function to access the payload data associated
    + * with an event data.
    + */
    +static inline void *VMCIEventDataPayload(struct vmci_event_data *evData) // IN:
    +{
    + return (void *)((char *)evData + sizeof *evData);
    +}
    +
    +/*
    + * Define the different VMCI_EVENT payload data types here. All structs must
    + * be a multiple of 8 bytes, and fields must be aligned to their natural
    + * alignment.
    + */
    +struct vmci_event_payld_ctx {
    + uint32_t contextID; /* 4 bytes. */
    + uint32_t _pad;
    +};
    +
    +struct vmci_event_payld_qp {
    + struct vmci_handle handle; /* QueuePair handle. */
    + uint32_t peerId; /* Context id of attaching/detaching VM. */
    + uint32_t _pad;
    +};
    +
    +/*
    + * We define the following struct to get the size of the maximum event data
    + * the hypervisor may send to the guest. If adding a new event payload type
    + * above, add it to the following struct too (inside the union).
    + */
    +struct vmci_event_data_max {
    + struct vmci_event_data eventData;
    + union {
    + struct vmci_event_payld_ctx contextPayload;
    + struct vmci_event_payld_qp qpPayload;
    + } evDataPayload;
    +};
    +
    +/*
    + * Struct used for VMCI_EVENT_SUBSCRIBE/UNSUBSCRIBE and VMCI_EVENT_HANDLER
    + * messages. Struct size is 32 bytes. All fields in struct are aligned to
    + * their natural alignment.
    + */
    +struct vmci_event_msg {
    + struct vmci_datagram hdr;
    + struct vmci_event_data eventData; /* Has event type and payload. */
    + /* Payload gets put here. */
    +};
    +
    +/*
    + * We use the following inline function to access the payload data associated
    + * with an event message.
    + *
    + * XXX: NUKE ME.
    + */
    +static inline void *VMCIEventMsgPayload(struct vmci_event_msg *eMsg) // IN:
    +{
    + return VMCIEventDataPayload(&eMsg->eventData);
    +}
    +
    +/* 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 | \
    + VMCI_QPFLAG_NONBLOCK)
    +
    +/*
    + * Structs used for QueuePair alloc and detach messages. We align fields of
    + * these structs to 64bit boundaries.
    + */
    +struct vmci_qp_alloc_msg {
    + struct vmci_datagram hdr;
    + struct vmci_handle handle;
    + uint32_t peer; /* 32bit field. */
    + uint32_t flags;
    + uint64_t produceSize;
    + uint64_t consumeSize;
    + uint64_t numPPNs;
    + /* List of PPNs placed here. */
    +};
    +
    +struct vmci_qp_detach_msg {
    + struct vmci_datagram hdr;
    + struct vmci_handle handle;
    +};
    +
    +#endif
    diff --git a/drivers/misc/vmw_vmci/vmci_defs.h b/drivers/misc/vmw_vmci/vmci_defs.h
    new file mode 100644
    index 0000000..bf1569b
    --- /dev/null
    +++ b/drivers/misc/vmw_vmci/vmci_defs.h
    @@ -0,0 +1,772 @@
    +/*
    + * VMware VMCI Driver
    + *
    + * Copyright (C) 2012 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
    + */
    +
    +#ifndef _VMCI_DEF_H_
    +#define _VMCI_DEF_H_
    +
    +#include <linux/atomic.h>
    +#include <linux/printk.h>
    +
    +#define DEBUG
    +
    +#ifdef DEBUG
    +#define VMCI_DBG(msg, args...) do { \
    + pr_devel("VMCI_DBG %s - %s - %d: msg", __FILE__, \
    + __func__, __LINE__, ##args ); \
    + } while (0)
    +#else
    +#define VMCI_DBG(msg, args...)
    +#endif
    +
    +/* Register offsets. */
    +#define VMCI_STATUS_ADDR 0x00
    +#define VMCI_CONTROL_ADDR 0x04
    +#define VMCI_ICR_ADDR 0x08
    +#define VMCI_IMR_ADDR 0x0c
    +#define VMCI_DATA_OUT_ADDR 0x10
    +#define VMCI_DATA_IN_ADDR 0x14
    +#define VMCI_CAPS_ADDR 0x18
    +#define VMCI_RESULT_LOW_ADDR 0x1c
    +#define VMCI_RESULT_HIGH_ADDR 0x20
    +
    +/* Max number of devices. */
    +#define VMCI_MAX_DEVICES 1
    +
    +/* Status register bits. */
    +#define VMCI_STATUS_INT_ON 0x1
    +
    +/* Control register bits. */
    +#define VMCI_CONTROL_RESET 0x1
    +#define VMCI_CONTROL_INT_ENABLE 0x2
    +#define VMCI_CONTROL_INT_DISABLE 0x4
    +
    +/* Capabilities register bits. */
    +#define VMCI_CAPS_HYPERCALL 0x1
    +#define VMCI_CAPS_GUESTCALL 0x2
    +#define VMCI_CAPS_DATAGRAM 0x4
    +#define VMCI_CAPS_NOTIFICATIONS 0x8
    +
    +/* Interrupt Cause register bits. */
    +#define VMCI_ICR_DATAGRAM 0x1
    +#define VMCI_ICR_NOTIFICATION 0x2
    +
    +/* Interrupt Mask register bits. */
    +#define VMCI_IMR_DATAGRAM 0x1
    +#define VMCI_IMR_NOTIFICATION 0x2
    +
    +/* Interrupt type. */
    +enum {
    + VMCI_INTR_TYPE_INTX = 0,
    + VMCI_INTR_TYPE_MSI = 1,
    + VMCI_INTR_TYPE_MSIX = 2
    +};
    +
    +/* Maximum MSI/MSI-X interrupt vectors in the device. */
    +#define VMCI_MAX_INTRS 2
    +
    +/*
    + * Supported interrupt vectors. There is one for each ICR value above,
    + * but here they indicate the position in the vector array/message ID.
    + */
    +#define VMCI_INTR_DATAGRAM 0
    +#define VMCI_INTR_NOTIFICATION 1
    +
    +/*
    + * A single VMCI device has an upper limit of 128MB on the amount of
    + * memory that can be used for queue pairs.
    + */
    +#define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024)
    +
    +/*
    + * We have a fixed set of resource IDs available in the VMX.
    + * This allows us to have a very simple implementation since we statically
    + * know how many will create datagram handles. If a new caller arrives and
    + * we have run out of slots we can manually increment the maximum size of
    + * available resource IDs.
    + *
    + * VMCI reserved hypervisor datagram resource IDs.
    + */
    +#define VMCI_RESOURCES_QUERY 0
    +#define VMCI_GET_CONTEXT_ID 1
    +#define VMCI_SET_NOTIFY_BITMAP 2
    +#define VMCI_DOORBELL_LINK 3
    +#define VMCI_DOORBELL_UNLINK 4
    +#define VMCI_DOORBELL_NOTIFY 5
    +/*
    + * VMCI_DATAGRAM_REQUEST_MAP and VMCI_DATAGRAM_REMOVE_MAP are
    + * obsoleted by the removal of VM to VM communication.
    + */
    +#define VMCI_DATAGRAM_REQUEST_MAP 6
    +#define VMCI_DATAGRAM_REMOVE_MAP 7
    +#define VMCI_EVENT_SUBSCRIBE 8
    +#define VMCI_EVENT_UNSUBSCRIBE 9
    +#define VMCI_QUEUEPAIR_ALLOC 10
    +#define VMCI_QUEUEPAIR_DETACH 11
    +
    +/*
    + * VMCI_VSOCK_VMX_LOOKUP was assigned to 12 for Fusion 3.0/3.1,
    + * WS 7.0/7.1 and ESX 4.1
    + */
    +#define VMCI_HGFS_TRANSPORT 13
    +#define VMCI_UNITY_PBRPC_REGISTER 14
    +#define VMCI_RESOURCE_MAX 15
    +
    +#define Log(fmt, args...) printk(KERN_INFO fmt, ##args)
    +#define Warning(fmt, args...) printk(KERN_WARNING fmt, ##args)
    +#define PCI_VENDOR_ID_VMWARE 0x15AD
    +#define PCI_DEVICE_ID_VMWARE_VMCI 0x0740
    +#define VMCI_DRIVER_VERSION 9.3.14.0-k
    +#define VMCI_DRIVER_VERSION_STRING "9.3.14.0-k"
    +
    +#define ASSERT(cond) ({if (unlikely(!(cond))) panic("ASSERT Failed at %s:%d\n", __FILE__, __LINE__);})
    +#define QWORD(_hi, _lo) ((((uint64_t)(_hi)) << 32) | ((uint32_t)(_lo)))
    +
    +/*
    + * Compile-time assertions.
    + *
    + * The implementation uses both enum and typedef because the typedef alone is
    + * insufficient; gcc allows arrays to be declared with non-constant expressions
    + * (even in typedefs, where it makes no sense).
    + */
    +#define ASSERT_ON_COMPILE(e) \
    + do { \
    + enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
    + typedef char AssertOnCompileFailed[AssertOnCompileMisused]; \
    + } while (0)
    +
    +/* XXX: Replacement? */
    +#define CEILING(x, y) (((x) + (y) - 1) / (y))
    +
    +#ifdef CONFIG_X86_64
    +# define CONST64(c) c##L
    +# define CONST64U(c) c##uL
    +# define FMT64 "ll"
    +#else
    +# define CONST64(c) c##LL
    +# define CONST64U(c) c##uLL
    +# define FMT64 "L"
    +#endif
    +
    +#define UNUSED_PARAM(_parm) _parm __attribute__((__unused__))
    +
    +/* VMCI Ids. */
    +struct vmci_handle {
    + uint32_t context;
    + uint32_t resource;
    +};
    +
    +static inline struct vmci_handle VMCI_MAKE_HANDLE(uint32_t cid, uint32_t rid)
    +{
    + struct vmci_handle h;
    + h.context = cid;
    + h.resource = rid;
    + return h;
    +}
    +
    +/*
    + *----------------------------------------------------------------------
    + *
    + * VMCI_HANDLE_TO_UINT64 --
    + *
    + * Helper for VMCI handle to uint64_t conversion.
    + *
    + * Results:
    + * The uint64_t value.
    + *
    + * Side effects:
    + * None.
    + *
    + *----------------------------------------------------------------------
    + */
    +
    +static inline uint64_t VMCI_HANDLE_TO_UINT64(struct vmci_handle handle) // IN:
    +{
    + uint64_t handle64;
    +
    + handle64 = handle.context;
    + handle64 <<= 32;
    + handle64 |= handle.resource;
    + return handle64;
    +}
    +
    +/*
    + *----------------------------------------------------------------------
    + *
    + * VMCI_UINT64_TO_HANDLE --
    + *
    + * Helper for uint64_t to VMCI handle conversion.
    + *
    + * Results:
    + * The VMCI handle value.
    + *
    + * Side effects:
    + * None.
    + *
    + *----------------------------------------------------------------------
    + */
    +
    +static inline struct vmci_handle VMCI_UINT64_TO_HANDLE(uint64_t handle64) // IN:
    +{
    + uint32_t context = (uint32_t) (handle64 >> 32);
    + uint32_t resource = (uint32_t) handle64;
    +
    + return VMCI_MAKE_HANDLE(context, resource);
    +}
    +
    +#define VMCI_HANDLE_TO_CONTEXT_ID(_handle) ((_handle).context)
    +#define VMCI_HANDLE_TO_RESOURCE_ID(_handle) ((_handle).resource)
    +#define VMCI_HANDLE_EQUAL(_h1, _h2) ((_h1).context == (_h2).context && \
    + (_h1).resource == (_h2).resource)
    +
    +#define VMCI_INVALID_ID 0xFFFFFFFF
    +static const struct vmci_handle VMCI_INVALID_HANDLE = { VMCI_INVALID_ID,
    + VMCI_INVALID_ID
    +};
    +
    +#define VMCI_HANDLE_INVALID(_handle) \
    + VMCI_HANDLE_EQUAL((_handle), VMCI_INVALID_HANDLE)
    +
    +/*
    + * The below defines can be used to send anonymous requests.
    + * This also indicates that no response is expected.
    + */
    +#define VMCI_ANON_SRC_CONTEXT_ID VMCI_INVALID_ID
    +#define VMCI_ANON_SRC_RESOURCE_ID VMCI_INVALID_ID
    +#define VMCI_ANON_SRC_HANDLE VMCI_MAKE_HANDLE(VMCI_ANON_SRC_CONTEXT_ID, \
    + VMCI_ANON_SRC_RESOURCE_ID)
    +
    +/* The lowest 16 context ids are reserved for internal use. */
    +#define VMCI_RESERVED_CID_LIMIT (uint32_t) 16
    +
    +/*
    + * Hypervisor context id, used for calling into hypervisor
    + * supplied services from the VM.
    + */
    +#define VMCI_HYPERVISOR_CONTEXT_ID 0
    +
    +/*
    + * Well-known context id, a logical context that contains a set of
    + * well-known services. This context ID is now obsolete.
    + */
    +#define VMCI_WELL_KNOWN_CONTEXT_ID 1
    +
    +/*
    + * Context ID used by host endpoints.
    + */
    +#define VMCI_HOST_CONTEXT_ID 2
    +
    +#define VMCI_CONTEXT_IS_VM(_cid) (VMCI_INVALID_ID != _cid && \
    + _cid > VMCI_HOST_CONTEXT_ID)
    +
    +/*
    + * The VMCI_CONTEXT_RESOURCE_ID is used together with VMCI_MAKE_HANDLE to make
    + * handles that refer to a specific context.
    + */
    +#define VMCI_CONTEXT_RESOURCE_ID 0
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCI error codes.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +#define VMCI_SUCCESS_QUEUEPAIR_ATTACH 5
    +#define VMCI_SUCCESS_QUEUEPAIR_CREATE 4
    +#define VMCI_SUCCESS_LAST_DETACH 3
    +#define VMCI_SUCCESS_ACCESS_GRANTED 2
    +#define VMCI_SUCCESS_ENTRY_DEAD 1
    +#define VMCI_SUCCESS 0LL
    +#define VMCI_ERROR_INVALID_RESOURCE (-1)
    +#define VMCI_ERROR_INVALID_ARGS (-2)
    +#define VMCI_ERROR_NO_MEM (-3)
    +#define VMCI_ERROR_DATAGRAM_FAILED (-4)
    +#define VMCI_ERROR_MORE_DATA (-5)
    +#define VMCI_ERROR_NO_MORE_DATAGRAMS (-6)
    +#define VMCI_ERROR_NO_ACCESS (-7)
    +#define VMCI_ERROR_NO_HANDLE (-8)
    +#define VMCI_ERROR_DUPLICATE_ENTRY (-9)
    +#define VMCI_ERROR_DST_UNREACHABLE (-10)
    +#define VMCI_ERROR_PAYLOAD_TOO_LARGE (-11)
    +#define VMCI_ERROR_INVALID_PRIV (-12)
    +#define VMCI_ERROR_GENERIC (-13)
    +#define VMCI_ERROR_PAGE_ALREADY_SHARED (-14)
    +#define VMCI_ERROR_CANNOT_SHARE_PAGE (-15)
    +#define VMCI_ERROR_CANNOT_UNSHARE_PAGE (-16)
    +#define VMCI_ERROR_NO_PROCESS (-17)
    +#define VMCI_ERROR_NO_DATAGRAM (-18)
    +#define VMCI_ERROR_NO_RESOURCES (-19)
    +#define VMCI_ERROR_UNAVAILABLE (-20)
    +#define VMCI_ERROR_NOT_FOUND (-21)
    +#define VMCI_ERROR_ALREADY_EXISTS (-22)
    +#define VMCI_ERROR_NOT_PAGE_ALIGNED (-23)
    +#define VMCI_ERROR_INVALID_SIZE (-24)
    +#define VMCI_ERROR_REGION_ALREADY_SHARED (-25)
    +#define VMCI_ERROR_TIMEOUT (-26)
    +#define VMCI_ERROR_DATAGRAM_INCOMPLETE (-27)
    +#define VMCI_ERROR_INCORRECT_IRQL (-28)
    +#define VMCI_ERROR_EVENT_UNKNOWN (-29)
    +#define VMCI_ERROR_OBSOLETE (-30)
    +#define VMCI_ERROR_QUEUEPAIR_MISMATCH (-31)
    +#define VMCI_ERROR_QUEUEPAIR_NOTSET (-32)
    +#define VMCI_ERROR_QUEUEPAIR_NOTOWNER (-33)
    +#define VMCI_ERROR_QUEUEPAIR_NOTATTACHED (-34)
    +#define VMCI_ERROR_QUEUEPAIR_NOSPACE (-35)
    +#define VMCI_ERROR_QUEUEPAIR_NODATA (-36)
    +#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 within this range */
    +#define VMCI_ERROR_CLIENT_MIN (-500)
    +#define VMCI_ERROR_CLIENT_MAX (-550)
    +
    +/* Internal error codes. */
    +#define VMCI_SHAREDMEM_ERROR_BAD_CONTEXT (-1000)
    +
    +#define VMCI_PATH_MAX 256
    +
    +/* VMCI reserved events. */
    +#define VMCI_EVENT_CTX_ID_UPDATE 0 // Only applicable to guest endpoints
    +#define VMCI_EVENT_CTX_REMOVED 1 // Applicable to guest and host
    +#define VMCI_EVENT_QP_RESUMED 2 // Only applicable to guest endpoints
    +#define VMCI_EVENT_QP_PEER_ATTACH 3 // Applicable to guest and host
    +#define VMCI_EVENT_QP_PEER_DETACH 4 // Applicable to guest and host
    +#define VMCI_EVENT_MEM_ACCESS_ON 5 // Applicable to VMX and vmk. On vmk,
    + // this event has the Context payload type.
    +#define VMCI_EVENT_MEM_ACCESS_OFF 6 // Applicable to VMX and vmk. Same as
    + // above for the payload type.
    +#define VMCI_EVENT_MAX 7
    +
    +/*
    + * Of the above events, a few are reserved for use in the VMX, and
    + * other endpoints (guest and host kernel) should not use them. For
    + * the rest of the events, we allow both host and guest endpoints to
    + * subscribe to them, to maintain the same API for host and guest
    + * endpoints.
    + */
    +
    +#define VMCI_EVENT_VALID_VMX(_event) (_event == VMCI_EVENT_MEM_ACCESS_ON || \
    + _event == VMCI_EVENT_MEM_ACCESS_OFF)
    +
    +#define VMCI_EVENT_VALID(_event) (_event < VMCI_EVENT_MAX && \
    + !VMCI_EVENT_VALID_VMX(_event))
    +
    +/* Reserved guest datagram resource ids. */
    +#define VMCI_EVENT_HANDLER 0
    +
    +/*
    + * VMCI coarse-grained privileges (per context or host
    + * process/endpoint. An entity with the restricted flag is only
    + * allowed to interact with the hypervisor and trusted entities.
    + */
    +#define VMCI_PRIVILEGE_FLAG_RESTRICTED 0x01
    +#define VMCI_PRIVILEGE_FLAG_TRUSTED 0x02
    +#define VMCI_PRIVILEGE_ALL_FLAGS (VMCI_PRIVILEGE_FLAG_RESTRICTED | \
    + VMCI_PRIVILEGE_FLAG_TRUSTED)
    +#define VMCI_NO_PRIVILEGE_FLAGS 0x00
    +#define VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS VMCI_NO_PRIVILEGE_FLAGS
    +#define VMCI_LEAST_PRIVILEGE_FLAGS VMCI_PRIVILEGE_FLAG_RESTRICTED
    +#define VMCI_MAX_PRIVILEGE_FLAGS VMCI_PRIVILEGE_FLAG_TRUSTED
    +
    +#define VMCI_PUBLIC_GROUP_NAME "vmci public group"
    +/* 0 through VMCI_RESERVED_RESOURCE_ID_MAX are reserved. */
    +#define VMCI_RESERVED_RESOURCE_ID_MAX 1023
    +
    +#define VMCI_DOMAIN_NAME_MAXLEN 32
    +
    +#define VMCI_LGPFX "VMCI: "
    +
    +/*
    + * struct vmci_queue_header
    + *
    + * A Queue cannot stand by itself as designed. Each Queue's header
    + * contains a pointer into itself (the producerTail) and into its peer
    + * (consumerHead). The reason for the separation is one of
    + * accessibility: Each end-point can modify two things: where the next
    + * location to enqueue is within its produceQ (producerTail); and
    + * where the next dequeue location is in its consumeQ (consumerHead).
    + *
    + * An end-point cannot modify the pointers of its peer (guest to
    + * guest; NOTE that in the host both queue headers are mapped r/w).
    + * But, each end-point needs read access to both Queue header
    + * structures in order to determine how much space is used (or left)
    + * in the Queue. This is because for an end-point to know how full
    + * its produceQ is, it needs to use the consumerHead that points into
    + * the produceQ but -that- consumerHead is in the Queue header for
    + * that end-points consumeQ.
    + *
    + * Thoroughly confused? Sorry.
    + *
    + * producerTail: the point to enqueue new entrants. When you approach
    + * a line in a store, for example, you walk up to the tail.
    + *
    + * consumerHead: the point in the queue from which the next element is
    + * dequeued. In other words, who is next in line is he who is at the
    + * head of the line.
    + *
    + * Also, producerTail points to an empty byte in the Queue, whereas
    + * consumerHead points to a valid byte of data (unless producerTail ==
    + * consumerHead in which case consumerHead does not point to a valid
    + * byte of data).
    + *
    + * For a queue of buffer 'size' bytes, the tail and head pointers will be in
    + * the range [0, size-1].
    + *
    + * If produceQHeader->producerTail == consumeQHeader->consumerHead
    + * then the produceQ is empty.
    + */
    +
    +struct vmci_queue_header {
    + /* All fields are 64bit and aligned. */
    + struct vmci_handle handle; /* Identifier. */
    + atomic64_t producerTail; /* Offset in this queue. */
    + atomic64_t consumerHead; /* Offset in peer queue. */
    +};
    +
    +/*
    + * If one client of a QueuePair is a 32bit entity, we restrict the QueuePair
    + * size to be less than 4GB, and use 32bit atomic operations on the head and
    + * tail pointers. 64bit atomic read on a 32bit entity involves cmpxchg8b which
    + * is an atomic read-modify-write. This will cause traces to fire when a 32bit
    + * consumer tries to read the producer's tail pointer, for example, because the
    + * consumer has read-only access to the producer's tail pointer.
    + *
    + * We provide the following macros to invoke 32bit or 64bit atomic operations
    + * based on the architecture the code is being compiled on.
    + */
    +
    +/* Architecture independent maximum queue size. */
    +#define QP_MAX_QUEUE_SIZE_ARCH_ANY CONST64U(0xffffffff)
    +
    +#ifdef __x86_64__
    +# define QP_MAX_QUEUE_SIZE_ARCH CONST64U(0xffffffffffffffff)
    +#else
    +# define QP_MAX_QUEUE_SIZE_ARCH CONST64U(0xffffffff)
    +#endif /* __x86_64__ */
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * QPAddPointer --
    + *
    + * Helper to add a given offset to a head or tail pointer. Wraps the value
    + * of the pointer around the max size of the queue.
    + *
    + * Results:
    + * None.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline void QPAddPointer(atomic64_t * var, // IN:
    + size_t add, // IN:
    + uint64_t size) // IN:
    +{
    + uint64_t newVal = atomic64_read(var);
    +
    + if (newVal >= size - add) {
    + newVal -= size;
    + }
    + newVal += add;
    +
    + atomic64_set(var, newVal);
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_ProducerTail() --
    + *
    + * Helper routine to get the Producer Tail from the supplied queue.
    + *
    + * Results:
    + * The contents of the queue's producer tail.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline uint64_t VMCIQueueHeader_ProducerTail(const struct vmci_queue_header *qHeader) // IN:
    +{
    + struct vmci_queue_header *qh = (struct vmci_queue_header *)qHeader;
    + return atomic64_read(&qh->producerTail);
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_ConsumerHead() --
    + *
    + * Helper routine to get the Consumer Head from the supplied queue.
    + *
    + * Results:
    + * The contents of the queue's consumer tail.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline uint64_t VMCIQueueHeader_ConsumerHead(const struct vmci_queue_header *qHeader) // IN:
    +{
    + struct vmci_queue_header *qh = (struct vmci_queue_header *)qHeader;
    + return atomic64_read(&qh->consumerHead);
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_AddProducerTail() --
    + *
    + * Helper routine to increment the Producer Tail. Fundamentally,
    + * QPAddPointer() is used to manipulate the tail itself.
    + *
    + * Results:
    + * None.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline void VMCIQueueHeader_AddProducerTail(struct vmci_queue_header *qHeader, // IN/OUT:
    + size_t add, // IN:
    + uint64_t queueSize) // IN:
    +{
    + QPAddPointer(&qHeader->producerTail, add, queueSize);
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_AddConsumerHead() --
    + *
    + * Helper routine to increment the Consumer Head. Fundamentally,
    + * QPAddPointer() is used to manipulate the head itself.
    + *
    + * Results:
    + * None.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline void VMCIQueueHeader_AddConsumerHead(struct vmci_queue_header *qHeader, // IN/OUT:
    + size_t add, // IN:
    + uint64_t queueSize) // IN:
    +{
    + QPAddPointer(&qHeader->consumerHead, add, queueSize);
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_CheckAlignment --
    + *
    + * Checks if the given queue is aligned to page boundary. Returns true if
    + * the alignment is good.
    + *
    + * Results:
    + * true or false.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline bool VMCIQueueHeader_CheckAlignment(const struct vmci_queue_header *qHeader) // IN:
    +{
    + uintptr_t hdr, offset;
    +
    + hdr = (uintptr_t) qHeader;
    + offset = hdr & (PAGE_SIZE - 1);
    +
    + return offset == 0;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_GetPointers --
    + *
    + * Helper routine for getting the head and the tail pointer for a queue.
    + * Both the VMCIQueues are needed to get both the pointers for one queue.
    + *
    + * Results:
    + * None.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline void VMCIQueueHeader_GetPointers(const struct vmci_queue_header *produceQHeader, // IN:
    + const struct vmci_queue_header *consumeQHeader, // IN:
    + uint64_t * producerTail, // OUT:
    + uint64_t * consumerHead) // OUT:
    +{
    + if (producerTail)
    + *producerTail = VMCIQueueHeader_ProducerTail(produceQHeader);
    +
    + if (consumerHead)
    + *consumerHead = VMCIQueueHeader_ConsumerHead(consumeQHeader);
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_ResetPointers --
    + *
    + * Reset the tail pointer (of "this" queue) and the head pointer (of
    + * "peer" queue).
    + *
    + * Results:
    + * None.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline void VMCIQueueHeader_ResetPointers(struct vmci_queue_header *qHeader) // IN/OUT:
    +{
    + atomic64_set(&qHeader->producerTail, CONST64U(0));
    + atomic64_set(&qHeader->consumerHead, CONST64U(0));
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_Init --
    + *
    + * Initializes a queue's state (head & tail pointers).
    + *
    + * Results:
    + * None.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline void VMCIQueueHeader_Init(struct vmci_queue_header *qHeader, // IN/OUT:
    + const struct vmci_handle handle) // IN:
    +{
    + qHeader->handle = handle;
    + VMCIQueueHeader_ResetPointers(qHeader);
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_FreeSpace --
    + *
    + * Finds available free space in a produce queue to enqueue more
    + * data or reports an error if queue pair corruption is detected.
    + *
    + * Results:
    + * Free space size in bytes or an error code.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline int64_t VMCIQueueHeader_FreeSpace(const struct vmci_queue_header *produceQHeader, // IN:
    + const struct vmci_queue_header *consumeQHeader, // IN:
    + const uint64_t produceQSize) // IN:
    +{
    + uint64_t tail;
    + uint64_t head;
    + uint64_t freeSpace;
    +
    + tail = VMCIQueueHeader_ProducerTail(produceQHeader);
    + head = VMCIQueueHeader_ConsumerHead(consumeQHeader);
    +
    + if (tail >= produceQSize || head >= produceQSize)
    + return VMCI_ERROR_INVALID_SIZE;
    +
    + /*
    + * Deduct 1 to avoid tail becoming equal to head which causes ambiguity. If
    + * head and tail are equal it means that the queue is empty.
    + */
    +
    + if (tail >= head) {
    + freeSpace = produceQSize - (tail - head) - 1;
    + } else {
    + freeSpace = head - tail - 1;
    + }
    +
    + return freeSpace;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIQueueHeader_BufReady --
    + *
    + * VMCIQueueHeader_FreeSpace() does all the heavy lifting of
    + * determing the number of free bytes in a Queue. This routine,
    + * then subtracts that size from the full size of the Queue so
    + * the caller knows how many bytes are ready to be dequeued.
    + *
    + * Results:
    + * On success, available data size in bytes (up to MAX_INT64).
    + * On failure, appropriate error code.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline int64_t VMCIQueueHeader_BufReady(const struct vmci_queue_header *consumeQHeader, // IN:
    + const struct vmci_queue_header *produceQHeader, // IN:
    + const uint64_t consumeQSize) // IN:
    +{
    + int64_t freeSpace;
    +
    + freeSpace = VMCIQueueHeader_FreeSpace(consumeQHeader,
    + produceQHeader, consumeQSize);
    + if (freeSpace < VMCI_SUCCESS) {
    + return freeSpace;
    + } else {
    + return consumeQSize - freeSpace - 1;
    + }
    +}
    +
    +#endif /* _VMCI_DEF_H_ */
    diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.h b/drivers/misc/vmw_vmci/vmci_handle_array.h
    new file mode 100644
    index 0000000..eb237e3
    --- /dev/null
    +++ b/drivers/misc/vmw_vmci/vmci_handle_array.h
    @@ -0,0 +1,339 @@
    +/*
    + *
    + * VMware VMCI Driver
    + *
    + * Copyright (C) 2012 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
    + */
    +
    +#ifndef _VMCI_HANDLE_ARRAY_H_
    +#define _VMCI_HANDLE_ARRAY_H_
    +
    +#include <linux/slab.h>
    +
    +#include "vmci_defs.h"
    +#include "vmci_kernel_if.h"
    +
    +#define VMCI_HANDLE_ARRAY_DEFAULT_SIZE 4
    +#define VMCI_ARR_CAP_MULT 2 /* Array capacity multiplier */
    +
    +struct vmci_handle_arr {
    + uint32_t capacity;
    + uint32_t size;
    + struct vmci_handle entries[1];
    +};
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_Create --
    + *
    + * Results:
    + * Array if successful, NULL if not.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline struct vmci_handle_arr *VMCIHandleArray_Create(uint32_t capacity)
    +{
    + struct vmci_handle_arr *array;
    +
    + if (capacity == 0)
    + capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
    +
    + array = (struct vmci_handle_arr *)kmalloc(sizeof array->capacity +
    + sizeof array->size +
    + capacity *
    + sizeof(struct
    + vmci_handle),
    + GFP_ATOMIC);
    + if (array == NULL)
    + return NULL;
    +
    + array->capacity = capacity;
    + array->size = 0;
    +
    + return array;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_Destroy --
    + *
    + * Results:
    + * None.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline void VMCIHandleArray_Destroy(struct vmci_handle_arr *array)
    +{
    + kfree(array);
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_AppendEntry --
    + *
    + * Results:
    + * None.
    + *
    + * Side effects:
    + * Array may be reallocated.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline void
    +VMCIHandleArray_AppendEntry(struct vmci_handle_arr **arrayPtr,
    + struct vmci_handle handle)
    +{
    + struct vmci_handle_arr *array;
    +
    + ASSERT(arrayPtr && *arrayPtr);
    + array = *arrayPtr;
    +
    + if (unlikely(array->size >= array->capacity)) {
    + /* reallocate. */
    + uint32_t arraySize =
    + sizeof array->capacity + sizeof array->size +
    + array->capacity * sizeof(struct vmci_handle) *
    + VMCI_ARR_CAP_MULT;
    + struct vmci_handle_arr *newArray = (struct vmci_handle_arr *)
    + kmalloc(arraySize, GFP_ATOMIC);
    +
    + if (newArray == NULL)
    + return;
    +
    + memcpy(newArray, array, arraySize);
    + newArray->capacity *= VMCI_ARR_CAP_MULT;
    + kfree(array);
    + *arrayPtr = newArray;
    + array = newArray;
    + }
    + array->entries[array->size] = handle;
    + array->size++;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_RemoveEntry --
    + *
    + * Results:
    + * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline struct vmci_handle
    +VMCIHandleArray_RemoveEntry(struct vmci_handle_arr *array,
    + struct vmci_handle entryHandle)
    +{
    + uint32_t i;
    + struct vmci_handle handle = VMCI_INVALID_HANDLE;
    +
    + ASSERT(array);
    + for (i = 0; i < array->size; i++) {
    + if (VMCI_HANDLE_EQUAL(array->entries[i], entryHandle)) {
    + handle = array->entries[i];
    + array->size--;
    + array->entries[i] = array->entries[array->size];
    + array->entries[array->size] = VMCI_INVALID_HANDLE;
    + break;
    + }
    + }
    +
    + return handle;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_RemoveTail --
    + *
    + * Results:
    + * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline struct vmci_handle
    +VMCIHandleArray_RemoveTail(struct vmci_handle_arr *array)
    +{
    + struct vmci_handle handle = VMCI_INVALID_HANDLE;
    +
    + if (array->size) {
    + array->size--;
    + handle = array->entries[array->size];
    + array->entries[array->size] = VMCI_INVALID_HANDLE;
    + }
    +
    + return handle;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_GetEntry --
    + *
    + * Results:
    + * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline struct vmci_handle
    +VMCIHandleArray_GetEntry(const struct vmci_handle_arr *array, uint32_t index)
    +{
    + ASSERT(array);
    +
    + if (unlikely(index >= array->size))
    + return VMCI_INVALID_HANDLE;
    +
    + return array->entries[index];
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_GetSize --
    + *
    + * Results:
    + * Number of entries in array.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline uint32_t
    +VMCIHandleArray_GetSize(const struct vmci_handle_arr *array)
    +{
    + ASSERT(array);
    + return array->size;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_HasEntry --
    + *
    + * Results:
    + * true is entry exists in array, false if not.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline bool
    +VMCIHandleArray_HasEntry(const struct vmci_handle_arr *array,
    + struct vmci_handle entryHandle)
    +{
    + uint32_t i;
    +
    + ASSERT(array);
    + for (i = 0; i < array->size; i++)
    + if (VMCI_HANDLE_EQUAL(array->entries[i], entryHandle))
    + return true;
    +
    + return false;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_GetCopy --
    + *
    + * Results:
    + * Returns pointer to copy of array on success or NULL, if memory allocation
    + * fails.
    + *
    + * Side effects:
    + * Allocates nonpaged memory.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline struct vmci_handle_arr *VMCIHandleArray_GetCopy(const struct
    + vmci_handle_arr
    + *array)
    +{
    + struct vmci_handle_arr *arrayCopy;
    +
    + ASSERT(array);
    +
    + arrayCopy =
    + (struct vmci_handle_arr *)kmalloc(sizeof array->capacity +
    + sizeof array->size +
    + array->size *
    + sizeof(struct vmci_handle),
    + GFP_ATOMIC);
    + if (arrayCopy != NULL) {
    + memcpy(&arrayCopy->size, &array->size,
    + sizeof array->size +
    + array->size * sizeof(struct vmci_handle));
    + arrayCopy->capacity = array->size;
    + }
    +
    + return arrayCopy;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------------
    + *
    + * VMCIHandleArray_GetHandles --
    + *
    + * Results:
    + * NULL if the array is empty. Otherwise, a pointer to the array
    + * of VMCI handles in the handle array.
    + *
    + * Side effects:
    + * None.
    + *
    + *-----------------------------------------------------------------------------------
    + */
    +
    +static inline struct vmci_handle *VMCIHandleArray_GetHandles(struct vmci_handle_arr *array) // IN
    +{
    + ASSERT(array);
    +
    + if (array->size)
    + return array->entries;
    +
    + return NULL;
    +}
    +
    +#endif // _VMCI_HANDLE_ARRAY_H_
    diff --git a/drivers/misc/vmw_vmci/vmci_infrastructure.h b/drivers/misc/vmw_vmci/vmci_infrastructure.h
    new file mode 100644
    index 0000000..04a9ba6
    --- /dev/null
    +++ b/drivers/misc/vmw_vmci/vmci_infrastructure.h
    @@ -0,0 +1,119 @@
    +/*
    + *
    + * VMware VMCI Driver
    + *
    + * Copyright (C) 2012 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
    + */
    +
    +#ifndef _VMCI_INFRASTRUCTURE_H_
    +#define _VMCI_INFRASTRUCTURE_H_
    +
    +#include "vmci_defs.h"
    +
    +typedef enum {
    + VMCIOBJ_VMX_VM = 10,
    + VMCIOBJ_CONTEXT,
    + VMCIOBJ_SOCKET,
    + VMCIOBJ_NOT_SET,
    +} VMCIObjType;
    +
    +/* For storing VMCI structures in file handles. */
    +typedef struct VMCIObj {
    + void *ptr;
    + VMCIObjType type;
    +} VMCIObj;
    +
    +/* Guestcalls currently support a maximum of 8 uint64_t arguments. */
    +#define VMCI_GUESTCALL_MAX_ARGS_SIZE 64
    +
    +/*
    + * Structure used for checkpointing the doorbell mappings. It is
    + * written to the checkpoint as is, so changing this structure will
    + * break checkpoint compatibility.
    + */
    +struct dbell_cpt_state {
    + struct vmci_handle handle;
    + uint64_t bitmapIdx;
    +};
    +
    +/* Used to determine what checkpoint state to get and set. */
    +#define VMCI_NOTIFICATION_CPT_STATE 0x1
    +#define VMCI_WELLKNOWN_CPT_STATE 0x2
    +#define VMCI_DG_OUT_STATE 0x3
    +#define VMCI_DG_IN_STATE 0x4
    +#define VMCI_DG_IN_SIZE_STATE 0x5
    +#define VMCI_DOORBELL_CPT_STATE 0x6
    +
    +/*
    + *-------------------------------------------------------------------------
    + *
    + * VMCI_Hash --
    + *
    + * Hash function used by the Simple Datagram API. Based on the djb2
    + * hash function by Dan Bernstein.
    + *
    + * Result:
    + * Returns guest call size.
    + *
    + * Side effects:
    + * None.
    + *
    + *-------------------------------------------------------------------------
    + */
    +
    +static inline int VMCI_Hash(struct vmci_handle handle, unsigned size)
    +{
    + unsigned i;
    + int hash = 5381;
    + const uint64_t handleValue = QWORD(handle.resource, handle.context);
    +
    + for (i = 0; i < sizeof handle; i++)
    + hash =
    + ((hash << 5) + hash) + (uint8_t) (handleValue >> (i * 8));
    +
    + return hash & (size - 1);
    +}
    +
    +/*
    + *-------------------------------------------------------------------------
    + *
    + * VMCI_HashId --
    + *
    + * Hash function used by the Simple Datagram API. Hashes only a VMCI id
    + * (not the full VMCI handle) Based on the djb2
    + * hash function by Dan Bernstein.
    + *
    + * Result:
    + * Returns guest call size.
    + *
    + * Side effects:
    + * None.
    + *
    + *-------------------------------------------------------------------------
    + */
    +
    +static inline int VMCI_HashId(uint32_t id, unsigned size)
    +{
    + unsigned i;
    + int hash = 5381;
    +
    + for (i = 0; i < sizeof id; i++)
    + hash = ((hash << 5) + hash) + (uint8_t) (id >> (i * 8));
    +
    + return hash & (size - 1);
    +}
    +
    +#endif // _VMCI_INFRASTRUCTURE_H_
    diff --git a/drivers/misc/vmw_vmci/vmci_iocontrols.h b/drivers/misc/vmw_vmci/vmci_iocontrols.h
    new file mode 100644
    index 0000000..06f5776
    --- /dev/null
    +++ b/drivers/misc/vmw_vmci/vmci_iocontrols.h
    @@ -0,0 +1,411 @@
    +/*
    + *
    + * VMware VMCI Driver
    + *
    + * Copyright (C) 2012 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
    + */
    +
    +#ifndef _VMCI_IOCONTROLS_H_
    +#define _VMCI_IOCONTROLS_H_
    +
    +#include "vmci_defs.h"
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIVA64ToPtr --
    + *
    + * Convert a VA64 to a pointer.
    + *
    + * Results:
    + * Virtual address.
    + *
    + * Side effects:
    + * None
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline void *VMCIVA64ToPtr(uint64_t va64) // IN
    +{
    +#ifdef CONFIG_X86_64
    + ASSERT_ON_COMPILE(sizeof(void *) == 8);
    +#else
    + ASSERT_ON_COMPILE(sizeof(void *) == 4);
    + /* Check that nothing of value will be lost. */
    + ASSERT(!(va64 >> 32));
    +#endif
    + return (void *)(uintptr_t) va64;
    +}
    +
    +/*
    + *-----------------------------------------------------------------------------
    + *
    + * VMCIPtrToVA64 --
    + *
    + * Convert a pointer to a uint64_t.
    + *
    + * Results:
    + * Virtual address.
    + *
    + * Side effects:
    + * None
    + *
    + *-----------------------------------------------------------------------------
    + */
    +
    +static inline uint64_t VMCIPtrToVA64(void const *ptr) // IN
    +{
    + ASSERT_ON_COMPILE(sizeof ptr <= sizeof(uint64_t));
    + return (uint64_t) (uintptr_t) ptr;
    +}
    +
    +/*
    + * Driver version.
    + *
    + * Increment major version when you make an incompatible change.
    + * Compatibility goes both ways (old driver with new executable
    + * as well as new driver with old executable).
    + */
    +#define VMCI_VERSION_SHIFT_WIDTH 16 /* Never change this. */
    +#define VMCI_MAKE_VERSION(_major, _minor) ((_major) << \
    + VMCI_VERSION_SHIFT_WIDTH | \
    + (uint16_t) (_minor))
    +#define VMCI_VERSION_MAJOR(v) ((uint32) (v) >> VMCI_VERSION_SHIFT_WIDTH)
    +#define VMCI_VERSION_MINOR(v) ((uint16_t) (v))
    +
    +/*
    + * VMCI_VERSION is always the current version. Subsequently listed
    + * versions are ways of detecting previous versions of the connecting
    + * application (i.e., VMX).
    + *
    + * VMCI_VERSION_NOVMVM: This version removed support for VM to VM
    + * communication.
    + *
    + * VMCI_VERSION_NOTIFY: This version introduced doorbell notification
    + * support.
    + *
    + * VMCI_VERSION_HOSTQP: This version introduced host end point support
    + * for hosted products.
    + *
    + * VMCI_VERSION_PREHOSTQP: This is the version prior to the adoption of
    + * support for host end-points.
    + *
    + * VMCI_VERSION_PREVERS2: This fictional version number is intended to
    + * represent the version of a VMX which doesn't call into the driver
    + * with ioctl VERSION2 and thus doesn't establish its version with the
    + * driver.
    + */
    +
    +#define VMCI_VERSION VMCI_VERSION_NOVMVM
    +#define VMCI_VERSION_NOVMVM VMCI_MAKE_VERSION(11, 0)
    +#define VMCI_VERSION_NOTIFY VMCI_MAKE_VERSION(10, 0)
    +#define VMCI_VERSION_HOSTQP VMCI_MAKE_VERSION(9, 0)
    +#define VMCI_VERSION_PREHOSTQP VMCI_MAKE_VERSION(8, 0)
    +#define VMCI_VERSION_PREVERS2 VMCI_MAKE_VERSION(1, 0)
    +
    +/*
    + * Linux defines _IO* macros, but the core kernel code ignore the encoded
    + * ioctl value. It is up to individual drivers to decode the value (for
    + * example to look at the size of a structure to determine which version
    + * of a specific command should be used) or not (which is what we
    + * currently do, so right now the ioctl value for a given command is the
    + * command itself).
    + *
    + * Hence, we just define the IOCTL_VMCI_foo values directly, with no
    + * intermediate IOCTLCMD_ representation.
    + */
    +# define IOCTLCMD(_cmd) IOCTL_VMCI_ ## _cmd
    +
    +enum IOCTLCmd_VMCI {
    + /*
    + * We need to bracket the range of values used for ioctls, because x86_64
    + * Linux forces us to explicitly register ioctl handlers by value for
    + * handling 32 bit ioctl syscalls. Hence FIRST and LAST. Pick something
    + * for FIRST that doesn't collide with vmmon (2001+).
    + */
    + IOCTLCMD(FIRST) = 1951,
    + IOCTLCMD(VERSION) = IOCTLCMD(FIRST),
    +
    + /* BEGIN VMCI */
    + IOCTLCMD(INIT_CONTEXT),
    +
    + /*
    + * The following two were used for process and datagram process creation.
    + * They are not used anymore and reserved for future use.
    + * They will fail if issued.
    + */
    + IOCTLCMD(RESERVED1),
    + IOCTLCMD(RESERVED2),
    +
    + /*
    + * The following used to be for shared memory. It is now unused and and is
    + * reserved for future use. It will fail if issued.
    + */
    + IOCTLCMD(RESERVED3),
    +
    + /*
    + * The follwoing three were also used to be for shared memory. An
    + * old WS6 user-mode client might try to use them with the new
    + * driver, but since we ensure that only contexts created by VMX'en
    + * of the appropriate version (VMCI_VERSION_NOTIFY or
    + * VMCI_VERSION_NEWQP) or higher use these ioctl, everything is
    + * fine.
    + */
    + IOCTLCMD(QUEUEPAIR_SETVA),
    + IOCTLCMD(NOTIFY_RESOURCE),
    + IOCTLCMD(NOTIFICATIONS_RECEIVE),
    + IOCTLCMD(VERSION2),
    + IOCTLCMD(QUEUEPAIR_ALLOC),
    + IOCTLCMD(QUEUEPAIR_SETPAGEFILE),
    + IOCTLCMD(QUEUEPAIR_DETACH),
    + IOCTLCMD(DATAGRAM_SEND),
    + IOCTLCMD(DATAGRAM_RECEIVE),
    + IOCTLCMD(DATAGRAM_REQUEST_MAP),
    + IOCTLCMD(DATAGRAM_REMOVE_MAP),
    + IOCTLCMD(CTX_ADD_NOTIFICATION),
    + IOCTLCMD(CTX_REMOVE_NOTIFICATION),
    + IOCTLCMD(CTX_GET_CPT_STATE),
    + IOCTLCMD(CTX_SET_CPT_STATE),
    + IOCTLCMD(GET_CONTEXT_ID),
    + /* END VMCI */
    +
    + /*
    + * BEGIN VMCI SOCKETS
    + * XXX: NEEDED?
    + *
    + * We mark the end of the vmci commands and the start of the vmci sockets
    + * commands since they are used in separate modules on Linux.
    + * */
    + IOCTLCMD(LAST),
    + IOCTLCMD(SOCKETS_FIRST) = IOCTLCMD(LAST),
    +
    + /*
    + * This used to be for accept() on Windows and Mac OS, which is now
    + * redundant (since we now use real handles). It is used instead for
    + * getting the version. This value is now public, so it cannot change.
    + */
    + IOCTLCMD(SOCKETS_VERSION) = IOCTLCMD(SOCKETS_FIRST),
    + IOCTLCMD(SOCKETS_BIND),
    +
    + /*
    + * This used to be for close() on Windows and Mac OS, but is no longer
    + * used for the same reason as accept() above. It is used instead for
    + * sending private symbols to the Mac OS driver.
    + */
    + IOCTLCMD(SOCKETS_SET_SYMBOLS),
    + IOCTLCMD(SOCKETS_CONNECT),
    +
    + /*
    + * The next two values are public (vmci_sockets.h) and cannot be changed.
    + * That means the number of values above these cannot be changed either
    + * unless the base index (specified below) is updated accordingly.
    + */
    + IOCTLCMD(SOCKETS_GET_AF_VALUE),
    + IOCTLCMD(SOCKETS_GET_LOCAL_CID),
    + IOCTLCMD(SOCKETS_GET_SOCK_NAME),
    + IOCTLCMD(SOCKETS_GET_SOCK_OPT),
    + IOCTLCMD(SOCKETS_GET_VM_BY_NAME),
    + IOCTLCMD(SOCKETS_IOCTL),
    + IOCTLCMD(SOCKETS_LISTEN),
    + IOCTLCMD(SOCKETS_RECV),
    + IOCTLCMD(SOCKETS_RECV_FROM),
    + IOCTLCMD(SOCKETS_SELECT),
    + IOCTLCMD(SOCKETS_SEND),
    + IOCTLCMD(SOCKETS_SEND_TO),
    + IOCTLCMD(SOCKETS_SET_SOCK_OPT),
    + IOCTLCMD(SOCKETS_SHUTDOWN),
    + IOCTLCMD(SOCKETS_SOCKET), /* 1990 on Linux. */
    + /* END VMCI SOCKETS */
    +
    + /*
    + * We reserve a range of 4 ioctls for VMCI Sockets to grow. We cannot
    + * reserve many ioctls here since we are close to overlapping with vmmon
    + * ioctls. Define a meta-ioctl if running out of this binary space.
    + *
    + * Must be last.
    + */
    + IOCTLCMD(SOCKETS_LAST) = IOCTLCMD(SOCKETS_SOCKET) + 4, /* 1994 on Linux. */
    +
    + /*
    + * The VSockets ioctls occupy the block above. We define a new range of
    + * VMCI ioctls to maintain binary compatibility between the user land and
    + * the kernel driver. Careful, vmmon ioctls start from 2001, so this means
    + * we can add only 4 new VMCI ioctls. Define a meta-ioctl if running out of
    + * this binary space.
    + */
    +
    + IOCTLCMD(FIRST2),
    + IOCTLCMD(SET_NOTIFY) = IOCTLCMD(FIRST2), /* 1995 on Linux. */
    + IOCTLCMD(LAST2),
    +};
    +
    +/* Clean up helper macros */
    +#undef IOCTLCMD
    +
    +/*
    + * VMCI driver initialization. This block can also be used to
    + * pass initial group membership etc.
    + */
    +struct vmci_init_blk {
    + uint32_t cid;
    + uint32_t flags;
    +};
    +
    +/* VMCIQueuePairAllocInfo_VMToVM */
    +struct vmci_qp_ai_vmvm {
    + struct vmci_handle handle;
    + uint32_t peer;
    + uint32_t flags;
    + uint64_t produceSize;
    + uint64_t consumeSize;
    + uint64_t producePageFile; /* User VA. */
    + uint64_t consumePageFile; /* User VA. */
    + uint64_t producePageFileSize; /* Size of the file name array. */
    + uint64_t consumePageFileSize; /* Size of the file name array. */
    + int32_t result;
    + uint32_t _pad;
    +};
    +
    +/* VMCIQueuePairAllocInfo */
    +struct vmci_qp_alloc_info {
    + struct vmci_handle handle;
    + uint32_t peer;
    + uint32_t flags;
    + uint64_t produceSize;
    + uint64_t consumeSize;
    + uint64_t ppnVA; /* Start VA of queue pair PPNs. */
    + uint64_t numPPNs;
    + int32_t result;
    + uint32_t version;
    +};
    +
    +/* VMCIQueuePairSetVAInfo */
    +struct vmci_qp_set_va_info {
    + struct vmci_handle handle;
    + uint64_t va; /* Start VA of queue pair PPNs. */
    + uint64_t numPPNs;
    + uint32_t version;
    + int32_t result;
    +};
    +
    +/*
    + * For backwards compatibility, here is a version of the
    + * VMCIQueuePairPageFileInfo before host support end-points was added.
    + * Note that the current version of that structure requires VMX to
    + * pass down the VA of the mapped file. Before host support was added
    + * there was nothing of the sort. So, when the driver sees the ioctl
    + * with a parameter that is the sizeof
    + * VMCIQueuePairPageFileInfo_NoHostQP then it can infer that the version
    + * of VMX running can't attach to host end points because it doesn't
    + * provide the VA of the mapped files.
    + *
    + * The Linux driver doesn't get an indication of the size of the
    + * structure passed down from user space. So, to fix a long standing
    + * but unfiled bug, the _pad field has been renamed to version.
    + * Existing versions of VMX always initialize the PageFileInfo
    + * structure so that _pad, er, version is set to 0.
    + *
    + * A version value of 1 indicates that the size of the structure has
    + * been increased to include two UVA's: produceUVA and consumeUVA.
    + * These UVA's are of the mmap()'d queue contents backing files.
    + *
    + * In addition, if when VMX is sending down the
    + * VMCIQueuePairPageFileInfo structure it gets an error then it will
    + * try again with the _NoHostQP version of the file to see if an older
    + * VMCI kernel module is running.
    + */
    +/* VMCIQueuePairPageFileInfo */
    +struct vmci_qp_page_file_info {
    + struct vmci_handle handle;
    + uint64_t producePageFile; /* User VA. */
    + uint64_t consumePageFile; /* User VA. */
    + uint64_t producePageFileSize; /* Size of the file name array. */
    + uint64_t consumePageFileSize; /* Size of the file name array. */
    + int32_t result;
    + uint32_t version; /* Was _pad. */
    + uint64_t produceVA; /* User VA of the mapped file. */
    + uint64_t consumeVA; /* User VA of the mapped file. */
    +};
    +
    +/* VMCIQueuePairDetachInfo */
    +struct vmci_qp_dtch_info {
    + struct vmci_handle handle;
    + int32_t result;
    + uint32_t _pad;
    +};
    +
    +/* VMCIDatagramSendRecvInfo */
    +struct vmci_dg_snd_rcv_info {
    + uint64_t addr;
    + uint32_t len;
    + int32_t result;
    +};
    +
    +/* VMCINotifyAddRemoveInfo: Used to add/remove remote context notifications. */
    +struct vmci_notify_add_rm_info {
    + uint32_t remoteCID;
    + int result;
    +};
    +
    +/* VMCICptBufInfo: Used to set/get current context's checkpoint state. */
    +struct vmci_chkpt_buf_info {
    + uint64_t cptBuf;
    + uint32_t cptType;
    + uint32_t bufSize;
    + int32_t result;
    + uint32_t _pad;
    +};
    +
    +/* VMCISetNotifyInfo: Used to pass notify flag's address to the host driver. */
    +struct vmci_set_notify_info {
    + uint64_t notifyUVA;
    + int32_t result;
    + uint32_t _pad;
    +};
    +
    +#define VMCI_NOTIFY_RESOURCE_QUEUE_PAIR 0
    +#define VMCI_NOTIFY_RESOURCE_DOOR_BELL 1
    +
    +#define VMCI_NOTIFY_RESOURCE_ACTION_NOTIFY 0
    +#define VMCI_NOTIFY_RESOURCE_ACTION_CREATE 1
    +#define VMCI_NOTIFY_RESOURCE_ACTION_DESTROY 2
    +
    +/*
    + * VMCINotifyResourceInfo: Used to create and destroy doorbells, and
    + * generate a notification for a doorbell or queue pair.
    + */
    +struct vmci_notify_rsrc_info {
    + struct vmci_handle handle;
    + uint16_t resource;
    + uint16_t action;
    + int32_t result;
    +};
    +
    +/*
    + * VMCINotificationReceiveInfo: Used to recieve pending notifications
    + * for doorbells and queue pairs.
    + */
    +struct vmci_notify_recv_info {
    + uint64_t dbHandleBufUVA;
    + uint64_t dbHandleBufSize;
    + uint64_t qpHandleBufUVA;
    + uint64_t qpHandleBufSize;
    + int32_t result;
    + uint32_t _pad;
    +};
    +
    +#endif // ifndef _VMCI_IOCONTROLS_H_
    diff --git a/drivers/misc/vmw_vmci/vmci_kernel_if.h b/drivers/misc/vmw_vmci/vmci_kernel_if.h
    new file mode 100644
    index 0000000..9b4e114
    --- /dev/null
    +++ b/drivers/misc/vmw_vmci/vmci_kernel_if.h
    @@ -0,0 +1,111 @@
    +/*
    + *
    + * VMware VMCI Driver
    + *
    + * Copyright (C) 2012 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
    + */
    +
    +/*
    + * This file defines helper functions for VMCI host _and_ guest
    + * kernel code.
    + */
    +
    +#ifndef _VMCI_KERNEL_IF_H_
    +#define _VMCI_KERNEL_IF_H_
    +
    +#include <linux/kernel.h>
    +#include <linux/wait.h>
    +
    +#include "vmci_defs.h"
    +
    +/* Callback needed for correctly waiting on events. */
    +typedef int (*VMCIEventReleaseCB) (void *clientData);
    +
    +/* Host specific struct used for signalling */
    +struct vmci_host {
    + wait_queue_head_t waitQueue;
    +};
    +
    +/* Guest device port I/O. */
    +bool VMCIHost_WaitForCallLocked(struct vmci_host *hostContext,
    + spinlock_t * lock,
    + unsigned long *flags, bool useBH);
    +
    +bool VMCIWellKnownID_AllowMap(uint32_t wellKnownID, uint32_t privFlags);
    +
    +int VMCIHost_CompareUser(uid_t * user1, uid_t * user2);
    +
    +void VMCI_WaitOnEvent(wait_queue_head_t * event,
    + VMCIEventReleaseCB releaseCB, void *clientData);
    +
    +bool VMCI_WaitOnEventInterruptible(wait_queue_head_t * event,
    + VMCIEventReleaseCB releaseCB,
    + void *clientData);
    +
    +typedef void (VMCIWorkFn) (void *data);
    +int VMCI_ScheduleDelayedWork(VMCIWorkFn * workFn, void *data);
    +
    +void *VMCI_AllocQueue(uint64_t size);
    +void VMCI_FreeQueue(void *q, uint64_t size);
    +struct PPNSet {
    + uint64_t numProducePages;
    + uint64_t numConsumePages;
    + uint32_t *producePPNs;
    + uint32_t *consumePPNs;
    + bool initialized;
    +};
    +int VMCI_AllocPPNSet(void *produceQ, uint64_t numProducePages,
    + void *consumeQ, uint64_t numConsumePages,
    + struct PPNSet *ppnSet);
    +void VMCI_FreePPNSet(struct PPNSet *ppnSet);
    +int VMCI_PopulatePPNList(uint8_t * callBuf, const struct PPNSet *ppnSet);
    +
    +struct vmci_queue;
    +
    +struct PageStoreAttachInfo;
    +struct vmci_queue *VMCIHost_AllocQueue(uint64_t queueSize);
    +void VMCIHost_FreeQueue(struct vmci_queue *queue, uint64_t queueSize);
    +
    +#define INVALID_VMCI_GUEST_MEM_ID 0
    +
    +struct QueuePairPageStore;
    +int VMCIHost_RegisterUserMemory(struct QueuePairPageStore *pageStore,
    + struct vmci_queue *produceQ,
    + struct vmci_queue *consumeQ);
    +void VMCIHost_UnregisterUserMemory(struct vmci_queue *produceQ,
    + struct vmci_queue *consumeQ);
    +int VMCIHost_MapQueueHeaders(struct vmci_queue *produceQ,
    + struct vmci_queue *consumeQ);
    +int VMCIHost_UnmapQueueHeaders(uint32_t gid,
    + struct vmci_queue *produceQ,
    + struct vmci_queue *consumeQ);
    +void VMCI_InitQueueMutex(struct vmci_queue *produceQ,
    + struct vmci_queue *consumeQ);
    +void VMCI_CleanupQueueMutex(struct vmci_queue *produceQ,
    + struct vmci_queue *consumeQ);
    +void VMCI_AcquireQueueMutex(struct vmci_queue *queue);
    +void VMCI_ReleaseQueueMutex(struct vmci_queue *queue);
    +
    +int VMCIHost_GetUserMemory(uint64_t produceUVA, uint64_t consumeUVA,
    + struct vmci_queue *produceQ,
    + struct vmci_queue *consumeQ);
    +void VMCIHost_ReleaseUserMemory(struct vmci_queue *produceQ,
    + struct vmci_queue *consumeQ);
    +
    +bool VMCI_GuestPersonalityActive(void);
    +bool VMCI_HostPersonalityActive(void);
    +
    +#endif // _VMCI_KERNEL_IF_H_
    --
    1.7.0.4


    \
     
     \ /
      Last update: 2012-02-15 02:19    [W:0.138 / U:0.728 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site