[PATCH 6/6] VSOCK: header and config files.

2013-01-08 Thread George Zhang
VSOCK header files, Makefiles and Kconfig systems for Linux VSocket module.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 Documentation/ioctl/ioctl-number.txt |1 
 include/linux/socket.h   |4 
 net/Kconfig  |1 
 net/Makefile |1 
 net/vmw_vsock/Kconfig|   14 +
 net/vmw_vsock/Makefile   |4 
 net/vmw_vsock/notify_qstate.c|  408 ++
 net/vmw_vsock/vmci_sockets.h |  270 +++
 net/vmw_vsock/vmci_sockets_packet.h  |   79 +++
 net/vmw_vsock/vsock_common.h |  103 +
 net/vmw_vsock/vsock_packet.h |   92 
 net/vmw_vsock/vsock_version.h|   22 ++
 12 files changed, 998 insertions(+), 1 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 2152b0e..df2b341 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -70,6 +70,7 @@ Code  Seq#(hex)   Include FileComments
 0x03   all linux/hdreg.h
 0x04   D2-DC   linux/umsdos_fs.h   Dead since 2.6.11, but don't reuse 
these.
 0x06   all linux/lp.h
+0x07   9F-D0   linux/vmw_vmci_defs.h   <mailto:georgezh...@vmware.com>
 0x09   all linux/raid/md_u.h
 0x10   00-0F   drivers/char/s390/vmcp.h
 0x12   all linux/fs.h
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 9a546ff..2c57d63 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -178,7 +178,8 @@ struct ucred {
 #define AF_CAIF37  /* CAIF sockets */
 #define AF_ALG 38  /* Algorithm sockets*/
 #define AF_NFC 39  /* NFC sockets  */
-#define AF_MAX 40  /* For now.. */
+#define AF_VSOCK   40  /* VMCI sockets */
+#define AF_MAX 41  /* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC  AF_UNSPEC
@@ -221,6 +222,7 @@ struct ucred {
 #define PF_CAIFAF_CAIF
 #define PF_ALG AF_ALG
 #define PF_NFC AF_NFC
+#define PF_VSOCK   AF_VSOCK
 #define PF_MAX AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/net/Kconfig b/net/Kconfig
index 30b48f5..f143ac3 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -218,6 +218,7 @@ source "net/dcb/Kconfig"
 source "net/dns_resolver/Kconfig"
 source "net/batman-adv/Kconfig"
 source "net/openvswitch/Kconfig"
+source "net/vmw_vsock/Kconfig"
 
 config RPS
boolean
diff --git a/net/Makefile b/net/Makefile
index 4f4ee08..cae59f4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_CEPH_LIB)+= ceph/
 obj-$(CONFIG_BATMAN_ADV)   += batman-adv/
 obj-$(CONFIG_NFC)  += nfc/
 obj-$(CONFIG_OPENVSWITCH)  += openvswitch/
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock/
diff --git a/net/vmw_vsock/Kconfig b/net/vmw_vsock/Kconfig
new file mode 100644
index 000..95e2568
--- /dev/null
+++ b/net/vmw_vsock/Kconfig
@@ -0,0 +1,14 @@
+#
+# Vsock protocol
+#
+
+config VMWARE_VSOCK
+   tristate "Virtual Socket protocol"
+   depends on VMWARE_VMCI
+   help
+ Virtual Socket Protocol is a socket protocol similar to TCP/IP
+ allowing comunication between Virtual Machines and VMware
+ hypervisor.
+
+ To compile this driver as a module, choose M here: the module
+ will be called vsock. If unsure, say N.
diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile
new file mode 100644
index 000..4e940fe
--- /dev/null
+++ b/net/vmw_vsock/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock.o
+
+vmw_vsock-y += af_vsock.o notify.o notify_qstate.o stats.o util.o \
+   vsock_addr.o
diff --git a/net/vmw_vsock/notify_qstate.c b/net/vmw_vsock/notify_qstate.c
new file mode 100644
index 000..1132ae4
--- /dev/null
+++ b/net/vmw_vsock/notify_qstate.c
@@ -0,0 +1,408 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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 MERCHA

[PATCH 5/6] VSOCK: utility functions.

2013-01-08 Thread George Zhang
VSOCK utility functions for Linux VSocket module.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 net/vmw_vsock/util.c |  345 ++
 net/vmw_vsock/util.h |  187 +++
 2 files changed, 532 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h

diff --git a/net/vmw_vsock/util.c b/net/vmw_vsock/util.c
new file mode 100644
index 000..b77cafa
--- /dev/null
+++ b/net/vmw_vsock/util.c
@@ -0,0 +1,345 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "af_vsock.h"
+#include "util.h"
+
+struct list_head vsock_bind_table[VSOCK_HASH_SIZE + 1];
+struct list_head vsock_connected_table[VSOCK_HASH_SIZE];
+
+DEFINE_SPINLOCK(vsock_table_lock);
+
+void vsock_vmci_log_pkt(char const *function, u32 line,
+   struct vsock_packet *pkt)
+{
+   char buf[256];
+   char *cur = buf;
+   int left = sizeof(buf);
+   int written = 0;
+   char *type_strings[] = {
+   [VSOCK_PACKET_TYPE_INVALID] = "INVALID",
+   [VSOCK_PACKET_TYPE_REQUEST] = "REQUEST",
+   [VSOCK_PACKET_TYPE_NEGOTIATE] = "NEGOTIATE",
+   [VSOCK_PACKET_TYPE_OFFER] = "OFFER",
+   [VSOCK_PACKET_TYPE_ATTACH] = "ATTACH",
+   [VSOCK_PACKET_TYPE_WROTE] = "WROTE",
+   [VSOCK_PACKET_TYPE_READ] = "READ",
+   [VSOCK_PACKET_TYPE_RST] = "RST",
+   [VSOCK_PACKET_TYPE_SHUTDOWN] = "SHUTDOWN",
+   [VSOCK_PACKET_TYPE_WAITING_WRITE] = "WAITING_WRITE",
+   [VSOCK_PACKET_TYPE_WAITING_READ] = "WAITING_READ",
+   [VSOCK_PACKET_TYPE_REQUEST2] = "REQUEST2",
+   [VSOCK_PACKET_TYPE_NEGOTIATE2] = "NEGOTIATE2",
+   };
+
+   written = snprintf(cur, left, "PKT: %u:%u -> %u:%u",
+  pkt->dg.src.context, pkt->src_port,
+  pkt->dg.dst.context, pkt->dst_port);
+   if (written >= left)
+   goto error;
+
+   left -= written;
+   cur += written;
+
+   switch (pkt->type) {
+   case VSOCK_PACKET_TYPE_REQUEST:
+   case VSOCK_PACKET_TYPE_NEGOTIATE:
+   written = snprintf(cur, left, ", %s, size = %" FMT64 "u",
+  type_strings[pkt->type], pkt->u.size);
+   break;
+
+   case VSOCK_PACKET_TYPE_OFFER:
+   case VSOCK_PACKET_TYPE_ATTACH:
+   written = snprintf(cur, left, ", %s, handle = %u:%u",
+  type_strings[pkt->type],
+  pkt->u.handle.context,
+  pkt->u.handle.resource);
+   break;
+
+   case VSOCK_PACKET_TYPE_WROTE:
+   case VSOCK_PACKET_TYPE_READ:
+   case VSOCK_PACKET_TYPE_RST:
+   written = snprintf(cur, left, ", %s", type_strings[pkt->type]);
+   break;
+   case VSOCK_PACKET_TYPE_SHUTDOWN: {
+   bool recv;
+   bool send;
+
+   recv = pkt->u.mode & RCV_SHUTDOWN;
+   send = pkt->u.mode & SEND_SHUTDOWN;
+   written = snprintf(cur, left, ", %s, mode = %c%c",
+  type_strings[pkt->type],
+  recv ? 'R' : ' ', send ? 'S' : ' ');
+   }
+   break;
+
+   case VSOCK_PACKET_TYPE_WAITING_WRITE:
+   case VSOCK_PACKET_TYPE_WAITING_READ:
+   written = snprintf(cur, left,
+   ", %s, generation = %" FMT64 "u, offset = %" FMT64 "u",
+   type_strings[pkt->type],
+   pkt->u.wait.generation, pkt->u.wait.offset);
+
+   break;
+
+   case VSOCK_PACKET_TYPE_REQUEST2:
+   case VSOCK_PACKET_TYPE_NEGOTIATE2:
+   written = snprintf(cur, left,
+  ", %s, size = %" FMT64 "u, proto = %u",
+  type_strings[pkt->type], pkt->u.size,

[PATCH 4/6] VSOCK: statistics implementation.

2013-01-08 Thread George Zhang
VSOCK stats for VMCI Stream Sockets protocol.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 net/vmw_vsock/stats.c |   30 ++
 net/vmw_vsock/stats.h |  150 +
 2 files changed, 180 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h

diff --git a/net/vmw_vsock/stats.c b/net/vmw_vsock/stats.c
new file mode 100644
index 000..49e09bb
--- /dev/null
+++ b/net/vmw_vsock/stats.c
@@ -0,0 +1,30 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "af_vsock.h"
+#include "stats.h"
+
+#ifdef VSOCK_GATHER_STATISTICS
+u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+atomic64_t vsock_stats_consume_total;
+atomic64_t vsock_stats_produce_total;
+#endif
diff --git a/net/vmw_vsock/stats.h b/net/vmw_vsock/stats.h
new file mode 100644
index 000..07e2bf0
--- /dev/null
+++ b/net/vmw_vsock/stats.h
@@ -0,0 +1,150 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+#ifndef __STATS_H__
+#define __STATS_H__
+
+#include 
+
+#include "vsock_common.h"
+#include "vsock_packet.h"
+
+/* Define VSOCK_GATHER_STATISTICS to turn on statistics gathering. Currently
+ * this consists of 3 types of stats: 1. The number of control datagram
+ * messages sent. 2. The level of queuepair fullness (in 10% buckets) whenever
+ * data is about to be enqueued or dequeued from the queuepair. 3. The total
+ * number of bytes enqueued/dequeued.
+ */
+
+#ifdef VSOCK_GATHER_STATISTICS
+
+#define VSOCK_NUM_QUEUE_LEVEL_BUCKETS 10
+extern u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+extern u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern atomic64_t vsock_stats_consume_total;
+extern atomic64_t vsock_stats_produce_total;
+
+#define VSOCK_STATS_STREAM_CONSUME_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->consume_size,\
+   vmci_qpair_consume_buf_ready((vsk)->qpair), \
+   vsock_stats_consume_queue_hist)
+#define VSOCK_STATS_STREAM_PRODUCE_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->produce_size,\
+   vmci_qpair_produce_buf_ready((vsk)->qpair), \
+   vsock_stats_produce_queue_hist)
+#define VSOCK_STATS_CTLPKT_LOG(pkt_type)   \
+   (++vsock_stats_ctl_pkt_count[pkt_type])
+#define VSOCK_STATS_STREAM_CONSUME(bytes)  \
+   atomic64_add(&vsock_stats_consume_total, bytes)
+#define VSOCK_STATS_STREAM_PRODUCE(bytes)  \
+   atomic64_add(&vsock_stats_produce_total, bytes)
+#define VSOCK_STATS_CTLPKT_DUMP_ALL() vsock_vmci_stats_ctl_pkt_dump_all()
+#define VSOCK_STATS_HIST_DUMP_ALL()   vsock_vmci_stats_hist_dump_all()
+#define VSOCK_STATS_TOTALS_DUMP_ALL() vsock_vmci_stats_totals_dump_all()
+#define VSOCK_STATS_RESET()   vsock_vmci_stats_reset()
+
+static inline void
+vsock_vmci_stats_update_queue_bucket_count(vmci_qpair *qpair,
+  u64 queue_size,
+  u64 data_ready,
+  u64 queue_hist[])
+{
+   u64 bucket = 0;
+   u32 remainder = 0;
+
+   /* We can't do 64 / 64 = 64 bit divides on linux because it requires a
+* libgcc which is not linked into the kernel module. Since this code
+* is only use

[PATCH 3/6] VSOCK: notification implementation.

2013-01-08 Thread George Zhang
VSOCK control notifications for VMCI Stream Sockets protocol.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 net/vmw_vsock/notify.c |  675 
 net/vmw_vsock/notify.h |  124 +
 2 files changed, 799 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h

diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c
new file mode 100644
index 000..23bad8b
--- /dev/null
+++ b/net/vmw_vsock/notify.c
@@ -0,0 +1,675 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) ((vsk)->notify.pkt.field_name)
+
+#define VSOCK_MAX_DGRAM_RESENDS   10
+
+static bool vsock_vmci_notify_waiting_write(struct vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+   bool retval;
+   u64 notify_limit;
+
+   if (!PKT_FIELD(vsk, peer_waiting_write))
+   return false;
+
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   /* When the sender blocks, we take that as a sign that the sender is
+* faster than the receiver. To reduce the transmit rate of the sender,
+* we delay the sending of the read notification by decreasing the
+* write_notify_window. The notification is delayed until the number of
+* bytes used in the queue drops below the write_notify_window.
+*/
+
+   if (!PKT_FIELD(vsk, peer_waiting_write_detected)) {
+   PKT_FIELD(vsk, peer_waiting_write_detected) = true;
+   if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) {
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+   } else {
+   PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE;
+   if (PKT_FIELD(vsk, write_notify_window) <
+   PKT_FIELD(vsk, write_notify_min_window))
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+
+   }
+   }
+   notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window);
+#else
+   notify_limit = 0;
+#endif
+
+   /* For now we ignore the wait information and just see if the free
+* space exceeds the notify limit.  Note that improving this function
+* to be more intelligent will not require a protocol change and will
+* retain compatibility between endpoints with mixed versions of this
+* function.
+*
+* The notify_limit is used to delay notifications in the case where
+* flow control is enabled. Below the test is expressed in terms of
+* free space in the queue: if free_space > ConsumeSize -
+* write_notify_window then notify An alternate way of expressing this
+* is to rewrite the expression to use the data ready in the receive
+* queue: if write_notify_window > bufferReady then notify as
+* free_space == ConsumeSize - bufferReady.
+*/
+   retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit;
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   if (retval) {
+   /*
+* Once we notify the peer, we reset the detected flag so the
+* next wait will again cause a decrease in the window size.
+*/
+
+   PKT_FIELD(vsk, peer_waiting_write_detected) = false;
+   }
+#endif
+   return retval;
+#else
+   return true;
+#endif
+}
+
+static bool vsock_vmci_notify_waiting_read(struct vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+   if (!PKT_FIELD(vsk, peer_waiting_read))
+   return false;
+
+   /* For now we ignore the wait information and just see if there is any
+* data for our peer to read.  Note that improving this function to be
+* more intelligent will not require a protocol change and will retain
+* compatibility between endpoints with mixed versions of this
+* function.
+*/
+   return vmci_qpair_produce_buf_ready(vsk->qpair) > 0;
+#else
+   return true;
+#endif
+}
+
+static void
+vsock_vmci_handle_waiting_read(struct sock *sk,

[PATCH 2/6] VSOCK: vsock address implementaion.

2013-01-08 Thread George Zhang
VSOCK linux address code implementation.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 net/vmw_vsock/vsock_addr.c |  116 
 net/vmw_vsock/vsock_addr.h |   34 +
 2 files changed, 150 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h

diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
new file mode 100644
index 000..9564576
--- /dev/null
+++ b/net/vmw_vsock/vsock_addr.c
@@ -0,0 +1,116 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vsock_common.h"
+
+void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port)
+{
+   memset(addr, 0, sizeof(*addr));
+   addr->svm_family = AF_VSOCK;
+   addr->svm_cid = cid;
+   addr->svm_port = port;
+}
+
+int vsock_addr_validate(const struct sockaddr_vm *addr)
+{
+   if (!addr)
+   return -EFAULT;
+
+   if (addr->svm_family != AF_VSOCK)
+   return -EAFNOSUPPORT;
+
+   if (addr->svm_zero[0] != 0)
+   return -EINVAL;
+
+   return 0;
+}
+
+bool vsock_addr_bound(const struct sockaddr_vm *addr)
+{
+   return addr->svm_port != VMADDR_PORT_ANY;
+}
+
+void vsock_addr_unbind(struct sockaddr_vm *addr)
+{
+   vsock_addr_init(addr, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+}
+
+bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   return addr->svm_cid == other->svm_cid &&
+   addr->svm_port == other->svm_port;
+}
+
+bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   return (addr->svm_cid == VMADDR_CID_ANY ||
+   other->svm_cid == VMADDR_CID_ANY ||
+   addr->svm_cid == other->svm_cid) &&
+  addr->svm_port == other->svm_port;
+}
+
+bool vsock_addr_equals_handle_port(const struct sockaddr_vm *addr,
+  struct vmci_handle handle, u32 port)
+{
+   return addr->svm_cid == handle.context && addr->svm_port == port;
+}
+
+int vsock_addr_cast(const struct sockaddr *addr,
+   size_t len, struct sockaddr_vm **out_addr)
+{
+   if (len < sizeof(**out_addr))
+   return -EFAULT;
+
+   *out_addr = (struct sockaddr_vm *)addr;
+   return vsock_addr_validate(*out_addr);
+}
+
+bool vsock_addr_socket_context_stream(u32 cid)
+{
+   static const u32 non_socket_contexts[] = {
+   VMCI_HYPERVISOR_CONTEXT_ID,
+   VMCI_WELL_KNOWN_CONTEXT_ID,
+   };
+   int i;
+
+   BUILD_BUG_ON(sizeof(cid) != sizeof(*non_socket_contexts));
+
+   for (i = 0; i < ARRAY_SIZE(non_socket_contexts); i++) {
+   if (cid == non_socket_contexts[i])
+   return false;
+
+   }
+
+   return true;
+}
+
+bool vsock_addr_socket_context_dgram(u32 cid, u32 rid)
+{
+   if (cid == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /* Registrations of PBRPC Servers do not modify VMX/Hypervisor
+* state and are allowed.
+*/
+   return rid == VMCI_UNITY_PBRPC_REGISTER;
+   }
+
+   return true;
+}
diff --git a/net/vmw_vsock/vsock_addr.h b/net/vmw_vsock/vsock_addr.h
new file mode 100644
index 000..65c4bcf
--- /dev/null
+++ b/net/vmw_vsock/vsock_addr.h
@@ -0,0 +1,34 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+#ifndef _VSOCK_ADDR_H_
+#define _VSOCK_ADDR_H_
+
+void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port);
+int vsock_addr_validate(const struct sockaddr_vm *addr);
+bool vsock_addr_bound(const struct sockaddr_vm *addr);
+void vsock_addr_unbind(struct sockaddr_vm *addr);

[PATCH 0/6] VSOCK for Linux upstreaming

2013-01-08 Thread George Zhang

* * *

This series of VSOCK linux upstreaming patches include latest udpate from
VMware to address Greg's and all other's code review comments.

Summary of changes:
- Rebase our linux kernel tree from v3.5 to v3.7.
- Fix all checkpatch warnings and errors. Fix some checkpatch with 
-strict
  errors.

  This addresses Greg's comment: On 15 Nov 2012 15:47:14 -0800
  Re: [PATCH 07/12] VMCI: queue pairs implementation.
  chckpatch sanity checking.
- Fix vmci_get_contextid naming error.
- Remove ASSERT/BUG_ON for vmci and vsock source codes.

  This addresses ddress Greg's comment on On 15 Nov 2012 15:47:14 
-0800
  Re: [PATCH 02/12] VMCI: datagram implementation.
  Remove all BUG_ON(), asserts.
- use standard Linux kernel ioctl interface.

  This addresses Greg's comment on On Thu, 15 Nov 2012 16:01:18 
-0800
  Re: [PATCH 12/12] VMCI: Some header and config files.
  use linux in-kernel IO macros for VMCI.
- Add vmci ioctl code entry in ioctl-number.txt.
- Remove printk from header file. Align properly for macro 
PCI_VENDOR_ID_VMWARE.
  Remove #define for VMCI_DRIVER_VERSION_STRING.
  Remove #define for MODULE_NAME.
  Remove #define for pr_fmt and #define ASSERT(x).
  Remove inline function VMCI_MAKE_HANDLE and vmci_make_handle which 
return a
  structure on stack. use macro instead and use C99 initialization.
  Remove #define for VMCI_HANDLE_TO_CONTEXT_ID and 
VMCI_HANDLE_TO_RESOURCE_ID
  Change macro to inline function for VMCI_HANDLE_EQUAL.
  Remove u32 typedefs for vmci_id, vmci_event, vmci_privilege_flags.
  Use C99 style initialization for struct VMCI_INVALID_HANDLE.
  Use inline function instead of macro for VMCI_HANDLE_INVALID.
  No change for vmw_vmci_api.h location (under include/linux/ 
directory).
  No change for macros VMCI_CONTEXT_IS_VM, VMCI_HOST_CONTEXT_ID,
  VMCI_RESERVED_CID_LIMIT, VMCI_HYPERVISOR_CONTEXT_ID and
  VMCI_WELL_KNOWN_CONTEXT_ID. Still in header file 
include/linux/vmw_vmci_defs.h

  This addresses Greg's several comments on Thu, 15 Nov 2012 
16:01:18 -0800
  Re: [PATCH 12/12] VMCI: Some header and config files.


* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets (VSOCK)
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vsock kernel
module. The vmw_vmci kernel module has been presented in an early post.


* * *

VMCI Sockets allows virtual machines to communicate with host kernel
modules and the VMware hypervisors. VMCI Sockets kernel module has
dependency on VMCI kernel module. User level applications both in
a virtual machine and on the host can use vmw_vmci through VMCI
Sockets API which facilitates fast and efficient communication
between guest virtual machines and their host. A socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

The VMware VMCI Sockets are similar to other socket types, like
Berkeley UNIX socket interface. The VMCI sockets module supports
both connection-oriented stream sockets like TCP, and connectionless
datagram sockets like UDP. The VSOCK protocol family is defined as
"AF_VSOCK" and the socket operations split for SOCK_DGRAM and
SOCK_STREAM.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.

---

George Zhang (6):
  VSOCK: vsock protocol implementation.
  VSOCK: vsock address implementaion.
  VSOCK: notification implementation.
  VSOCK: statistics implementation.
  VSOCK: utility functions.
  VSOCK: header and config files.


 Documentation/ioctl/ioctl-number.txt |1 
 include/linux/socket.h   |4 
 net/Kconfig  |1 
 net/Makefile |1 
 net/vmw_vsock/Kconfig|   14 
 net/vmw_vsock/Makefile   |4 
 net/vmw_vsock/af_vsock.c | 3279 

[PATCH 12/12] VMCI: Some header and config files.

2013-01-08 Thread George Zhang
VMCI head config patch Adds all the necessary files to enable building of the 
VMCI
module with the Linux Makefiles and Kconfig systems. Also adds the header files 
used
for building modules against the driver.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/Kconfig   |1 
 drivers/misc/Makefile  |2 
 drivers/misc/vmw_vmci/Kconfig  |   16 +
 drivers/misc/vmw_vmci/Makefile |4 
 include/linux/vmw_vmci_api.h   |   82 
 include/linux/vmw_vmci_defs.h  |  880 
 6 files changed, 985 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/Kconfig
 create mode 100644 drivers/misc/vmw_vmci/Makefile
 create mode 100644 include/linux/vmw_vmci_api.h
 create mode 100644 include/linux/vmw_vmci_defs.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b151b7c..264e647 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -507,4 +507,5 @@ source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
+source "drivers/misc/vmw_vmci/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 2129377..5c99726 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -49,3 +49,5 @@ obj-y += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)+= mei/
+obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
+obj-$(CONFIG_VMWARE_VMCI)  += vmw_vmci/
diff --git a/drivers/misc/vmw_vmci/Kconfig b/drivers/misc/vmw_vmci/Kconfig
new file mode 100644
index 000..55015e7
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Kconfig
@@ -0,0 +1,16 @@
+#
+# VMware VMCI device
+#
+
+config VMWARE_VMCI
+   tristate "VMware VMCI Driver"
+   depends on X86
+   help
+ This is VMware's Virtual Machine Communication Interface.  It enables
+ high-speed communication between host and guest in a virtual
+ environment via the VMCI virtual device.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vmw_vmci.
diff --git a/drivers/misc/vmw_vmci/Makefile b/drivers/misc/vmw_vmci/Makefile
new file mode 100644
index 000..4da9893
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci.o
+vmw_vmci-y += vmci_context.o vmci_datagram.o vmci_doorbell.o \
+   vmci_driver.o vmci_event.o vmci_guest.o vmci_handle_array.o \
+   vmci_host.o vmci_queue_pair.o vmci_resource.o vmci_route.o
diff --git a/include/linux/vmw_vmci_api.h b/include/linux/vmw_vmci_api.h
new file mode 100644
index 000..023430e
--- /dev/null
+++ b/include/linux/vmw_vmci_api.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef __VMW_VMCI_API_H__
+#define __VMW_VMCI_API_H__
+
+#include 
+#include 
+
+#undef  VMCI_KERNEL_API_VERSION
+#define VMCI_KERNEL_API_VERSION_1 1
+#define VMCI_KERNEL_API_VERSION_2 2
+#define VMCI_KERNEL_API_VERSION   VMCI_KERNEL_API_VERSION_2
+
+typedef void (vmci_device_shutdown_fn) (void *device_registration,
+   void *user_data);
+
+int vmci_datagram_create_handle(u32 resource_id, u32 flags,
+   vmci_datagram_recv_cb recv_cb,
+   void *client_data,
+   struct vmci_handle *out_handle);
+int vmci_datagram_create_handle_priv(u32 resource_id, u32 flags, u32 
priv_flags,
+vmci_datagram_recv_cb recv_cb,
+void *client_data,
+struct vmci_handle *out_handle);
+int vmci_datagram_destroy_handle(struct vmci_handle handle);
+int vmci_datagram_send(struct vmci_datagram *msg);
+int vmci_doorbell_create(struct vmci_handle *handle, u32 flags,
+u32 priv_flags,
+vmci_callback notify_cb, void *client_data);
+int vmci_doorbell_destroy(struct vmci_handle handle);
+int vmci_doorbell_notify(struct vmci_handle handle, u32 priv_flags);
+u32 vmci_get_context_id(void);
+bool vmci_is_context_owner(u32 context_id, kuid_t uid);
+
+int vmci_event_subscribe(u32 event,
+  

[PATCH 11/12] VMCI: host side driver implementation.

2013-01-08 Thread George Zhang
VMCI host side driver code implementation.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_host.c | 1042 +
 1 files changed, 1042 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_host.c

diff --git a/drivers/misc/vmw_vmci/vmci_host.c 
b/drivers/misc/vmw_vmci/vmci_host.c
new file mode 100644
index 000..16e7f54
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_host.c
@@ -0,0 +1,1042 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_handle_array.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+enum {
+   VMCI_NOTIFY_RESOURCE_QUEUE_PAIR = 0,
+   VMCI_NOTIFY_RESOURCE_DOOR_BELL = 1,
+};
+
+enum {
+   VMCI_NOTIFY_RESOURCE_ACTION_NOTIFY = 0,
+   VMCI_NOTIFY_RESOURCE_ACTION_CREATE = 1,
+   VMCI_NOTIFY_RESOURCE_ACTION_DESTROY = 2,
+};
+
+/*
+ * VMCI driver initialization. This block can also be used to
+ * pass initial group membership etc.
+ */
+struct vmci_init_blk {
+   u32 cid;
+   u32 flags;
+};
+
+/* VMCIqueue_pairAllocInfo_VMToVM */
+struct vmci_qp_alloc_info_vmvm {
+   struct vmci_handle handle;
+   u32 peer;
+   u32 flags;
+   u64 produce_size;
+   u64 consume_size;
+   u64 produce_page_file;/* User VA. */
+   u64 consume_page_file;/* User VA. */
+   u64 produce_page_file_size;  /* Size of the file name array. */
+   u64 consume_page_file_size;  /* Size of the file name array. */
+   s32 result;
+   u32 _pad;
+};
+
+/* VMCISetNotifyInfo: Used to pass notify flag's address to the host driver. */
+struct vmci_set_notify_info {
+   u64 notify_uva;
+   s32 result;
+   u32 _pad;
+};
+
+/*
+ * Per-instance host state
+ */
+struct vmci_host_dev {
+   struct vmci_ctx *context;
+   int user_version;
+   enum vmci_obj_type ct_type;
+   struct mutex lock;  /* Mutex lock for vmci context access */
+};
+
+static struct vmci_ctx *host_context;
+static bool vmci_host_device_initialized;
+static atomic_t vmci_host_active_users = ATOMIC_INIT(0);
+
+/*
+ * Determines whether the VMCI host personality is
+ * available. Since the core functionality of the host driver is
+ * always present, all guests could possibly use the host
+ * personality. However, to minimize the deviation from the
+ * pre-unified driver state of affairs, we only consider the host
+ * device active if there is no active guest device or if there
+ * are VMX'en with active VMCI contexts using the host device.
+ */
+bool vmci_host_code_active(void)
+{
+   return vmci_host_device_initialized &&
+   (!vmci_guest_code_active() ||
+atomic_read(&vmci_host_active_users) > 0);
+}
+
+/*
+ * Called on open of /dev/vmci.
+ */
+static int vmci_host_open(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev;
+
+   vmci_host_dev = kzalloc(sizeof(struct vmci_host_dev), GFP_KERNEL);
+   if (vmci_host_dev == NULL)
+   return -ENOMEM;
+
+   vmci_host_dev->ct_type = VMCIOBJ_NOT_SET;
+   mutex_init(&vmci_host_dev->lock);
+   filp->private_data = vmci_host_dev;
+
+   return 0;
+}
+
+/*
+ * Called on close of /dev/vmci, most often when the process
+ * exits.
+ */
+static int vmci_host_close(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev = filp->private_data;
+
+   if (vmci_host_dev->ct_type == VMCIOBJ_CONTEXT) {
+   vmci_ctx_destroy(vmci_host_dev->context);
+   vmci_host_dev->context = NULL;
+
+   /*
+* The number of active contexts is used to track whether any
+* VMX'en are using the host personality. It is incremented when
+* a context is created through the IOCTL_VMCI_INIT_CONTEXT
+* ioctl.
+*/
+   atomic_dec(&vmci_host_active_users);
+   

[PATCH 10/12] VMCI: guest side driver implementation.

2013-01-08 Thread George Zhang
VMCI guest side driver code implementation.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_guest.c |  759 
 1 files changed, 759 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_guest.c

diff --git a/drivers/misc/vmw_vmci/vmci_guest.c 
b/drivers/misc/vmw_vmci/vmci_guest.c
new file mode 100644
index 000..d302c89
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -0,0 +1,759 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define PCI_VENDOR_ID_VMWARE   0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMCI  0x0740
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+static bool vmci_disable_msi;
+module_param_named(disable_msi, vmci_disable_msi, bool, 0);
+MODULE_PARM_DESC(disable_msi, "Disable MSI use in driver - (default=0)");
+
+static bool vmci_disable_msix;
+module_param_named(disable_msix, vmci_disable_msix, bool, 0);
+MODULE_PARM_DESC(disable_msix, "Disable MSI-X use in driver - (default=0)");
+
+static u32 ctx_update_sub_id = VMCI_INVALID_ID;
+static u32 vm_context_id = VMCI_INVALID_ID;
+
+struct vmci_guest_device {
+   struct device *dev; /* PCI device we are attached to */
+   void __iomem *iobase;
+
+   unsigned int irq;
+   unsigned int intr_type;
+   bool exclusive_vectors;
+   struct msix_entry msix_entries[VMCI_MAX_INTRS];
+
+   struct tasklet_struct datagram_tasklet;
+   struct tasklet_struct bm_tasklet;
+
+   void *data_buffer;
+   void *notification_bitmap;
+};
+
+/* vmci_dev singleton device and supporting data*/
+static struct vmci_guest_device *vmci_dev_g;
+static DEFINE_SPINLOCK(vmci_dev_spinlock);
+
+static atomic_t vmci_num_guest_devices = ATOMIC_INIT(0);
+
+bool vmci_guest_code_active(void)
+{
+   return atomic_read(&vmci_num_guest_devices) != 0;
+}
+
+u32 vmci_get_vm_context_id(void)
+{
+   if (vm_context_id == VMCI_INVALID_ID) {
+   u32 result;
+   struct vmci_datagram get_cid_msg;
+   get_cid_msg.dst =
+   vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
+VMCI_GET_CONTEXT_ID);
+   get_cid_msg.src = VMCI_ANON_SRC_HANDLE;
+   get_cid_msg.payload_size = 0;
+   result = vmci_send_datagram(&get_cid_msg);
+   if (result >= 0)
+   vm_context_id = result;
+   }
+   return vm_context_id;
+}
+
+/*
+ * VM to hypervisor call mechanism. We use the standard VMware naming
+ * convention since shared code is calling this function as well.
+ */
+int vmci_send_datagram(struct vmci_datagram *dg)
+{
+   unsigned long flags;
+   int result;
+
+   /* Check args. */
+   if (dg == NULL)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* Need to acquire spinlock on the device because the datagram
+* data may be spread over multiple pages and the monitor may
+* interleave device user rpc calls from multiple
+* VCPUs. Acquiring the spinlock precludes that
+* possibility. Disabling interrupts to avoid incoming
+* datagrams during a "rep out" and possibly landing up in
+* this function.
+*/
+   spin_lock_irqsave(&vmci_dev_spinlock, flags);
+
+   if (vmci_dev_g) {
+   iowrite8_rep(vmci_dev_g->iobase + VMCI_DATA_OUT_ADDR,
+dg, VMCI_DG_SIZE(dg));
+   result = ioread32(vmci_dev_g->iobase + VMCI_RESULT_LOW_ADDR);
+   } else {
+   result = VMCI_ERROR_UNAVAILABLE;
+   }
+
+   spin_unlock_irqrestore(&vmci_dev_spinlock, flags);
+
+   return result;
+}
+EXPORT_SYMBOL_GPL(vmci_send_datagram);
+
+/*
+ * Gets called with the new context id if updated or resumed.
+ * Context id.
+ */
+static void vmci_guest_cid_update(u32 sub_id,
+ const struct vmci_event_data *event_data,
+ void *client_data)
+{
+   const struct vmci_event_payld_ctx *ev_payload =
+  

[PATCH 09/12] VMCI: routing implementation.

2013-01-08 Thread George Zhang
VMCI routing code is responsible for routing between various hosts/guests as 
well as
routing in nested scenarios.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_route.c |  226 
 drivers/misc/vmw_vmci/vmci_route.h |   30 +
 2 files changed, 256 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.h

diff --git a/drivers/misc/vmw_vmci/vmci_route.c 
b/drivers/misc/vmw_vmci/vmci_route.c
new file mode 100644
index 000..9109065
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_route.c
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+/*
+ * Make a routing decision for the given source and destination handles.
+ * This will try to determine the route using the handles and the available
+ * devices.  Will set the source context if it is invalid.
+ */
+int vmci_route(struct vmci_handle *src,
+  const struct vmci_handle *dst,
+  bool from_guest,
+  enum vmci_route *route)
+{
+   bool has_host_device = vmci_host_code_active();
+   bool has_guest_device = vmci_guest_code_active();
+
+   *route = VMCI_ROUTE_NONE;
+
+   /*
+* "from_guest" is only ever set to true by
+* IOCTL_VMCI_DATAGRAM_SEND (or by the vmkernel equivalent),
+* which comes from the VMX, so we know it is coming from a
+* guest.
+*
+* To avoid inconsistencies, test these once.  We will test
+* them again when we do the actual send to ensure that we do
+* not touch a non-existent device.
+*/
+
+   /* Must have a valid destination context. */
+   if (VMCI_INVALID_ID == dst->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /* Anywhere to hypervisor. */
+   if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
+
+   /*
+* If this message already came from a guest then we
+* cannot send it to the hypervisor.  It must come
+* from a local client.
+*/
+   if (from_guest)
+   return VMCI_ERROR_DST_UNREACHABLE;
+
+   /*
+* We must be acting as a guest in order to send to
+* the hypervisor.
+*/
+   if (!has_guest_device)
+   return VMCI_ERROR_DEVICE_NOT_FOUND;
+
+   /* And we cannot send if the source is the host context. */
+   if (VMCI_HOST_CONTEXT_ID == src->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* If the client passed the ANON source handle then
+* respect it (both context and resource are invalid).
+* However, if they passed only an invalid context,
+* then they probably mean ANY, in which case we
+* should set the real context here before passing it
+* down.
+*/
+   if (VMCI_INVALID_ID == src->context &&
+   VMCI_INVALID_ID != src->resource)
+   src->context = vmci_get_context_id();
+
+   /* Send from local client down to the hypervisor. */
+   *route = VMCI_ROUTE_AS_GUEST;
+   return VMCI_SUCCESS;
+   }
+
+   /* Anywhere to local client on host. */
+   if (VMCI_HOST_CONTEXT_ID == dst->context) {
+   /*
+* If it is not from a guest but we are acting as a
+* guest, then we need to send it down to the host.
+* Note that if we are also acting as a host then this
+* will prevent us from sending from local client to
+* local client, but we accept that restriction as a
+* way to remove any ambiguity from the host context.
+*/
+   if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* If the hypervisor is the source, this is
+* host local communication. The hypervisor
+* may send vmci event datagrams to the hos

[PATCH 08/12] VMCI: resource object implementation.

2013-01-08 Thread George Zhang
VMCI resource tracks all used resources within the vmci code.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_resource.c |  229 +
 drivers/misc/vmw_vmci/vmci_resource.h |   59 +
 2 files changed, 288 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.h

diff --git a/drivers/misc/vmw_vmci/vmci_resource.c 
b/drivers/misc/vmw_vmci/vmci_resource.c
new file mode 100644
index 000..a196f84
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_resource.c
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+
+
+#define VMCI_RESOURCE_HASH_BITS 7
+#define VMCI_RESOURCE_HASH_BUCKETS  (1 << VMCI_RESOURCE_HASH_BITS)
+
+struct vmci_hash_table {
+   spinlock_t lock;
+   struct hlist_head entries[VMCI_RESOURCE_HASH_BUCKETS];
+};
+
+static struct vmci_hash_table vmci_resource_table = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_resource_table.lock),
+};
+
+static unsigned int vmci_resource_hash(struct vmci_handle handle)
+{
+   return hash_32(handle.resource, VMCI_RESOURCE_HASH_BITS);
+}
+
+/*
+ * Gets a resource (if one exists) matching given handle from the hash table.
+ */
+static struct vmci_resource *vmci_resource_lookup(struct vmci_handle handle,
+ enum vmci_resource_type type)
+{
+   struct vmci_resource *r, *resource = NULL;
+   struct hlist_node *node;
+   unsigned int idx = vmci_resource_hash(handle);
+
+   rcu_read_lock();
+   hlist_for_each_entry_rcu(r, node,
+&vmci_resource_table.entries[idx], node) {
+   u32 cid = r->handle.context;
+   u32 rid = r->handle.resource;
+
+   if (r->type == type &&
+   rid == handle.resource &&
+   (cid == handle.context || cid == VMCI_INVALID_ID)) {
+   resource = r;
+   break;
+   }
+   }
+   rcu_read_unlock();
+
+   return resource;
+}
+
+/*
+ * Find an unused resource ID and return it. The first
+ * VMCI_RESERVED_RESOURCE_ID_MAX are reserved so we start from
+ * its value + 1.
+ * Returns VMCI resource id on success, VMCI_INVALID_ID on failure.
+ */
+static u32 vmci_resource_find_id(u32 context_id,
+enum vmci_resource_type resource_type)
+{
+   static u32 resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   u32 old_rid = resource_id;
+   u32 current_rid;
+
+   /*
+* Generate a unique resource ID.  Keep on trying until we wrap around
+* in the RID space.
+*/
+   do {
+   struct vmci_handle handle;
+
+   current_rid = resource_id;
+   resource_id++;
+   if (unlikely(resource_id == VMCI_INVALID_ID)) {
+   /* Skip the reserved rids. */
+   resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   }
+
+   handle = vmci_make_handle(context_id, current_rid);
+   if (!vmci_resource_lookup(handle, resource_type))
+   return current_rid;
+   } while (resource_id != old_rid);
+
+   return VMCI_INVALID_ID;
+}
+
+
+int vmci_resource_add(struct vmci_resource *resource,
+ enum vmci_resource_type resource_type,
+ struct vmci_handle handle)
+
+{
+   unsigned int idx;
+   int result;
+
+   spin_lock(&vmci_resource_table.lock);
+
+   if (handle.resource == VMCI_INVALID_ID) {
+   handle.resource = vmci_resource_find_id(handle.context,
+   resource_type);
+   if (handle.resource == VMCI_INVALID_ID) {
+   result = VMCI_ERROR_NO_HANDLE;
+   goto out;
+   }
+   } else if (vmci_resource_lookup(handle, resource_type)) {
+   result = VMCI_ERROR_ALREADY_EXISTS;
+   goto out;
+   }
+
+   resource->handle = handle;
+   resource->type = resource_type;
+   INIT_HLIST_NODE(&resource->node);
+   kref_init(&resource->kref);
+   init_c

[PATCH 06/12] VMCI: handle array implementation.

2013-01-08 Thread George Zhang
VMCI handle code adds support for dynamic arrays that will grow if they need to.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_handle_array.c |  142 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   52 +++
 2 files changed, 194 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.h

diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c 
b/drivers/misc/vmw_vmci/vmci_handle_array.c
new file mode 100644
index 000..344973a
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_handle_array.c
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include 
+#include "vmci_handle_array.h"
+
+static size_t handle_arr_calc_size(size_t capacity)
+{
+   return sizeof(struct vmci_handle_arr) +
+   capacity * sizeof(struct vmci_handle);
+}
+
+struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity)
+{
+   struct vmci_handle_arr *array;
+
+   if (capacity == 0)
+   capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
+
+   array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC);
+   if (!array)
+   return NULL;
+
+   array->capacity = capacity;
+   array->size = 0;
+
+   return array;
+}
+
+void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
+{
+   kfree(array);
+}
+
+void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
+ struct vmci_handle handle)
+{
+   struct vmci_handle_arr *array = *array_ptr;
+
+   if (unlikely(array->size >= array->capacity)) {
+   /* reallocate. */
+   struct vmci_handle_arr *new_array;
+   size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT;
+   size_t new_size = handle_arr_calc_size(new_capacity);
+
+   new_array = krealloc(array, new_size, GFP_ATOMIC);
+   if (!new_array)
+   return;
+
+   new_array->capacity = new_capacity;
+   *array_ptr = array = new_array;
+   }
+
+   array->entries[array->size] = handle;
+   array->size++;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
+ */
+struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
+   struct vmci_handle entry_handle)
+{
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+   size_t i;
+
+   for (i = 0; i < array->size; i++) {
+   if (vmci_handle_is_equal(array->entries[i], entry_handle)) {
+   handle = array->entries[i];
+   array->size--;
+   array->entries[i] = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   break;
+   }
+   }
+
+   return handle;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
+ */
+struct vmci_handle vmci_handle_arr_remove_tail(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;
+}
+
+/*
+ * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
+ */
+struct vmci_handle
+vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index)
+{
+   if (unlikely(index >= array->size))
+   return VMCI_INVALID_HANDLE;
+
+   return array->entries[index];
+}
+
+bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
+  struct vmci_handle entry_handle)
+{
+   size_t i;
+
+   for (i = 0; i < array->size; i++)
+   if (vmci_handle_is_equal(array->entries[i], entry_handle))
+   return true;
+
+   return false;
+}
+
+/*
+ * NULL if the array is empty. Otherwise, a pointer to the array
+ * of VMCI handles in the handle array.
+ */
+struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array)
+{
+   if (array->size)
+   return array->en

[PATCH 05/12] VMCI: event handling implementation.

2013-01-08 Thread George Zhang
VMCI event code that manages event handlers and handles callbacks when specific
events fire.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_event.c |  224 
 drivers/misc/vmw_vmci/vmci_event.h |   25 
 2 files changed, 249 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.h

diff --git a/drivers/misc/vmw_vmci/vmci_event.c 
b/drivers/misc/vmw_vmci/vmci_event.c
new file mode 100644
index 000..8449516
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_event.c
@@ -0,0 +1,224 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define EVENT_MAGIC 0xEABE
+#define VMCI_EVENT_MAX_ATTEMPTS 10
+
+struct vmci_subscription {
+   u32 id;
+   u32 event;
+   vmci_event_cb callback;
+   void *callback_data;
+   struct list_head node;  /* on one of subscriber lists */
+};
+
+static struct list_head subscriber_array[VMCI_EVENT_MAX];
+static DEFINE_MUTEX(subscriber_mutex);
+
+int __init vmci_event_init(void)
+{
+   int i;
+
+   for (i = 0; i < VMCI_EVENT_MAX; i++)
+   INIT_LIST_HEAD(&subscriber_array[i]);
+
+   return VMCI_SUCCESS;
+}
+
+void vmci_event_exit(void)
+{
+   int e;
+
+   /* We free all memory at exit. */
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur, *p2;
+   list_for_each_entry_safe(cur, p2, &subscriber_array[e], node) {
+
+   /*
+* We should never get here because all events
+* should have been unregistered before we try
+* to unload the driver module.
+*/
+   pr_warn("Unexpected free events occurring\n");
+   list_del(&cur->node);
+   kfree(cur);
+   }
+   }
+}
+
+/*
+ * Find entry. Assumes subscriber_mutex is held.
+ */
+static struct vmci_subscription *event_find(u32 sub_id)
+{
+   int e;
+
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur;
+   list_for_each_entry(cur, &subscriber_array[e], node) {
+   if (cur->id == sub_id)
+   return cur;
+   }
+   }
+   return NULL;
+}
+
+/*
+ * Actually delivers the events to the subscribers.
+ * The callback function for each subscriber is invoked.
+ */
+static void event_deliver(struct vmci_event_msg *event_msg)
+{
+   struct vmci_subscription *cur;
+   struct list_head *subscriber_list;
+
+   rcu_read_lock();
+   subscriber_list = &subscriber_array[event_msg->event_data.event];
+   list_for_each_entry_rcu(cur, subscriber_list, node) {
+   cur->callback(cur->id, &event_msg->event_data,
+ cur->callback_data);
+   }
+   rcu_read_unlock();
+}
+
+/*
+ * Dispatcher for the VMCI_EVENT_RECEIVE datagrams. Calls all
+ * subscribers for given event.
+ */
+int vmci_event_dispatch(struct vmci_datagram *msg)
+{
+   struct vmci_event_msg *event_msg = (struct vmci_event_msg *)msg;
+
+   if (msg->payload_size < sizeof(u32) ||
+   msg->payload_size > sizeof(struct vmci_event_data_max))
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (!VMCI_EVENT_VALID(event_msg->event_data.event))
+   return VMCI_ERROR_EVENT_UNKNOWN;
+
+   event_deliver(event_msg);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * vmci_event_subscribe() - Subscribe to a given event.
+ * @event:  The event to subscribe to.
+ * @callback:   The callback to invoke upon the event.
+ * @callback_data:  Data to pass to the callback.
+ * @subscription_id:ID used to track subscription.  Used with
+ *  vmci_event_unsubscribe()
+ *
+ * Subscribes to the provided event. The callback specified will be
+ * fired from RCU critical section and therefore must not sleep.
+ */
+int vmci_event_subscribe(u32 event,
+vmci_event_cb callback,
+void *callback_data,
+u32 *new_subscription_id)
+{
+   struct

[PATCH 04/12] VMCI: device driver implementaton.

2013-01-08 Thread George Zhang
VMCI driver code implementes both the host and guest personalities of the VMCI 
driver.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_driver.c |  117 +++
 drivers/misc/vmw_vmci/vmci_driver.h |   50 +++
 2 files changed, 167 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.h

diff --git a/drivers/misc/vmw_vmci/vmci_driver.c 
b/drivers/misc/vmw_vmci/vmci_driver.c
new file mode 100644
index 000..7b3fce2
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.c
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+static bool vmci_disable_host;
+module_param_named(disable_host, vmci_disable_host, bool, 0);
+MODULE_PARM_DESC(disable_host,
+"Disable driver host personality (default=enabled)");
+
+static bool vmci_disable_guest;
+module_param_named(disable_guest, vmci_disable_guest, bool, 0);
+MODULE_PARM_DESC(disable_guest,
+"Disable driver guest personality (default=enabled)");
+
+static bool vmci_guest_personality_initialized;
+static bool vmci_host_personality_initialized;
+
+/*
+ * vmci_get_context_id() - Gets the current context ID.
+ *
+ * Returns the current context ID.  Note that since this is accessed only
+ * from code running in the host, this always returns the host context ID.
+ */
+u32 vmci_get_context_id(void)
+{
+   if (vmci_guest_code_active())
+   return vmci_get_vm_context_id();
+   else if (vmci_host_code_active())
+   return VMCI_HOST_CONTEXT_ID;
+
+   return VMCI_INVALID_ID;
+}
+EXPORT_SYMBOL_GPL(vmci_get_context_id);
+
+static int __init vmci_drv_init(void)
+{
+   int vmci_err;
+   int error;
+
+   vmci_err = vmci_event_init();
+   if (vmci_err < VMCI_SUCCESS) {
+   pr_err("Failed to initialize VMCIEvent (result=%d)\n",
+  vmci_err);
+   return -EINVAL;
+   }
+
+   if (!vmci_disable_guest) {
+   error = vmci_guest_init();
+   if (error) {
+   pr_warn("Failed to initialize guest personality 
(err=%d)\n",
+   error);
+   } else {
+   vmci_guest_personality_initialized = true;
+   pr_info("Guest personality initialized and is %s\n",
+   vmci_guest_code_active() ?
+   "active" : "inactive");
+   }
+   }
+
+   if (!vmci_disable_host) {
+   error = vmci_host_init();
+   if (error) {
+   pr_warn("Unable to initialize host personality 
(err=%d)\n",
+   error);
+   } else {
+   vmci_host_personality_initialized = true;
+   pr_info("Initialized host personality\n");
+   }
+   }
+
+   if (!vmci_guest_personality_initialized &&
+   !vmci_host_personality_initialized) {
+   vmci_event_exit();
+   return -ENODEV;
+   }
+
+   return 0;
+}
+module_init(vmci_drv_init);
+
+static void __exit vmci_drv_exit(void)
+{
+   if (vmci_guest_personality_initialized)
+   vmci_guest_exit();
+
+   if (vmci_host_personality_initialized)
+   vmci_host_exit();
+
+   vmci_event_exit();
+}
+module_exit(vmci_drv_exit);
+
+MODULE_AUTHOR("VMware, Inc.");
+MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
+MODULE_VERSION("1.0.0.0-k");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/vmw_vmci/vmci_driver.h 
b/drivers/misc/vmw_vmci/vmci_driver.h
new file mode 100644
index 000..f69156a
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ * 

[PATCH 03/12] VMCI: doorbell implementation.

2013-01-08 Thread George Zhang
VMCI doorbell code allows for notifcations between host and guest.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_doorbell.c |  604 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   51 +++
 2 files changed, 655 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.h

diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.c 
b/drivers/misc/vmw_vmci/vmci_doorbell.c
new file mode 100644
index 000..c3e8397
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -0,0 +1,604 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+
+#define VMCI_DOORBELL_INDEX_BITS   6
+#define VMCI_DOORBELL_INDEX_TABLE_SIZE (1 << VMCI_DOORBELL_INDEX_BITS)
+#define VMCI_DOORBELL_HASH(_idx)   hash_32(_idx, VMCI_DOORBELL_INDEX_BITS)
+
+/*
+ * DoorbellEntry describes the a doorbell notification handle allocated by the
+ * host.
+ */
+struct dbell_entry {
+   struct vmci_resource resource;
+   struct hlist_node node;
+   struct work_struct work;
+   vmci_callback notify_cb;
+   void *client_data;
+   u32 idx;
+   u32 priv_flags;
+   bool run_delayed;
+   atomic_t active;/* Only used by guest personality */
+};
+
+/* The VMCI index table keeps track of currently registered doorbells. */
+struct dbell_index_table {
+   spinlock_t lock;/* Index table lock */
+   struct hlist_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
+};
+
+static struct dbell_index_table vmci_doorbell_it = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_doorbell_it.lock),
+};
+
+/*
+ * The max_notify_idx is one larger than the currently known bitmap index in
+ * use, and is used to determine how much of the bitmap needs to be scanned.
+ */
+static u32 max_notify_idx;
+
+/*
+ * The notify_idx_count is used for determining whether there are free entries
+ * within the bitmap (if notify_idx_count + 1 < max_notify_idx).
+ */
+static u32 notify_idx_count;
+
+/*
+ * The last_notify_idx_reserved is used to track the last index handed out - in
+ * the case where multiple handles share a notification index, we hand out
+ * indexes round robin based on last_notify_idx_reserved.
+ */
+static u32 last_notify_idx_reserved;
+
+/* This is a one entry cache used to by the index allocation. */
+static u32 last_notify_idx_released = PAGE_SIZE;
+
+
+/*
+ * Utility function that retrieves the privilege flags associated
+ * with a given doorbell handle. For guest endpoints, the
+ * privileges are determined by the context ID, but for host
+ * endpoints privileges are associated with the complete
+ * handle. Hypervisor endpoints are not yet supported.
+ */
+int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags)
+{
+   if (priv_flags == NULL || handle.context == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (handle.context == VMCI_HOST_CONTEXT_ID) {
+   struct dbell_entry *entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DOORBELL);
+   if (!resource)
+   return VMCI_ERROR_NOT_FOUND;
+
+   entry = container_of(resource, struct dbell_entry, resource);
+   *priv_flags = entry->priv_flags;
+   vmci_resource_put(resource);
+   } else if (handle.context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* Hypervisor endpoints for notifications are not
+* supported (yet).
+*/
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   *priv_flags = vmci_context_get_priv_flags(handle.context);
+   }
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Find doorbell entry by bitmap index.
+ */
+static struct dbell_entry *dbell_index_table_find(u32 idx)
+{
+   u32 bucket = VMCI_DOORBELL_HASH(idx);
+   struct dbell_entry *dbell;
+   struct hlist_node *node;
+
+   hlist_for_each_entry(dbell, node, &v

[PATCH 02/12] VMCI: datagram implementation.

2013-01-08 Thread George Zhang
VMCI datagram Implements datagrams to allow data to be sent between host and 
guest.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_datagram.c |  500 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   52 +++
 2 files changed, 552 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.h

diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c 
b/drivers/misc/vmw_vmci/vmci_datagram.c
new file mode 100644
index 000..ed5c433
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -0,0 +1,500 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_datagram.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+#include "vmci_route.h"
+
+/*
+ * struct datagram_entry describes the datagram entity. It is used for datagram
+ * entities created only on the host.
+ */
+struct datagram_entry {
+   struct vmci_resource resource;
+   u32 flags;
+   bool run_delayed;
+   vmci_datagram_recv_cb recv_cb;
+   void *client_data;
+   u32 priv_flags;
+};
+
+struct delayed_datagram_info {
+   struct datagram_entry *entry;
+   struct vmci_datagram msg;
+   struct work_struct work;
+   bool in_dg_host_queue;
+};
+
+/* Number of in-flight host->host datagrams */
+static atomic_t delayed_dg_host_queue_size = ATOMIC_INIT(0);
+
+/*
+ * Create a datagram entry given a handle pointer.
+ */
+static int dg_create_handle(u32 resource_id,
+   u32 flags,
+   u32 priv_flags,
+   vmci_datagram_recv_cb recv_cb,
+   void *client_data, struct vmci_handle *out_handle)
+{
+   int result;
+   u32 context_id;
+   struct vmci_handle handle;
+   struct datagram_entry *entry;
+
+   if ((flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if ((flags & VMCI_FLAG_ANYCID_DG_HND) != 0) {
+   context_id = VMCI_INVALID_ID;
+   } else {
+   context_id = vmci_get_context_id();
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_RESOURCES;
+   }
+
+   handle = vmci_make_handle(context_id, resource_id);
+
+   entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+   if (!entry) {
+   pr_warn("Failed allocating memory for datagram entry\n");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   entry->run_delayed = (flags & VMCI_FLAG_DG_DELAYED_CB) ? true : false;
+   entry->flags = flags;
+   entry->recv_cb = recv_cb;
+   entry->client_data = client_data;
+   entry->priv_flags = priv_flags;
+
+   /* Make datagram resource live. */
+   result = vmci_resource_add(&entry->resource,
+  VMCI_RESOURCE_TYPE_DATAGRAM,
+  handle);
+   if (result != VMCI_SUCCESS) {
+   pr_warn("Failed to add new resource (handle=0x%x:0x%x), error: 
%d\n",
+   handle.context, handle.resource, result);
+   kfree(entry);
+   return result;
+   }
+
+   *out_handle = vmci_resource_handle(&entry->resource);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Internal utility function with the same purpose as
+ * vmci_datagram_get_priv_flags that also takes a context_id.
+ */
+static int vmci_datagram_get_priv_flags(u32 context_id,
+   struct vmci_handle handle,
+   u32 *priv_flags)
+{
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (context_id == VMCI_HOST_CONTEXT_ID) {
+   struct datagram_entry *src_entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DATAGRAM);
+   if (!resource)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   src_entry = container_of(resource, struct datagram_entry,
+  

[PATCH 01/12] VMCI: context implementation.

2013-01-08 Thread George Zhang
VMCI Context code maintains state for vmci and allows the driver to communicate
with multiple VMs.

Signed-off-by: George Zhang 
Acked-by: Andy king 
Acked-by: Dmitry Torokhov 
---
 drivers/misc/vmw_vmci/vmci_context.c | 1214 ++
 drivers/misc/vmw_vmci/vmci_context.h |  182 +
 2 files changed, 1396 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.h

diff --git a/drivers/misc/vmw_vmci/vmci_context.c 
b/drivers/misc/vmw_vmci/vmci_context.c
new file mode 100644
index 000..f866a4b
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_context.c
@@ -0,0 +1,1214 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+/*
+ * List of current VMCI contexts.  Contexts can be added by
+ * vmci_ctx_create() and removed via vmci_ctx_destroy().
+ * These, along with context lookup, are protected by the
+ * list structure's lock.
+ */
+static struct {
+   struct list_head head;
+   spinlock_t lock; /* Spinlock for context list operations */
+} ctx_list = {
+   .head = LIST_HEAD_INIT(ctx_list.head),
+   .lock = __SPIN_LOCK_UNLOCKED(ctx_list.lock),
+};
+
+/* Used by contexts that did not set up notify flag pointers */
+static bool ctx_dummy_notify;
+
+static void ctx_signal_notify(struct vmci_ctx *context)
+{
+   *context->notify = true;
+}
+
+static void ctx_clear_notify(struct vmci_ctx *context)
+{
+   *context->notify = false;
+}
+
+/*
+ * If nothing requires the attention of the guest, clears both
+ * notify flag and call.
+ */
+static void ctx_clear_notify_call(struct vmci_ctx *context)
+{
+   if (context->pending_datagrams == 0 &&
+   vmci_handle_arr_get_size(context->pending_doorbell_array) == 0)
+   ctx_clear_notify(context);
+}
+
+/*
+ * Sets the context's notify flag iff datagrams are pending for this
+ * context.  Called from vmci_setup_notify().
+ */
+void vmci_ctx_check_signal_notify(struct vmci_ctx *context)
+{
+   spin_lock(&context->lock);
+   if (context->pending_datagrams)
+   ctx_signal_notify(context);
+   spin_unlock(&context->lock);
+}
+
+/*
+ * Allocates and initializes a VMCI context.
+ */
+struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags,
+uintptr_t event_hnd,
+int user_version,
+const struct cred *cred)
+{
+   struct vmci_ctx *context;
+   int error;
+
+   if (cid == VMCI_INVALID_ID) {
+   pr_devel("Invalid context ID for VMCI context\n");
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   if (priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
+   pr_devel("Invalid flag (flags=0x%x) for VMCI context\n",
+priv_flags);
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   if (user_version == 0) {
+   pr_devel("Invalid suer_version %d\n", user_version);
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   context = kzalloc(sizeof(*context), GFP_KERNEL);
+   if (!context) {
+   pr_warn("Failed to allocate memory for VMCI context\n");
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   kref_init(&context->kref);
+   spin_lock_init(&context->lock);
+   INIT_LIST_HEAD(&context->list_item);
+   INIT_LIST_HEAD(&context->datagram_queue);
+   INIT_LIST_HEAD(&context->notifier_list);
+
+   /* Initialize host-specific VMCI context. */
+   init_waitqueue_head(&context->host_context.wait_queue);
+
+   context->queue_pair_array = vmci_handle_arr_create(0);
+   if (!context->queue_pair_array) {
+   error = -ENOMEM;
+   goto err_free_ctx;
+   }
+
+   context->doorbell_array = vmci_handle_arr_create(0);
+   if (!context->doorbell_array) {
+   error = -ENOMEM;
+   goto err_free_qp_ar

[PATCH 00/12] VMCI for Linux upstreaming

2013-01-08 Thread George Zhang
isor through a set of ioctls on the VMCI device node.  To
provide seamless support for nested virtualization, where a virtual
machine may use both a VMCI PCI device to talk to its hypervisor, and
the VMCI host side support to run nested virtual machines, the VMCI
host and virtual machine support are combined in a single kernel
module.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.



---

George Zhang (12):
  VMCI: context implementation.
  VMCI: datagram implementation.
  VMCI: doorbell implementation. VMCI doorbell code allows for notifcations 
between
  VMCI: device driver implementaton.
  VMCI: event handling implementation.
  VMCI: handle array implementation.
  VMCI: queue pairs implementation.
  VMCI: resource object implementation.
  VMCI: routing implementation.
  VMCI: guest side driver implementation.
  VMCI: host side driver implementation.
  VMCI: Some header and config files.


 drivers/misc/Kconfig  |1 
 drivers/misc/Makefile |2 
 drivers/misc/vmw_vmci/Kconfig |   16 
 drivers/misc/vmw_vmci/Makefile|4 
 drivers/misc/vmw_vmci/vmci_context.c  | 1214 ++
 drivers/misc/vmw_vmci/vmci_context.h  |  182 ++
 drivers/misc/vmw_vmci/vmci_datagram.c |  500 
 drivers/misc/vmw_vmci/vmci_datagram.h |   52 
 drivers/misc/vmw_vmci/vmci_doorbell.c |  604 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   51 
 drivers/misc/vmw_vmci/vmci_driver.c   |  117 +
 drivers/misc/vmw_vmci/vmci_driver.h   |   50 
 drivers/misc/vmw_vmci/vmci_event.c|  224 ++
 drivers/misc/vmw_vmci/vmci_event.h|   25 
 drivers/misc/vmw_vmci/vmci_guest.c|  759 ++
 drivers/misc/vmw_vmci/vmci_handle_array.c |  142 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   52 
 drivers/misc/vmw_vmci/vmci_host.c | 1042 +
 drivers/misc/vmw_vmci/vmci_queue_pair.c   | 3420 +
 drivers/misc/vmw_vmci/vmci_queue_pair.h   |  191 ++
 drivers/misc/vmw_vmci/vmci_resource.c |  229 ++
 drivers/misc/vmw_vmci/vmci_resource.h |   59 +
 drivers/misc/vmw_vmci/vmci_route.c|  226 ++
 drivers/misc/vmw_vmci/vmci_route.h|   30 
 include/linux/vmw_vmci_api.h  |   82 +
 include/linux/vmw_vmci_defs.h |  880 +++
 26 files changed, 10154 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/Kconfig
 create mode 100644 drivers/misc/vmw_vmci/Makefile
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.h
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.h
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.h
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.h
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.h
 create mode 100644 drivers/misc/vmw_vmci/vmci_guest.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.h
 create mode 100644 drivers/misc/vmw_vmci/vmci_host.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_queue_pair.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_queue_pair.h
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.h
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.h
 create mode 100644 include/linux/vmw_vmci_api.h
 create mode 100644 include/linux/vmw_vmci_defs.h

-- 
Signature
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


Re: [Pv-drivers] [PATCH 00/12] VMCI for Linux upstreaming

2012-11-26 Thread George Zhang

Greg

> 
> And why isn't George responding to my comments when I ask questions?
> 
I think Andy or Dmitry replied faster...
We will improve our process from your comments,
Thanks a lot,
George
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH 6/6] VSOCK: header and config files.

2012-11-21 Thread George Zhang
VSOCK header files, Makefiles and Kconfig systems for Linux VSocket module.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 include/linux/socket.h  |4 
 net/Kconfig |1 
 net/Makefile|1 
 net/vmw_vsock/Kconfig   |   14 +
 net/vmw_vsock/Makefile  |4 
 net/vmw_vsock/notify_qstate.c   |  625 +++
 net/vmw_vsock/vmci_sockets.h|  517 +
 net/vmw_vsock/vmci_sockets_packet.h |   90 +
 net/vmw_vsock/vsock_common.h|  127 +++
 net/vmw_vsock/vsock_packet.h|  124 +++
 net/vmw_vsock/vsock_version.h   |   28 ++
 11 files changed, 1534 insertions(+), 1 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 25d6322..57bc85e 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -195,7 +195,8 @@ struct ucred {
 #define AF_CAIF37  /* CAIF sockets */
 #define AF_ALG 38  /* Algorithm sockets*/
 #define AF_NFC 39  /* NFC sockets  */
-#define AF_MAX 40  /* For now.. */
+#define AF_VSOCK   40  /* VMCI sockets */
+#define AF_MAX 41  /* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC  AF_UNSPEC
@@ -238,6 +239,7 @@ struct ucred {
 #define PF_CAIFAF_CAIF
 #define PF_ALG AF_ALG
 #define PF_NFC AF_NFC
+#define PF_VSOCK   AF_VSOCK
 #define PF_MAX AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/net/Kconfig b/net/Kconfig
index 245831b..75b8d5e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -216,6 +216,7 @@ source "net/dcb/Kconfig"
 source "net/dns_resolver/Kconfig"
 source "net/batman-adv/Kconfig"
 source "net/openvswitch/Kconfig"
+source "net/vmw_vsock/Kconfig"
 
 config RPS
boolean
diff --git a/net/Makefile b/net/Makefile
index 4f4ee08..cae59f4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_CEPH_LIB)+= ceph/
 obj-$(CONFIG_BATMAN_ADV)   += batman-adv/
 obj-$(CONFIG_NFC)  += nfc/
 obj-$(CONFIG_OPENVSWITCH)  += openvswitch/
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock/
diff --git a/net/vmw_vsock/Kconfig b/net/vmw_vsock/Kconfig
new file mode 100644
index 000..95e2568
--- /dev/null
+++ b/net/vmw_vsock/Kconfig
@@ -0,0 +1,14 @@
+#
+# Vsock protocol
+#
+
+config VMWARE_VSOCK
+   tristate "Virtual Socket protocol"
+   depends on VMWARE_VMCI
+   help
+ Virtual Socket Protocol is a socket protocol similar to TCP/IP
+ allowing comunication between Virtual Machines and VMware
+ hypervisor.
+
+ To compile this driver as a module, choose M here: the module
+ will be called vsock. If unsure, say N.
diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile
new file mode 100644
index 000..4e940fe
--- /dev/null
+++ b/net/vmw_vsock/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock.o
+
+vmw_vsock-y += af_vsock.o notify.o notify_qstate.o stats.o util.o \
+   vsock_addr.o
diff --git a/net/vmw_vsock/notify_qstate.c b/net/vmw_vsock/notify_qstate.c
new file mode 100644
index 000..5a2f066
--- /dev/null
+++ b/net/vmw_vsock/notify_qstate.c
@@ -0,0 +1,625 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * notifyQState.c --
+ *
+ * Linux control notifications based on Queuepair state for the VMCI Stream
+ * Sockets protocol.
+ */
+
+#include 
+
+#include 
+
+#include   /* for NULL */
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) ((vsk)->notify.pkt_q_state.field_name)
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notificati

[PATCH 5/6] VSOCK: utility functions.

2012-11-21 Thread George Zhang
VSOCK utility functions for Linux VSocket module.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 net/vmw_vsock/util.c |  620 ++
 net/vmw_vsock/util.h |  314 +
 2 files changed, 934 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h

diff --git a/net/vmw_vsock/util.c b/net/vmw_vsock/util.c
new file mode 100644
index 000..cd86482
--- /dev/null
+++ b/net/vmw_vsock/util.c
@@ -0,0 +1,620 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+/*
+ * util.c --
+ *
+ * Utility functions for Linux VSocket module.
+ */
+
+#include 
+#include 
+#include 
+#include   /* for NULL */
+#include 
+
+#include "af_vsock.h"
+#include "util.h"
+
+struct list_head vsock_bind_table[VSOCK_HASH_SIZE + 1];
+struct list_head vsock_connected_table[VSOCK_HASH_SIZE];
+
+DEFINE_SPINLOCK(vsock_table_lock);
+
+/*
+ *
+ * vsock_vmci_log_pkt --
+ *
+ * Logs the provided packet.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_vmci_log_pkt(char const *function, u32 line,
+   struct vsock_packet *pkt)
+{
+   char buf[256];
+   char *cur = buf;
+   int left = sizeof buf;
+   int written = 0;
+   char *type_strings[] = {
+   [VSOCK_PACKET_TYPE_INVALID] = "INVALID",
+   [VSOCK_PACKET_TYPE_REQUEST] = "REQUEST",
+   [VSOCK_PACKET_TYPE_NEGOTIATE] = "NEGOTIATE",
+   [VSOCK_PACKET_TYPE_OFFER] = "OFFER",
+   [VSOCK_PACKET_TYPE_ATTACH] = "ATTACH",
+   [VSOCK_PACKET_TYPE_WROTE] = "WROTE",
+   [VSOCK_PACKET_TYPE_READ] = "READ",
+   [VSOCK_PACKET_TYPE_RST] = "RST",
+   [VSOCK_PACKET_TYPE_SHUTDOWN] = "SHUTDOWN",
+   [VSOCK_PACKET_TYPE_WAITING_WRITE] = "WAITING_WRITE",
+   [VSOCK_PACKET_TYPE_WAITING_READ] = "WAITING_READ",
+   [VSOCK_PACKET_TYPE_REQUEST2] = "REQUEST2",
+   [VSOCK_PACKET_TYPE_NEGOTIATE2] = "NEGOTIATE2",
+   };
+
+   written = snprintf(cur, left, "PKT: %u:%u -> %u:%u",
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.src),
+  pkt->src_port,
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.dst),
+  pkt->dst_port);
+   if (written >= left)
+   goto error;
+
+   left -= written;
+   cur += written;
+
+   switch (pkt->type) {
+   case VSOCK_PACKET_TYPE_REQUEST:
+   case VSOCK_PACKET_TYPE_NEGOTIATE:
+   written = snprintf(cur, left, ", %s, size = %" FMT64 "u",
+  type_strings[pkt->type], pkt->u.size);
+   break;
+
+   case VSOCK_PACKET_TYPE_OFFER:
+   case VSOCK_PACKET_TYPE_ATTACH:
+   written = snprintf(cur, left, ", %s, handle = %u:%u",
+  type_strings[pkt->type],
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->u.handle),
+  VMCI_HANDLE_TO_RESOURCE_ID(pkt->u.handle));
+   break;
+
+   case VSOCK_PACKET_TYPE_WROTE:
+   case VSOCK_PACKET_TYPE_READ:
+   case VSOCK_PACKET_TYPE_RST:
+   written = snprintf(cur, left, ", %s", type_strings[pkt->type]);
+   break;
+   case VSOCK_PACKET_TYPE_SHUTDOWN: {
+   bool recv;
+   bool send;
+
+   recv = pkt->u.mode & RCV_SHUTDOWN;
+   send = pkt->u.mode & SEND_SHUTDOWN;
+   written = snprintf(cur, left, ", %s, mode = %c%c",
+  type_strings[pkt->type],
+  recv ? 'R' : ' ', send ? 'S' : ' ');
+   }
+   break;
+
+   case VSOCK_PACKET_TYPE_WAITING_WRITE:
+   case VSOCK_PACKET_TYPE_WAITING_READ:
+   written = snprintf(cur, left,
+   ", %s, generation = %" FMT64 "u, offset = %" FMT64 "u",
+   type_strings[pkt->type],
+   pkt->u

[PATCH 4/6] VSOCK: statistics implementation.

2012-11-21 Thread George Zhang
VSOCK stats for VMCI Stream Sockets protocol.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 net/vmw_vsock/stats.c |   37 
 net/vmw_vsock/stats.h |  217 +
 2 files changed, 254 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h

diff --git a/net/vmw_vsock/stats.c b/net/vmw_vsock/stats.c
new file mode 100644
index 000..2d172d5
--- /dev/null
+++ b/net/vmw_vsock/stats.c
@@ -0,0 +1,37 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * stats.c --
+ *
+ * Linux stats for the VMCI Stream Sockets protocol.
+ */
+
+#include 
+
+#include 
+#include   /* for NULL */
+#include 
+
+#include "af_vsock.h"
+#include "stats.h"
+
+#ifdef VSOCK_GATHER_STATISTICS
+u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+atomic64_t vsock_stats_consume_total;
+atomic64_t vsock_stats_produce_total;
+#endif
diff --git a/net/vmw_vsock/stats.h b/net/vmw_vsock/stats.h
new file mode 100644
index 000..9949b22
--- /dev/null
+++ b/net/vmw_vsock/stats.h
@@ -0,0 +1,217 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * stats.h --
+ *
+ * Stats functions for Linux vsock module.
+ */
+
+#ifndef __STATS_H__
+#define __STATS_H__
+
+#include 
+
+#include "vsock_common.h"
+#include "vsock_packet.h"
+
+/*
+ * Define VSOCK_GATHER_STATISTICS to turn on statistics gathering. Currently
+ * this consists of 3 types of stats: 1. The number of control datagram
+ * messages sent. 2. The level of queuepair fullness (in 10% buckets) whenever
+ * data is about to be enqueued or dequeued from the queuepair. 3. The total
+ * number of bytes enqueued/dequeued.
+ */
+
+#ifdef VSOCK_GATHER_STATISTICS
+
+#define VSOCK_NUM_QUEUE_LEVEL_BUCKETS 10
+extern u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+extern u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern atomic64_t vsock_stats_consume_total;
+extern atomic64_t vsock_stats_produce_total;
+
+#define VSOCK_STATS_STREAM_CONSUME_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->consume_size,\
+   vmci_qpair_consume_buf_ready((vsk)->qpair), \
+   vsock_stats_consume_queue_hist)
+#define VSOCK_STATS_STREAM_PRODUCE_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->produce_size,\
+   vmci_qpair_produce_buf_ready((vsk)->qpair), \
+   vsock_stats_produce_queue_hist)
+#define VSOCK_STATS_CTLPKT_LOG(pkt_type)   \
+   do {\
+   ++vsock_stats_ctl_pkt_count[pkt_type];  \
+   } while (0)
+#define VSOCK_STATS_STREAM_CONSUME(bytes)  \
+   atomic64_add(&vsock_stats_consume_total, bytes)
+#define VSOCK_STATS_STREAM_PRODUCE(bytes)  \
+   atomic64_add(&vsock_stats_produce_total, bytes)
+#define VSOCK_STATS_CTLPKT_DUMP_ALL() vsock_vmci_stats_ctl_pkt_dump_all()
+#define VSOCK_STATS_HIST_DUMP_ALL()   vsock_vmci_stats_hist_dump_all()
+#define VSOCK_STATS_TOTALS_DUMP_ALL() vsock_vmci_stats_totals_dump_all()
+#define VSOCK_STATS_RESET()   vsock_vmci_stats_reset()
+
+/*
+ *
+ * vsock_vmci_stats_update_queue_bucket_count --
+ *
+ * Given a queue, determine how much data is enqueued and add that to the
+ * specified queue level s

[PATCH 3/6] VSOCK: notification implementation.

2012-11-21 Thread George Zhang
VSOCK control notifications for VMCI Stream Sockets protocol.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 net/vmw_vsock/notify.c |  983 
 net/vmw_vsock/notify.h |  130 ++
 2 files changed, 1113 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h

diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c
new file mode 100644
index 000..8504e28
--- /dev/null
+++ b/net/vmw_vsock/notify.c
@@ -0,0 +1,983 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * notify.c --
+ *
+ * Linux control notifications for the VMCI Stream Sockets protocol.
+ */
+
+#include 
+
+#include 
+#include   /* for NULL */
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) ((vsk)->notify.pkt.field_name)
+
+#define VSOCK_MAX_DGRAM_RESENDS   10
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_write(struct vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+   bool retval;
+   u64 notify_limit;
+
+   if (!PKT_FIELD(vsk, peer_waiting_write))
+   return false;
+
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   /*
+* When the sender blocks, we take that as a sign that the sender is
+* faster than the receiver. To reduce the transmit rate of the sender,
+* we delay the sending of the read notification by decreasing the
+* write_notify_window. The notification is delayed until the number of
+* bytes used in the queue drops below the write_notify_window.
+*/
+
+   if (!PKT_FIELD(vsk, peer_waiting_write_detected)) {
+   PKT_FIELD(vsk, peer_waiting_write_detected) = true;
+   if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) {
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+   } else {
+   PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE;
+   if (PKT_FIELD(vsk, write_notify_window) <
+   PKT_FIELD(vsk, write_notify_min_window))
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+
+   }
+   }
+   notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window);
+#else
+   notify_limit = 0;
+#endif
+
+   /*
+* For now we ignore the wait information and just see if the free
+* space exceeds the notify limit.  Note that improving this function
+* to be more intelligent will not require a protocol change and will
+* retain compatibility between endpoints with mixed versions of this
+* function.
+*
+* The notify_limit is used to delay notifications in the case where
+* flow control is enabled. Below the test is expressed in terms of
+* free space in the queue: if free_space > ConsumeSize -
+* write_notify_window then notify An alternate way of expressing this
+* is to rewrite the expression to use the data ready in the receive
+* queue: if write_notify_window > bufferReady then notify as
+* free_space == ConsumeSize - bufferReady.
+*/
+   retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit;
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   if (retval) {
+   /*
+* Once we notify the peer, we reset the detected flag so the
+* next wait will again cause a decrease in the window size.
+*/
+
+   PKT_FIELD(vsk, peer_waiting_write_detected) = false;
+   }
+#endif
+   return retval;
+#else
+   return true;
+#endif
+}
+
+/*
+ *
+ * vsock_vmci_notify_waiting_read --
+ *
+ * Determines if the conditions have been met to notify a waiting reader.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_read(struct vsock_vmci_sock *vsk)
+{
+#if defined(V

[PATCH 2/6] VSOCK: vsock address implementaion.

2012-11-21 Thread George Zhang
VSOCK linux address code implementation.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 net/vmw_vsock/vsock_addr.c |  246 
 net/vmw_vsock/vsock_addr.h |   40 +++
 2 files changed, 286 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h

diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
new file mode 100644
index 000..35eeb14
--- /dev/null
+++ b/net/vmw_vsock/vsock_addr.c
@@ -0,0 +1,246 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+/*
+ * vsockAddr.c --
+ *
+ * VSockets address implementation.
+ */
+
+#include 
+#include 
+#include   /* for NULL */
+#include 
+
+#include "vsock_common.h"
+
+/*
+ *
+ * vsock_addr_init --
+ *
+ * Initialize the given address with the given context id and port. This will
+ * clear the address, set the correct family, and add the given values.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port)
+{
+   memset(addr, 0, sizeof *addr);
+
+   addr->svm_family = AF_VSOCK;
+   addr->svm_cid = cid;
+   addr->svm_port = port;
+}
+
+/*
+ *
+ * vsock_addr_validate --
+ *
+ * Try to validate the given address.  The address must not be null and must
+ * have the correct address family.  Any reserved fields must be zero.
+ *
+ * Results: 0 on success, EFAULT if the address is null, EAFNOSUPPORT if the
+ * address is of the wrong family, and EINVAL if the reserved fields are not
+ * zero.
+ *
+ * Side effects: None.
+ */
+
+int vsock_addr_validate(const struct sockaddr_vm *addr)
+{
+   if (!addr)
+   return -EFAULT;
+
+   if (addr->svm_family != AF_VSOCK)
+   return -EAFNOSUPPORT;
+
+   if (addr->svm_zero[0] != 0)
+   return -EINVAL;
+
+   return 0;
+}
+
+/*
+ *
+ * vsock_addr_bound --
+ *
+ * Determines whether the provided address is bound.
+ *
+ * Results: TRUE if the address structure is bound, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_bound(const struct sockaddr_vm *addr)
+{
+   return addr->svm_port != VMADDR_PORT_ANY;
+}
+
+/*
+ *
+ * vsock_addr_unbind --
+ *
+ * Unbind the given addresss.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_addr_unbind(struct sockaddr_vm *addr)
+{
+   vsock_addr_init(addr, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+}
+
+/*
+ *
+ * vsock_addr_equals_addr --
+ *
+ * Determine if the given addresses are equal.
+ *
+ * Results: TRUE if the addresses are equal, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   return addr->svm_cid == other->svm_cid &&
+   addr->svm_port == other->svm_port;
+}
+
+/*
+ *
+ * vsock_addr_equals_addr_any --
+ *
+ * Determine if the given addresses are equal. Will accept either an exact
+ * match or one where the rids match and that either the cids match or are set
+ * to VMADDR_CID_ANY.
+ *
+ * Results: TRUE if the addresses are equal, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   return (addr->svm_cid == VMADDR_CID_ANY ||
+   other->svm_cid == VMADDR_CID_ANY ||
+   addr->svm_cid == other->svm_cid) &&
+  addr->svm_port == other->svm_port;
+}
+
+/*
+ *
+ * vsock_addr_equals_handle_port --
+ *
+ * Determines if the given address matches the given handle and port.
+ *
+ * Results: TRUE if the address matches the handle and port, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_handle_port(const struct sockaddr_vm *addr,
+  struct vmci_handle handle, u32 port)
+{
+   return addr->svm_cid == VMCI_HANDLE_TO_CONTEXT_ID(handle) &&
+   addr->svm_port == port;
+}
+
+/*
+ *
+ * vsock_addr_cast --
+ *
+ * Try to cast the given generic address to a VM address.  The given length
+ * must match that of a VM address and the address must be valid. The
+ * "out_addr" parameter contains the address if successful.
+ *
+ * Results: 0 on success, EFAULT if the

[PATCH 0/6] VSOCK for Linux upstreaming

2012-11-21 Thread George Zhang

* * *
This series of VSOCK linux upstreaming patches include latest udpate from
VMware.

Summary of changes:
- Sparse clean.
- Checkpatch clean with one exception, a "complex macro" in
  which we can't add parentheses.
- Remove all runtime assertions.
- Fix device name, so that existing user clients work.
- Fix VMCI handle lookup.

* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets (VSOCK)
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vsock kernel
module. The vmw_vmci kernel module has been presented in an early post.


* * *

VMCI Sockets allows virtual machines to communicate with host kernel
modules and the VMware hypervisors. VMCI Sockets kernel module has
dependency on VMCI kernel module. User level applications both in
a virtual machine and on the host can use vmw_vmci through VMCI
Sockets API which facilitates fast and efficient communication
between guest virtual machines and their host. A socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

The VMware VMCI Sockets are similar to other socket types, like
Berkeley UNIX socket interface. The VMCI sockets module supports
both connection-oriented stream sockets like TCP, and connectionless
datagram sockets like UDP. The VSOCK protocol family is defined as
"AF_VSOCK" and the socket operations split for SOCK_DGRAM and
SOCK_STREAM.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.



---

George Zhang (6):
  VSOCK: vsock protocol implementation.
  VSOCK: vsock address implementaion.
  VSOCK: notification implementation.
  VSOCK: statistics implementation.
  VSOCK: utility functions.
  VSOCK: header and config files.


 include/linux/socket.h  |4 
 net/Kconfig |1 
 net/Makefile|1 
 net/vmw_vsock/Kconfig   |   14 
 net/vmw_vsock/Makefile  |4 
 net/vmw_vsock/af_vsock.c| 4054 +++
 net/vmw_vsock/af_vsock.h|  180 ++
 net/vmw_vsock/notify.c  |  983 
 net/vmw_vsock/notify.h  |  130 +
 net/vmw_vsock/notify_qstate.c   |  625 +
 net/vmw_vsock/stats.c   |   37 
 net/vmw_vsock/stats.h   |  217 ++
 net/vmw_vsock/util.c|  620 +
 net/vmw_vsock/util.h|  314 +++
 net/vmw_vsock/vmci_sockets.h|  517 
 net/vmw_vsock/vmci_sockets_packet.h |   90 +
 net/vmw_vsock/vsock_addr.c  |  246 ++
 net/vmw_vsock/vsock_addr.h  |   40 
 net/vmw_vsock/vsock_common.h|  127 +
 net/vmw_vsock/vsock_packet.h|  124 +
 net/vmw_vsock/vsock_version.h   |   28 
 21 files changed, 8355 insertions(+), 1 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/af_vsock.c
 create mode 100644 net/vmw_vsock/af_vsock.h
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

-- 
Signature
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH 12/12] VMCI: Some header and config files.

2012-11-21 Thread George Zhang
VMCI head config patch Adds all the necessary files to enable building of the
VMCI module with the Linux Makefiles and Kconfig systems. Also adds the header
files used for building modules against the driver.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/Kconfig|1 
 drivers/misc/Makefile   |2 
 drivers/misc/vmw_vmci/Kconfig   |   16 +
 drivers/misc/vmw_vmci/Makefile  |4 
 drivers/misc/vmw_vmci/vmci_common_int.h |   32 +
 include/linux/vmw_vmci_api.h|   82 +++
 include/linux/vmw_vmci_defs.h   |  973 +++
 7 files changed, 1110 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/Kconfig
 create mode 100644 drivers/misc/vmw_vmci/Makefile
 create mode 100644 drivers/misc/vmw_vmci/vmci_common_int.h
 create mode 100644 include/linux/vmw_vmci_api.h
 create mode 100644 include/linux/vmw_vmci_defs.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2661f6e..fe38c7a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -517,4 +517,5 @@ source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
+source "drivers/misc/vmw_vmci/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 456972f..21ed953 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -51,3 +51,5 @@ obj-y += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)+= mei/
+obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
+obj-$(CONFIG_VMWARE_VMCI)  += vmw_vmci/
diff --git a/drivers/misc/vmw_vmci/Kconfig b/drivers/misc/vmw_vmci/Kconfig
new file mode 100644
index 000..55015e7
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Kconfig
@@ -0,0 +1,16 @@
+#
+# VMware VMCI device
+#
+
+config VMWARE_VMCI
+   tristate "VMware VMCI Driver"
+   depends on X86
+   help
+ This is VMware's Virtual Machine Communication Interface.  It enables
+ high-speed communication between host and guest in a virtual
+ environment via the VMCI virtual device.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vmw_vmci.
diff --git a/drivers/misc/vmw_vmci/Makefile b/drivers/misc/vmw_vmci/Makefile
new file mode 100644
index 000..4da9893
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci.o
+vmw_vmci-y += vmci_context.o vmci_datagram.o vmci_doorbell.o \
+   vmci_driver.o vmci_event.o vmci_guest.o vmci_handle_array.o \
+   vmci_host.o vmci_queue_pair.o vmci_resource.o vmci_route.o
diff --git a/drivers/misc/vmw_vmci/vmci_common_int.h 
b/drivers/misc/vmw_vmci/vmci_common_int.h
new file mode 100644
index 000..81a268a
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_common_int.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#ifndef _VMCI_COMMONINT_H_
+#define _VMCI_COMMONINT_H_
+
+#include 
+
+#define PCI_VENDOR_ID_VMWARE   0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMCI  0x0740
+#define VMCI_DRIVER_VERSION_STRING "1.0.0.0-k"
+#define MODULE_NAME "vmw_vmci"
+
+/* Print magic... whee! */
+#ifdef pr_fmt
+#undef pr_fmt
+#define pr_fmt(fmt) MODULE_NAME ": " fmt
+#endif
+
+#endif /* _VMCI_COMMONINT_H_ */
diff --git a/include/linux/vmw_vmci_api.h b/include/linux/vmw_vmci_api.h
new file mode 100644
index 000..193129d
--- /dev/null
+++ b/include/linux/vmw_vmci_api.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef __VMW_VMCI_API_H__
+#define __VMW_VMCI_API_H__
+
+#include 
+#include 
+
+#undef  VMCI_KERNEL

[PATCH 11/12] VMCI: host side driver implementation.

2012-11-21 Thread George Zhang
VMCI host side driver code implementation.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_host.c | 1036 +
 1 files changed, 1036 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_host.c

diff --git a/drivers/misc/vmw_vmci/vmci_host.c 
b/drivers/misc/vmw_vmci/vmci_host.c
new file mode 100644
index 000..4639e91
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_host.c
@@ -0,0 +1,1036 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_handle_array.h"
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+enum {
+   VMCI_NOTIFY_RESOURCE_QUEUE_PAIR = 0,
+   VMCI_NOTIFY_RESOURCE_DOOR_BELL = 1,
+};
+
+enum {
+   VMCI_NOTIFY_RESOURCE_ACTION_NOTIFY = 0,
+   VMCI_NOTIFY_RESOURCE_ACTION_CREATE = 1,
+   VMCI_NOTIFY_RESOURCE_ACTION_DESTROY = 2,
+};
+
+/*
+ * VMCI driver initialization. This block can also be used to
+ * pass initial group membership etc.
+ */
+struct vmci_init_blk {
+   u32 cid;
+   u32 flags;
+};
+
+/* VMCIqueue_pairAllocInfo_VMToVM */
+struct vmci_qp_alloc_info_vmvm {
+   struct vmci_handle handle;
+   u32 peer;
+   u32 flags;
+   u64 produce_size;
+   u64 consume_size;
+   u64 produce_page_file;/* User VA. */
+   u64 consume_page_file;/* User VA. */
+   u64 produce_page_file_size;  /* Size of the file name array. */
+   u64 consume_page_file_size;  /* Size of the file name array. */
+   s32 result;
+   u32 _pad;
+};
+
+/* VMCISetNotifyInfo: Used to pass notify flag's address to the host driver. */
+struct vmci_set_notify_info {
+   u64 notify_uva;
+   s32 result;
+   u32 _pad;
+};
+
+/*
+ * Per-instance host state
+ */
+struct vmci_host_dev {
+   struct vmci_ctx *context;
+   int user_version;
+   enum vmci_obj_type ct_type;
+   struct mutex lock;  /* Mutex lock for vmci context access */
+};
+
+static struct vmci_ctx *host_context;
+static bool vmci_host_device_initialized;
+static atomic_t vmci_host_active_users = ATOMIC_INIT(0);
+
+/*
+ * Determines whether the VMCI host personality is
+ * available. Since the core functionality of the host driver is
+ * always present, all guests could possibly use the host
+ * personality. However, to minimize the deviation from the
+ * pre-unified driver state of affairs, we only consider the host
+ * device active if there is no active guest device or if there
+ * are VMX'en with active VMCI contexts using the host device.
+ */
+bool vmci_host_code_active(void)
+{
+   return vmci_host_device_initialized &&
+   (!vmci_guest_code_active() ||
+atomic_read(&vmci_host_active_users) > 0);
+}
+
+/*
+ * Called on open of /dev/vmci.
+ */
+static int vmci_host_open(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev;
+
+   vmci_host_dev = kzalloc(sizeof(struct vmci_host_dev), GFP_KERNEL);
+   if (vmci_host_dev == NULL)
+   return -ENOMEM;
+
+   vmci_host_dev->ct_type = VMCIOBJ_NOT_SET;
+   mutex_init(&vmci_host_dev->lock);
+   filp->private_data = vmci_host_dev;
+
+   return 0;
+}
+
+/*
+ * Called on close of /dev/vmci, most often when the process
+ * exits.
+ */
+static int vmci_host_close(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev = filp->private_data;
+
+   if (vmci_host_dev->ct_type == VMCIOBJ_CONTEXT) {
+   vmci_ctx_destroy(vmci_host_dev->context);
+   vmci_host_dev->context = NULL;
+
+   /*
+* The number of active contexts is used to track whether any
+* VMX'en are using the host personality. It is incremented when
+* a context is created through the IOCTL_VMCI_INIT_CONTEXT
+* ioctl.
+*/
+   

[PATCH 10/12] VMCI: guest side driver implementation.

2012-11-21 Thread George Zhang
VMCI guest side driver code implementation.

Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 
Signed-off-by: George Zhang 

---
 drivers/misc/vmw_vmci/vmci_guest.c |  757 
 1 files changed, 757 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_guest.c

diff --git a/drivers/misc/vmw_vmci/vmci_guest.c 
b/drivers/misc/vmw_vmci/vmci_guest.c
new file mode 100644
index 000..bcbe8ab
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -0,0 +1,757 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+static bool vmci_disable_msi;
+module_param_named(disable_msi, vmci_disable_msi, bool, 0);
+MODULE_PARM_DESC(disable_msi, "Disable MSI use in driver - (default=0)");
+
+static bool vmci_disable_msix;
+module_param_named(disable_msix, vmci_disable_msix, bool, 0);
+MODULE_PARM_DESC(disable_msix, "Disable MSI-X use in driver - (default=0)");
+
+static u32 ctx_update_sub_id = VMCI_INVALID_ID;
+static u32 vm_context_id = VMCI_INVALID_ID;
+
+struct vmci_guest_device {
+   struct device *dev; /* PCI device we are attached to */
+   void __iomem *iobase;
+
+   unsigned int irq;
+   unsigned int intr_type;
+   bool exclusive_vectors;
+   struct msix_entry msix_entries[VMCI_MAX_INTRS];
+
+   struct tasklet_struct datagram_tasklet;
+   struct tasklet_struct bm_tasklet;
+
+   void *data_buffer;
+   void *notification_bitmap;
+};
+
+/* vmci_dev singleton device and supporting data*/
+static struct vmci_guest_device *vmci_dev_g;
+static DEFINE_SPINLOCK(vmci_dev_spinlock);
+
+static atomic_t vmci_num_guest_devices = ATOMIC_INIT(0);
+
+bool vmci_guest_code_active(void)
+{
+   return atomic_read(&vmci_num_guest_devices) != 0;
+}
+
+u32 vmci_get_vm_context_id(void)
+{
+   if (vm_context_id == VMCI_INVALID_ID) {
+   u32 result;
+   struct vmci_datagram get_cid_msg;
+   get_cid_msg.dst =
+   vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
+VMCI_GET_CONTEXT_ID);
+   get_cid_msg.src = VMCI_ANON_SRC_HANDLE;
+   get_cid_msg.payload_size = 0;
+   result = vmci_send_datagram(&get_cid_msg);
+   if (result >= 0)
+   vm_context_id = result;
+   }
+   return vm_context_id;
+}
+
+/*
+ * VM to hypervisor call mechanism. We use the standard VMware naming
+ * convention since shared code is calling this function as well.
+ */
+int vmci_send_datagram(struct vmci_datagram *dg)
+{
+   unsigned long flags;
+   int result;
+
+   /* Check args. */
+   if (dg == NULL)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* Need to acquire spinlock on the device because the datagram
+* data may be spread over multiple pages and the monitor may
+* interleave device user rpc calls from multiple
+* VCPUs. Acquiring the spinlock precludes that
+* possibility. Disabling interrupts to avoid incoming
+* datagrams during a "rep out" and possibly landing up in
+* this function.
+*/
+   spin_lock_irqsave(&vmci_dev_spinlock, flags);
+
+   if (vmci_dev_g) {
+   iowrite8_rep(vmci_dev_g->iobase + VMCI_DATA_OUT_ADDR,
+dg, VMCI_DG_SIZE(dg));
+   result = ioread32(vmci_dev_g->iobase + VMCI_RESULT_LOW_ADDR);
+   } else {
+   result = VMCI_ERROR_UNAVAILABLE;
+   }
+
+   spin_unlock_irqrestore(&vmci_dev_spinlock, flags);
+
+   return result;
+}
+EXPORT_SYMBOL_GPL(vmci_send_datagram);
+
+/*
+ * Gets called with the new context id if updated or resumed.
+ * Context id.
+ */
+static void vmci_guest_cid_update(u32 sub_id,
+ const struct vmci_event_data *event_data,
+ void *client_data)
+{
+   const struct vmci_event_payld_ctx *ev_payload =
+   vmci_event_data_const_payload(

[PATCH 09/12] VMCI: routing implementation.

2012-11-21 Thread George Zhang
VMCI routing code is responsible for routing between various hosts/guests as 
well
as routing in nested scenarios.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_route.c |  227 
 drivers/misc/vmw_vmci/vmci_route.h |   30 +
 2 files changed, 257 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.h

diff --git a/drivers/misc/vmw_vmci/vmci_route.c 
b/drivers/misc/vmw_vmci/vmci_route.c
new file mode 100644
index 000..7cca156
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_route.c
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+/*
+ * Make a routing decision for the given source and destination handles.
+ * This will try to determine the route using the handles and the available
+ * devices.  Will set the source context if it is invalid.
+ */
+int vmci_route(struct vmci_handle *src,
+  const struct vmci_handle *dst,
+  bool from_guest,
+  enum vmci_route *route)
+{
+   bool has_host_device = vmci_host_code_active();
+   bool has_guest_device = vmci_guest_code_active();
+
+   *route = VMCI_ROUTE_NONE;
+
+   /*
+* "from_guest" is only ever set to true by
+* IOCTL_VMCI_DATAGRAM_SEND (or by the vmkernel equivalent),
+* which comes from the VMX, so we know it is coming from a
+* guest.
+*
+* To avoid inconsistencies, test these once.  We will test
+* them again when we do the actual send to ensure that we do
+* not touch a non-existent device.
+*/
+
+   /* Must have a valid destination context. */
+   if (VMCI_INVALID_ID == dst->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /* Anywhere to hypervisor. */
+   if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
+
+   /*
+* If this message already came from a guest then we
+* cannot send it to the hypervisor.  It must come
+* from a local client.
+*/
+   if (from_guest)
+   return VMCI_ERROR_DST_UNREACHABLE;
+
+   /*
+* We must be acting as a guest in order to send to
+* the hypervisor.
+*/
+   if (!has_guest_device)
+   return VMCI_ERROR_DEVICE_NOT_FOUND;
+
+   /* And we cannot send if the source is the host context. */
+   if (VMCI_HOST_CONTEXT_ID == src->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* If the client passed the ANON source handle then
+* respect it (both context and resource are invalid).
+* However, if they passed only an invalid context,
+* then they probably mean ANY, in which case we
+* should set the real context here before passing it
+* down.
+*/
+   if (VMCI_INVALID_ID == src->context &&
+   VMCI_INVALID_ID != src->resource)
+   src->context = vmci_get_context_id();
+
+   /* Send from local client down to the hypervisor. */
+   *route = VMCI_ROUTE_AS_GUEST;
+   return VMCI_SUCCESS;
+   }
+
+   /* Anywhere to local client on host. */
+   if (VMCI_HOST_CONTEXT_ID == dst->context) {
+   /*
+* If it is not from a guest but we are acting as a
+* guest, then we need to send it down to the host.
+* Note that if we are also acting as a host then this
+* will prevent us from sending from local client to
+* local client, but we accept that restriction as a
+* way to remove any ambiguity from the host context.
+*/
+   if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* If the hypervisor is the source, this is
+* host local communication. The hypervisor
+* may send vmc

[PATCH 08/12] VMCI: resource object implementation.

2012-11-21 Thread George Zhang
VMCI resource tracks all used resources within the vmci code.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_resource.c |  232 +
 drivers/misc/vmw_vmci/vmci_resource.h |   59 
 2 files changed, 291 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.h

diff --git a/drivers/misc/vmw_vmci/vmci_resource.c 
b/drivers/misc/vmw_vmci/vmci_resource.c
new file mode 100644
index 000..0d3a2bc
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_resource.c
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+
+
+#define VMCI_RESOURCE_HASH_BITS 7
+#define VMCI_RESOURCE_HASH_BUCKETS  (1 << VMCI_RESOURCE_HASH_BITS)
+
+struct vmci_hash_table {
+   spinlock_t lock;
+   struct hlist_head entries[VMCI_RESOURCE_HASH_BUCKETS];
+};
+
+static struct vmci_hash_table vmci_resource_table = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_resource_table.lock),
+};
+
+static unsigned int vmci_resource_hash(struct vmci_handle handle)
+{
+   return hash_32(VMCI_HANDLE_TO_RESOURCE_ID(handle),
+  VMCI_RESOURCE_HASH_BITS);
+}
+
+/*
+ * Gets a resource (if one exists) matching given handle from the hash table.
+ */
+static struct vmci_resource *vmci_resource_lookup(struct vmci_handle handle,
+ enum vmci_resource_type type)
+{
+   struct vmci_resource *r, *resource = NULL;
+   struct hlist_node *node;
+   unsigned int idx = vmci_resource_hash(handle);
+
+   rcu_read_lock();
+   hlist_for_each_entry_rcu(r, node,
+&vmci_resource_table.entries[idx], node) {
+   u32 rid = VMCI_HANDLE_TO_RESOURCE_ID(r->handle);
+   u32 cid = VMCI_HANDLE_TO_CONTEXT_ID(r->handle);
+
+   if (r->type == type &&
+   rid == VMCI_HANDLE_TO_RESOURCE_ID(handle) &&
+   (cid == VMCI_HANDLE_TO_CONTEXT_ID(handle) ||
+cid == VMCI_INVALID_ID)) {
+   resource = r;
+   break;
+   }
+   }
+   rcu_read_unlock();
+
+   return resource;
+}
+
+/*
+ * Find an unused resource ID and return it. The first
+ * VMCI_RESERVED_RESOURCE_ID_MAX are reserved so we start from
+ * its value + 1.
+ * Returns VMCI resource id on success, VMCI_INVALID_ID on failure.
+ */
+static u32 vmci_resource_find_id(u32 context_id,
+enum vmci_resource_type resource_type)
+{
+   static u32 resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   u32 old_rid = resource_id;
+   u32 current_rid;
+
+   /*
+* Generate a unique resource ID.  Keep on trying until we wrap around
+* in the RID space.
+*/
+   do {
+   struct vmci_handle handle;
+
+   current_rid = resource_id;
+   resource_id++;
+   if (unlikely(resource_id == VMCI_INVALID_ID)) {
+   /* Skip the reserved rids. */
+   resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   }
+
+   handle = vmci_make_handle(context_id, current_rid);
+   if (!vmci_resource_lookup(handle, resource_type))
+   return current_rid;
+   } while (resource_id != old_rid);
+
+   return VMCI_INVALID_ID;
+}
+
+
+int vmci_resource_add(struct vmci_resource *resource,
+ enum vmci_resource_type resource_type,
+ struct vmci_handle handle)
+
+{
+   unsigned int idx;
+   int result;
+
+   spin_lock(&vmci_resource_table.lock);
+
+   if (handle.resource == VMCI_INVALID_ID) {
+   handle.resource = vmci_resource_find_id(handle.context,
+   resource_type);
+   if (handle.resource == VMCI_INVALID_ID) {
+   result = VMCI_ERROR_NO_HANDLE;
+   goto out;
+   }
+   } else if (vmci_resource_lookup(handle, resource_type)) {
+   result = VMCI_ERROR_ALREADY_EXISTS;
+   goto out;
+   }
+
+   

[PATCH 06/12] VMCI: handle array implementation.

2012-11-21 Thread George Zhang
VMCI handle code adds support for dynamic arrays that will grow if they need to.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_handle_array.c |  142 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   52 +++
 2 files changed, 194 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.h

diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c 
b/drivers/misc/vmw_vmci/vmci_handle_array.c
new file mode 100644
index 000..9122373
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_handle_array.c
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include 
+#include "vmci_handle_array.h"
+
+static size_t handle_arr_calc_size(size_t capacity)
+{
+   return sizeof(struct vmci_handle_arr) +
+   capacity * sizeof(struct vmci_handle);
+}
+
+struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity)
+{
+   struct vmci_handle_arr *array;
+
+   if (capacity == 0)
+   capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
+
+   array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC);
+   if (!array)
+   return NULL;
+
+   array->capacity = capacity;
+   array->size = 0;
+
+   return array;
+}
+
+void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
+{
+   kfree(array);
+}
+
+void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
+ struct vmci_handle handle)
+{
+   struct vmci_handle_arr *array = *array_ptr;
+
+   if (unlikely(array->size >= array->capacity)) {
+   /* reallocate. */
+   struct vmci_handle_arr *new_array;
+   size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT;
+   size_t new_size = handle_arr_calc_size(new_capacity);
+
+   new_array = krealloc(array, new_size, GFP_ATOMIC);
+   if (!new_array)
+   return;
+
+   new_array->capacity = new_capacity;
+   *array_ptr = array = new_array;
+   }
+
+   array->entries[array->size] = handle;
+   array->size++;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
+ */
+struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
+   struct vmci_handle entry_handle)
+{
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+   size_t i;
+
+   for (i = 0; i < array->size; i++) {
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle)) {
+   handle = array->entries[i];
+   array->size--;
+   array->entries[i] = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   break;
+   }
+   }
+
+   return handle;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
+ */
+struct vmci_handle vmci_handle_arr_remove_tail(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;
+}
+
+/*
+ * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
+ */
+struct vmci_handle
+vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index)
+{
+   if (unlikely(index >= array->size))
+   return VMCI_INVALID_HANDLE;
+
+   return array->entries[index];
+}
+
+bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
+  struct vmci_handle entry_handle)
+{
+   size_t i;
+
+   for (i = 0; i < array->size; i++)
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle))
+   return true;
+
+   return false;
+}
+
+/*
+ * NULL if the array is empty. Otherwise, a pointer to the array
+ * of VMCI handles in the handle array.
+ */
+struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array)
+{
+   if (array->size)
+   return array->en

[PATCH 05/12] VMCI: event handling implementation.

2012-11-21 Thread George Zhang
VMCI event code that manages event handlers and handles callbacks when
specific events fire.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_event.c |  224 
 drivers/misc/vmw_vmci/vmci_event.h |   25 
 2 files changed, 249 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.h

diff --git a/drivers/misc/vmw_vmci/vmci_event.c 
b/drivers/misc/vmw_vmci/vmci_event.c
new file mode 100644
index 000..1fe40e5
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_event.c
@@ -0,0 +1,224 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define EVENT_MAGIC 0xEABE
+#define VMCI_EVENT_MAX_ATTEMPTS 10
+
+struct vmci_subscription {
+   u32 id;
+   u32 event;
+   vmci_event_cb callback;
+   void *callback_data;
+   struct list_head node;  /* on one of subscriber lists */
+};
+
+static struct list_head subscriber_array[VMCI_EVENT_MAX];
+static DEFINE_MUTEX(subscriber_mutex);
+
+int __init vmci_event_init(void)
+{
+   int i;
+
+   for (i = 0; i < VMCI_EVENT_MAX; i++)
+   INIT_LIST_HEAD(&subscriber_array[i]);
+
+   return VMCI_SUCCESS;
+}
+
+void vmci_event_exit(void)
+{
+   int e;
+
+   /* We free all memory at exit. */
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur, *p2;
+   list_for_each_entry_safe(cur, p2, &subscriber_array[e], node) {
+
+   /*
+* We should never get here because all events
+* should have been unregistered before we try
+* to unload the driver module.
+*/
+   pr_warn("Unexpected free events occurring.\n");
+   list_del(&cur->node);
+   kfree(cur);
+   }
+   }
+}
+
+/*
+ * Find entry. Assumes subscriber_mutex is held.
+ */
+static struct vmci_subscription *event_find(u32 sub_id)
+{
+   int e;
+
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur;
+   list_for_each_entry(cur, &subscriber_array[e], node) {
+   if (cur->id == sub_id)
+   return cur;
+   }
+   }
+   return NULL;
+}
+
+/*
+ * Actually delivers the events to the subscribers.
+ * The callback function for each subscriber is invoked.
+ */
+static void event_deliver(struct vmci_event_msg *event_msg)
+{
+   struct vmci_subscription *cur;
+   struct list_head *subscriber_list;
+
+   rcu_read_lock();
+   subscriber_list = &subscriber_array[event_msg->event_data.event];
+   list_for_each_entry_rcu(cur, subscriber_list, node) {
+   cur->callback(cur->id, &event_msg->event_data,
+ cur->callback_data);
+   }
+   rcu_read_unlock();
+}
+
+/*
+ * Dispatcher for the VMCI_EVENT_RECEIVE datagrams. Calls all
+ * subscribers for given event.
+ */
+int vmci_event_dispatch(struct vmci_datagram *msg)
+{
+   struct vmci_event_msg *event_msg = (struct vmci_event_msg *)msg;
+
+   if (msg->payload_size < sizeof(u32) ||
+   msg->payload_size > sizeof(struct vmci_event_data_max))
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (!VMCI_EVENT_VALID(event_msg->event_data.event))
+   return VMCI_ERROR_EVENT_UNKNOWN;
+
+   event_deliver(event_msg);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * vmci_event_subscribe() - Subscribe to a given event.
+ * @event:  The event to subscribe to.
+ * @callback:   The callback to invoke upon the event.
+ * @callback_data:  Data to pass to the callback.
+ * @subscription_id:ID used to track subscription.  Used with
+ *  vmci_event_unsubscribe()
+ *
+ * Subscribes to the provided event. The callback specified will be
+ * fired from RCU critical section and therefore must not sleep.
+ */
+int vmci_event_subscribe(u32 event,
+vmci_event_cb callback,
+void *callback_data,
+u32 *new_subscription_i

[PATCH 04/12] VMCI: device driver implementaton.

2012-11-21 Thread George Zhang
VMCI driver code implementes both the host and guest personalities of the VMCI 
driver.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_driver.c |  117 +++
 drivers/misc/vmw_vmci/vmci_driver.h |   50 +++
 2 files changed, 167 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.h

diff --git a/drivers/misc/vmw_vmci/vmci_driver.c 
b/drivers/misc/vmw_vmci/vmci_driver.c
new file mode 100644
index 000..c04c24c
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.c
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+static bool vmci_disable_host;
+module_param_named(disable_host, vmci_disable_host, bool, 0);
+MODULE_PARM_DESC(disable_host,
+"Disable driver host personality (default=enabled)");
+
+static bool vmci_disable_guest;
+module_param_named(disable_guest, vmci_disable_guest, bool, 0);
+MODULE_PARM_DESC(disable_guest,
+"Disable driver guest personality (default=enabled)");
+
+static bool vmci_guest_personality_initialized;
+static bool vmci_host_personality_initialized;
+
+/*
+ * vmci_get_context_id() - Gets the current context ID.
+ *
+ * Returns the current context ID.  Note that since this is accessed only
+ * from code running in the host, this always returns the host context ID.
+ */
+u32 vmci_get_context_id(void)
+{
+   if (vmci_guest_code_active())
+   return vmci_get_vm_context_id();
+   else if (vmci_host_code_active())
+   return VMCI_HOST_CONTEXT_ID;
+
+   return VMCI_INVALID_ID;
+}
+EXPORT_SYMBOL_GPL(vmci_get_context_id);
+
+static int __init vmci_drv_init(void)
+{
+   int vmci_err;
+   int error;
+
+   vmci_err = vmci_event_init();
+   if (vmci_err < VMCI_SUCCESS) {
+   pr_err("Failed to initialize VMCIEvent (result=%d).\n",
+   vmci_err);
+   return -EINVAL;
+   }
+
+   if (!vmci_disable_guest) {
+   error = vmci_guest_init();
+   if (error) {
+   pr_warn("Failed to initialize guest personality 
(err=%d).\n",
+   error);
+   } else {
+   vmci_guest_personality_initialized = true;
+   pr_info("Guest personality initialized and is %s\n",
+   vmci_guest_code_active() ?
+   "active" : "inactive");
+   }
+   }
+
+   if (!vmci_disable_host) {
+   error = vmci_host_init();
+   if (error) {
+   pr_warn("Unable to initialize host personality 
(err=%d).\n",
+   error);
+   } else {
+   vmci_host_personality_initialized = true;
+   pr_info("Initialized host personality\n");
+   }
+   }
+
+   if (!vmci_guest_personality_initialized &&
+   !vmci_host_personality_initialized) {
+   vmci_event_exit();
+   return -ENODEV;
+   }
+
+   return 0;
+}
+module_init(vmci_drv_init);
+
+static void __exit vmci_drv_exit(void)
+{
+   if (vmci_guest_personality_initialized)
+   vmci_guest_exit();
+
+   if (vmci_host_personality_initialized)
+   vmci_host_exit();
+
+   vmci_event_exit();
+}
+module_exit(vmci_drv_exit);
+
+MODULE_AUTHOR("VMware, Inc.");
+MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
+MODULE_VERSION(VMCI_DRIVER_VERSION_STRING);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/vmw_vmci/vmci_driver.h 
b/drivers/misc/vmw_vmci/vmci_driver.h
new file mode 100644
index 000..f69156a
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.h
@@ -0,0 +1,50 @@
+/*
+ * 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 la

[PATCH 03/12] VMCI: doorbell implementation.

2012-11-21 Thread George Zhang
VMCI doorbell code allows for notifcations between host and guest.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_doorbell.c |  605 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   51 +++
 2 files changed, 656 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.h

diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.c 
b/drivers/misc/vmw_vmci/vmci_doorbell.c
new file mode 100644
index 000..bced12b
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -0,0 +1,605 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+
+#define VMCI_DOORBELL_INDEX_BITS   6
+#define VMCI_DOORBELL_INDEX_TABLE_SIZE (1 << VMCI_DOORBELL_INDEX_BITS)
+#define VMCI_DOORBELL_HASH(_idx)   hash_32(_idx, VMCI_DOORBELL_INDEX_BITS)
+
+/*
+ * DoorbellEntry describes the a doorbell notification handle allocated by the
+ * host.
+ */
+struct dbell_entry {
+   struct vmci_resource resource;
+   struct hlist_node node;
+   struct work_struct work;
+   vmci_callback notify_cb;
+   void *client_data;
+   u32 idx;
+   u32 priv_flags;
+   bool run_delayed;
+   atomic_t active;/* Only used by guest personality */
+};
+
+/* The VMCI index table keeps track of currently registered doorbells. */
+struct dbell_index_table {
+   spinlock_t lock;/* Index table lock */
+   struct hlist_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
+};
+
+static struct dbell_index_table vmci_doorbell_it = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_doorbell_it.lock),
+};
+
+/*
+ * The max_notify_idx is one larger than the currently known bitmap index in
+ * use, and is used to determine how much of the bitmap needs to be scanned.
+ */
+static u32 max_notify_idx;
+
+/*
+ * The notify_idx_count is used for determining whether there are free entries
+ * within the bitmap (if notify_idx_count + 1 < max_notify_idx).
+ */
+static u32 notify_idx_count;
+
+/*
+ * The last_notify_idx_reserved is used to track the last index handed out - in
+ * the case where multiple handles share a notification index, we hand out
+ * indexes round robin based on last_notify_idx_reserved.
+ */
+static u32 last_notify_idx_reserved;
+
+/* This is a one entry cache used to by the index allocation. */
+static u32 last_notify_idx_released = PAGE_SIZE;
+
+
+/*
+ * Utility function that retrieves the privilege flags associated
+ * with a given doorbell handle. For guest endpoints, the
+ * privileges are determined by the context ID, but for host
+ * endpoints privileges are associated with the complete
+ * handle. Hypervisor endpoints are not yet supported.
+ */
+int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags)
+{
+   if (priv_flags == NULL || handle.context == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (handle.context == VMCI_HOST_CONTEXT_ID) {
+   struct dbell_entry *entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DOORBELL);
+   if (!resource)
+   return VMCI_ERROR_NOT_FOUND;
+
+   entry = container_of(resource, struct dbell_entry, resource);
+   *priv_flags = entry->priv_flags;
+   vmci_resource_put(resource);
+   } else if (handle.context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* Hypervisor endpoints for notifications are not
+* supported (yet).
+*/
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   *priv_flags = vmci_context_get_priv_flags(handle.context);
+   }
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Find doorbell entry by bitmap index.
+ */
+static struct dbell_entry *dbell_index_table_find(u32 idx)
+{
+   u32 bucket = VMCI_DOORBELL_HASH(idx);
+   struct dbell_entry *dbell;
+   struct hlist_node *node;
+
+ 

[PATCH 02/12] VMCI: datagram implementation.

2012-11-21 Thread George Zhang
VMCI datagram Implements datagrams to allow data to be sent between host and 
guest.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_datagram.c |  501 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   52 +++
 2 files changed, 553 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.h

diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c 
b/drivers/misc/vmw_vmci/vmci_datagram.c
new file mode 100644
index 000..a6513f4
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -0,0 +1,501 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+#include "vmci_route.h"
+
+/*
+ * struct datagram_entry describes the datagram entity. It is used for datagram
+ * entities created only on the host.
+ */
+struct datagram_entry {
+   struct vmci_resource resource;
+   u32 flags;
+   bool run_delayed;
+   vmci_datagram_recv_cb recv_cb;
+   void *client_data;
+   u32 priv_flags;
+};
+
+struct delayed_datagram_info {
+   struct datagram_entry *entry;
+   struct vmci_datagram msg;
+   struct work_struct work;
+   bool in_dg_host_queue;
+};
+
+/* Number of in-flight host->host datagrams */
+static atomic_t delayed_dg_host_queue_size = ATOMIC_INIT(0);
+
+/*
+ * Create a datagram entry given a handle pointer.
+ */
+static int dg_create_handle(u32 resource_id,
+   u32 flags,
+   u32 priv_flags,
+   vmci_datagram_recv_cb recv_cb,
+   void *client_data, struct vmci_handle *out_handle)
+{
+   int result;
+   u32 context_id;
+   struct vmci_handle handle;
+   struct datagram_entry *entry;
+
+   if ((flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if ((flags & VMCI_FLAG_ANYCID_DG_HND) != 0) {
+   context_id = VMCI_INVALID_ID;
+   } else {
+   context_id = vmci_get_context_id();
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_RESOURCES;
+   }
+
+   handle = vmci_make_handle(context_id, resource_id);
+
+   entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+   if (!entry) {
+   pr_warn("Failed allocating memory for datagram entry.\n");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   entry->run_delayed = (flags & VMCI_FLAG_DG_DELAYED_CB) ? true : false;
+   entry->flags = flags;
+   entry->recv_cb = recv_cb;
+   entry->client_data = client_data;
+   entry->priv_flags = priv_flags;
+
+   /* Make datagram resource live. */
+   result = vmci_resource_add(&entry->resource,
+  VMCI_RESOURCE_TYPE_DATAGRAM,
+  handle);
+   if (result != VMCI_SUCCESS) {
+   pr_warn("Failed to add new resource (handle=0x%x:0x%x), error: 
%d\n",
+   handle.context, handle.resource, result);
+   kfree(entry);
+   return result;
+   }
+
+   *out_handle = vmci_resource_handle(&entry->resource);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Internal utility function with the same purpose as
+ * vmci_datagram_get_priv_flags that also takes a context_id.
+ */
+static int vmci_datagram_get_priv_flags(u32 context_id,
+   struct vmci_handle handle,
+   u32 *priv_flags)
+{
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (context_id == VMCI_HOST_CONTEXT_ID) {
+   struct datagram_entry *src_entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DATAGRAM);
+   if (!resource)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   src_entry = container_of(re

[PATCH 01/12] VMCI: context implementation.

2012-11-21 Thread George Zhang
VMCI Context code maintains state for vmci and allows the driver to communicate
with multiple VMs.

Signed-off-by: George Zhang 
Signed-off-by: Dmitry Torokhov 
Signed-off-by: Andy King 

---
 drivers/misc/vmw_vmci/vmci_context.c | 1223 ++
 drivers/misc/vmw_vmci/vmci_context.h |  183 +
 2 files changed, 1406 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.h

diff --git a/drivers/misc/vmw_vmci/vmci_context.c 
b/drivers/misc/vmw_vmci/vmci_context.c
new file mode 100644
index 000..6f5abb5
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_context.c
@@ -0,0 +1,1223 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+/*
+ * List of current VMCI contexts.  Contexts can be added by
+ * vmci_ctx_create() and removed via vmci_ctx_destroy().
+ * These, along with context lookup, are protected by the
+ * list structure's lock.
+ */
+static struct {
+   struct list_head head;
+   spinlock_t lock; /* Spinlock for context list operations */
+} ctx_list = {
+   .head = LIST_HEAD_INIT(ctx_list.head),
+   .lock = __SPIN_LOCK_UNLOCKED(ctx_list.lock),
+};
+
+/* Used by contexts that did not set up notify flag pointers */
+static bool ctx_dummy_notify;
+
+static void ctx_signal_notify(struct vmci_ctx *context)
+{
+   *context->notify = true;
+}
+
+static void ctx_clear_notify(struct vmci_ctx *context)
+{
+   *context->notify = false;
+}
+
+/*
+ * If nothing requires the attention of the guest, clears both
+ * notify flag and call.
+ */
+static void ctx_clear_notify_call(struct vmci_ctx *context)
+{
+   if (context->pending_datagrams == 0 &&
+   vmci_handle_arr_get_size(context->pending_doorbell_array) == 0)
+   ctx_clear_notify(context);
+}
+
+/*
+ * Sets the context's notify flag iff datagrams are pending for this
+ * context.  Called from vmci_setup_notify().
+ */
+void vmci_ctx_check_signal_notify(struct vmci_ctx *context)
+{
+   spin_lock(&context->lock);
+   if (context->pending_datagrams)
+   ctx_signal_notify(context);
+   spin_unlock(&context->lock);
+}
+
+/*
+ * Allocates and initializes a VMCI context.
+ */
+struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags,
+uintptr_t event_hnd,
+int user_version,
+const struct cred *cred)
+{
+   struct vmci_ctx *context;
+   int error;
+
+   if (cid == VMCI_INVALID_ID) {
+   pr_devel("Invalid context ID for VMCI context.\n");
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   if (priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
+   pr_devel("Invalid flag (flags=0x%x) for VMCI context.\n",
+priv_flags);
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   if (user_version == 0) {
+   pr_devel("Invalid suer_version %d\n", user_version);
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   context = kzalloc(sizeof(*context), GFP_KERNEL);
+   if (!context) {
+   pr_warn("Failed to allocate memory for VMCI context.\n");
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   kref_init(&context->kref);
+   spin_lock_init(&context->lock);
+   INIT_LIST_HEAD(&context->list_item);
+   INIT_LIST_HEAD(&context->datagram_queue);
+   INIT_LIST_HEAD(&context->notifier_list);
+
+   /* Initialize host-specific VMCI context. */
+   init_waitqueue_head(&context->host_context.wait_queue);
+
+   context->queue_pair_array = vmci_handle_arr_create(0);
+   if (!context->queue_pair_array) {
+   error = -ENOMEM;
+   goto err_free_ctx;
+   }
+
+   context->doorbell_array = vmci_handle_arr_create(0);
+   if (!context->doorbell_array) {
+   er

[PATCH 00/12] VMCI for Linux upstreaming

2012-11-21 Thread George Zhang

* * *
This series of VMCI linux upstreaming patches include latest udpate from
VMware.

Summary of changes:

- Sparse clean.
- Checkpatch clean with one exception, a "complex macro" in
  which we can't add parentheses.
- Remove all runtime assertions.
- Fix device name, so that existing user clients work.
- Fix VMCI handle lookup.


* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vmci kernel
module. The vmw_vsock kernel module will be presented in a later post.


* * *

VMCI allows virtual machines to communicate with host kernel modules
and the VMware hypervisors. User level applications both in a virtual
machine and on the host can use vmw_vmci through VMCI Sockets, a socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

In a virtual machine, VMCI is exposed as a regular PCI device. The
primary communication mechanisms supported are a point-to-point
bidirectional transport based on a pair of memory-mapped queues, and
asynchronous notifications in the form of datagrams and
doorbells. These features are available to kernel level components
such as HGFS and VMCI Sockets through the VMCI kernel API. In addition
to this, the VMCI kernel API provides support for receiving events
related to the state of the VMCI communication channels, and the
virtual machine itself.

Outside the virtual machine, the host side support of the VMCI kernel
module makes the same VMCI kernel API available to VMCI endpoints on
the host. In addition to this, the host side manages each VMCI device
in a virtual machine through a context object. This context object
serves to identify the virtual machine for communication, and to track
the resource consumption of the given VMCI device. Both operations
related to communication between the virtual machine and the host
kernel, and those related to the management of the VMCI device state
in the host kernel, are invoked by the user level component of the
hypervisor through a set of ioctls on the VMCI device node.  To
provide seamless support for nested virtualization, where a virtual
machine may use both a VMCI PCI device to talk to its hypervisor, and
the VMCI host side support to run nested virtual machines, the VMCI
host and virtual machine support are combined in a single kernel
module.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.



---

George Zhang (12):
  VMCI: context implementation.
  VMCI: datagram implementation.
  VMCI: doorbell implementation.
  VMCI: device driver implementaton.
  VMCI: event handling implementation.
  VMCI: handle array implementation.
  VMCI: queue pairs implementation.
  VMCI: resource object implementation.
  VMCI: routing implementation.
  VMCI: guest side driver implementation.
  VMCI: host side driver implementation.
  VMCI: Some header and config files.


 drivers/misc/Kconfig  |1 
 drivers/misc/Makefile |2 
 drivers/misc/vmw_vmci/Kconfig |   16 
 drivers/misc/vmw_vmci/Makefile|4 
 drivers/misc/vmw_vmci/vmci_common_int.h   |   32 
 drivers/misc/vmw_vmci/vmci_context.c  | 1223 ++
 drivers/misc/vmw_vmci/vmci_context.h  |  183 ++
 drivers/misc/vmw_vmci/vmci_datagram.c |  501 
 drivers/misc/vmw_vmci/vmci_datagram.h |   52 
 drivers/misc/vmw_vmci/vmci_doorbell.c |  605 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   51 
 drivers/misc/vmw_vmci/vmci_driver.c   |  117 +
 drivers/misc/vmw_vmci/vmci_driver.h   |   50 
 drivers/misc/vmw_vmci/vmci_event.c|  224 ++
 drivers/misc/vmw_vmci/vmci_event.h|   25 
 drivers/misc/vmw_vmci/vmci_guest.c|  757 ++
 drivers/misc/vmw_vmci/vmci_handle_array.c |  142 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   52 
 drivers/misc/vmw_vmci/vmci_host.c | 1036 +
 drivers/misc/vmw_vmci/vmci_queue_pair.c   | 3439 +
 drivers/misc/vmw_vmci/vmci_queue_pair.h 

[PATCH 6/6] VSOCK: header and config files.

2012-11-07 Thread George Zhang
VSOCK header files, Makefiles and Kconfig systems for Linux VSocket module.


Signed-off-by: George Zhang 
---
 include/linux/socket.h  |4 
 net/Kconfig |1 
 net/Makefile|1 
 net/vmw_vsock/Kconfig   |   14 +
 net/vmw_vsock/Makefile  |4 
 net/vmw_vsock/notify_qstate.c   |  627 +++
 net/vmw_vsock/vmci_sockets.h|  517 +
 net/vmw_vsock/vmci_sockets_packet.h |  106 ++
 net/vmw_vsock/vsock_common.h|  130 +++
 net/vmw_vsock/vsock_packet.h|  131 +++
 net/vmw_vsock/vsock_version.h   |   29 ++
 11 files changed, 1563 insertions(+), 1 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 25d6322..57bc85e 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -195,7 +195,8 @@ struct ucred {
 #define AF_CAIF37  /* CAIF sockets */
 #define AF_ALG 38  /* Algorithm sockets*/
 #define AF_NFC 39  /* NFC sockets  */
-#define AF_MAX 40  /* For now.. */
+#define AF_VSOCK   40  /* VMCI sockets */
+#define AF_MAX 41  /* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC  AF_UNSPEC
@@ -238,6 +239,7 @@ struct ucred {
 #define PF_CAIFAF_CAIF
 #define PF_ALG AF_ALG
 #define PF_NFC AF_NFC
+#define PF_VSOCK   AF_VSOCK
 #define PF_MAX AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/net/Kconfig b/net/Kconfig
index 245831b..75b8d5e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -216,6 +216,7 @@ source "net/dcb/Kconfig"
 source "net/dns_resolver/Kconfig"
 source "net/batman-adv/Kconfig"
 source "net/openvswitch/Kconfig"
+source "net/vmw_vsock/Kconfig"
 
 config RPS
boolean
diff --git a/net/Makefile b/net/Makefile
index 4f4ee08..cae59f4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_CEPH_LIB)+= ceph/
 obj-$(CONFIG_BATMAN_ADV)   += batman-adv/
 obj-$(CONFIG_NFC)  += nfc/
 obj-$(CONFIG_OPENVSWITCH)  += openvswitch/
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock/
diff --git a/net/vmw_vsock/Kconfig b/net/vmw_vsock/Kconfig
new file mode 100644
index 000..95e2568
--- /dev/null
+++ b/net/vmw_vsock/Kconfig
@@ -0,0 +1,14 @@
+#
+# Vsock protocol
+#
+
+config VMWARE_VSOCK
+   tristate "Virtual Socket protocol"
+   depends on VMWARE_VMCI
+   help
+ Virtual Socket Protocol is a socket protocol similar to TCP/IP
+ allowing comunication between Virtual Machines and VMware
+ hypervisor.
+
+ To compile this driver as a module, choose M here: the module
+ will be called vsock. If unsure, say N.
diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile
new file mode 100644
index 000..4e940fe
--- /dev/null
+++ b/net/vmw_vsock/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock.o
+
+vmw_vsock-y += af_vsock.o notify.o notify_qstate.o stats.o util.o \
+   vsock_addr.o
diff --git a/net/vmw_vsock/notify_qstate.c b/net/vmw_vsock/notify_qstate.c
new file mode 100644
index 000..9cc4b58
--- /dev/null
+++ b/net/vmw_vsock/notify_qstate.c
@@ -0,0 +1,627 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * notifyQState.c --
+ *
+ * Linux control notifications based on Queuepair state for the VMCI Stream
+ * Sockets protocol.
+ */
+
+#include 
+
+#include 
+
+#include   /* for NULL */
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) \
+   (vsk)->notify.pkt_q_state.field_name
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effe

[PATCH 5/6] VSOCK: utility functions.

2012-11-07 Thread George Zhang
VSOCK utility functions for Linux VSocket module.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/util.c |  626 ++
 net/vmw_vsock/util.h |  312 +
 2 files changed, 938 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h

diff --git a/net/vmw_vsock/util.c b/net/vmw_vsock/util.c
new file mode 100644
index 000..1c42b23
--- /dev/null
+++ b/net/vmw_vsock/util.c
@@ -0,0 +1,626 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+/*
+ * util.c --
+ *
+ * Utility functions for Linux VSocket module.
+ */
+
+#include 
+#include 
+#include 
+#include   /* for NULL */
+#include 
+
+#include "af_vsock.h"
+#include "util.h"
+
+struct list_head vsock_bind_table[VSOCK_HASH_SIZE + 1];
+struct list_head vsock_connected_table[VSOCK_HASH_SIZE];
+
+DEFINE_SPINLOCK(vsock_table_lock);
+
+/*
+ *
+ * vsock_vmci_log_pkt --
+ *
+ * Logs the provided packet.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_vmci_log_pkt(char const *function, u32 line, vsock_packet *pkt)
+{
+   char buf[256];
+   char *cur = buf;
+   int left = sizeof buf;
+   int written = 0;
+   char *type_strings[] = {
+   [VSOCK_PACKET_TYPE_INVALID] = "INVALID",
+   [VSOCK_PACKET_TYPE_REQUEST] = "REQUEST",
+   [VSOCK_PACKET_TYPE_NEGOTIATE] = "NEGOTIATE",
+   [VSOCK_PACKET_TYPE_OFFER] = "OFFER",
+   [VSOCK_PACKET_TYPE_ATTACH] = "ATTACH",
+   [VSOCK_PACKET_TYPE_WROTE] = "WROTE",
+   [VSOCK_PACKET_TYPE_READ] = "READ",
+   [VSOCK_PACKET_TYPE_RST] = "RST",
+   [VSOCK_PACKET_TYPE_SHUTDOWN] = "SHUTDOWN",
+   [VSOCK_PACKET_TYPE_WAITING_WRITE] = "WAITING_WRITE",
+   [VSOCK_PACKET_TYPE_WAITING_READ] = "WAITING_READ",
+   [VSOCK_PACKET_TYPE_REQUEST2] = "REQUEST2",
+   [VSOCK_PACKET_TYPE_NEGOTIATE2] = "NEGOTIATE2",
+   };
+
+   written = snprintf(cur, left, "PKT: %u:%u -> %u:%u",
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.src),
+  pkt->src_port,
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.dst),
+  pkt->dst_port);
+   if (written >= left)
+   goto error;
+
+   left -= written;
+   cur += written;
+
+   switch (pkt->type) {
+   case VSOCK_PACKET_TYPE_REQUEST:
+   case VSOCK_PACKET_TYPE_NEGOTIATE:
+   written = snprintf(cur, left, ", %s, size = %" FMT64 "u",
+  type_strings[pkt->type], pkt->u.size);
+   break;
+
+   case VSOCK_PACKET_TYPE_OFFER:
+   case VSOCK_PACKET_TYPE_ATTACH:
+   written = snprintf(cur, left, ", %s, handle = %u:%u",
+  type_strings[pkt->type],
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->u.handle),
+  VMCI_HANDLE_TO_RESOURCE_ID(pkt->u.handle));
+   break;
+
+   case VSOCK_PACKET_TYPE_WROTE:
+   case VSOCK_PACKET_TYPE_READ:
+   case VSOCK_PACKET_TYPE_RST:
+   written = snprintf(cur, left, ", %s", type_strings[pkt->type]);
+   break;
+   case VSOCK_PACKET_TYPE_SHUTDOWN: {
+   bool recv;
+   bool send;
+
+   recv = pkt->u.mode & RCV_SHUTDOWN;
+   send = pkt->u.mode & SEND_SHUTDOWN;
+   written = snprintf(cur, left, ", %s, mode = %c%c",
+  type_strings[pkt->type],
+  recv ? 'R' : ' ', send ? 'S' : ' ');
+   }
+   break;
+
+   case VSOCK_PACKET_TYPE_WAITING_WRITE:
+   case VSOCK_PACKET_TYPE_WAITING_READ:
+   written = snprintf(cur, left, ", %s, generation = %" FMT64 "u, "
+  "offset = %" FMT64 "u",
+  type_strings[pkt->type],
+  pkt->u.wait.generation, pkt->u.wait.offset)

[PATCH 4/6] VSOCK: statistics implementation.

2012-11-07 Thread George Zhang
VSOCK stats for VMCI Stream Sockets protocol.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/stats.c |   37 
 net/vmw_vsock/stats.h |  219 +
 2 files changed, 256 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h

diff --git a/net/vmw_vsock/stats.c b/net/vmw_vsock/stats.c
new file mode 100644
index 000..2d172d5
--- /dev/null
+++ b/net/vmw_vsock/stats.c
@@ -0,0 +1,37 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * stats.c --
+ *
+ * Linux stats for the VMCI Stream Sockets protocol.
+ */
+
+#include 
+
+#include 
+#include   /* for NULL */
+#include 
+
+#include "af_vsock.h"
+#include "stats.h"
+
+#ifdef VSOCK_GATHER_STATISTICS
+u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+atomic64_t vsock_stats_consume_total;
+atomic64_t vsock_stats_produce_total;
+#endif
diff --git a/net/vmw_vsock/stats.h b/net/vmw_vsock/stats.h
new file mode 100644
index 000..2f9d44c
--- /dev/null
+++ b/net/vmw_vsock/stats.h
@@ -0,0 +1,219 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * stats.h --
+ *
+ * Stats functions for Linux vsock module.
+ */
+
+#ifndef __STATS_H__
+#define __STATS_H__
+
+#include 
+
+#include "vsock_common.h"
+#include "vsock_packet.h"
+
+/*
+ * Define VSOCK_GATHER_STATISTICS to turn on statistics gathering. Currently
+ * this consists of 3 types of stats: 1. The number of control datagram
+ * messages sent. 2. The level of queuepair fullness (in 10% buckets) whenever
+ * data is about to be enqueued or dequeued from the queuepair. 3. The total
+ * number of bytes enqueued/dequeued.
+ */
+
+#ifdef VSOCK_GATHER_STATISTICS
+
+#define VSOCK_NUM_QUEUE_LEVEL_BUCKETS 10
+extern u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+extern u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern atomic64_t vsock_stats_consume_total;
+extern atomic64_t vsock_stats_produce_total;
+
+#define VSOCK_STATS_STREAM_CONSUME_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->consume_size,\
+   vmci_qpair_consume_buf_ready((vsk)->qpair), \
+   vsock_stats_consume_queue_hist)
+#define VSOCK_STATS_STREAM_PRODUCE_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->produce_size,\
+   vmci_qpair_produce_buf_ready((vsk)->qpair), \
+   vsock_stats_produce_queue_hist)
+#define VSOCK_STATS_CTLPKT_LOG(pkt_type)   \
+   do {\
+   ++vsock_stats_ctl_pkt_count[pkt_type];  \
+   } while (0)
+#define VSOCK_STATS_STREAM_CONSUME(bytes)  \
+   atomic64_add(&vsock_stats_consume_total, bytes)
+#define VSOCK_STATS_STREAM_PRODUCE(bytes)  \
+   atomic64_add(&vsock_stats_produce_total, bytes)
+#define VSOCK_STATS_CTLPKT_DUMP_ALL() vsock_vmci_stats_ctl_pkt_dump_all()
+#define VSOCK_STATS_HIST_DUMP_ALL()   vsock_vmci_stats_hist_dump_all()
+#define VSOCK_STATS_TOTALS_DUMP_ALL() vsock_vmci_stats_totals_dump_all()
+#define VSOCK_STATS_RESET()   vsock_vmci_stats_reset()
+
+/*
+ *
+ * vsock_vmci_stats_update_queue_bucket_count --
+ *
+ * Given a queue, determine how much data is enqueued and add that to the
+ * specified queue level statistic bucket.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */

[PATCH 3/6] VSOCK: notification implementation.

2012-11-07 Thread George Zhang
VSOCK control notifications for VMCI Stream Sockets protocol.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/notify.c |  984 
 net/vmw_vsock/notify.h |  130 ++
 2 files changed, 1114 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h

diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c
new file mode 100644
index 000..5c69c7c
--- /dev/null
+++ b/net/vmw_vsock/notify.c
@@ -0,0 +1,984 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * notify.c --
+ *
+ * Linux control notifications for the VMCI Stream Sockets protocol.
+ */
+
+#include 
+
+#include 
+#include   /* for NULL */
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) \
+   (vsk)->notify.pkt.field_name
+
+#define VSOCK_MAX_DGRAM_RESENDS   10
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+   bool retval;
+   u64 notify_limit;
+
+   if (!PKT_FIELD(vsk, peer_waiting_write))
+   return false;
+
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   /*
+* When the sender blocks, we take that as a sign that the sender is
+* faster than the receiver. To reduce the transmit rate of the sender,
+* we delay the sending of the read notification by decreasing the
+* write_notify_window. The notification is delayed until the number of
+* bytes used in the queue drops below the write_notify_window.
+*/
+
+   if (!PKT_FIELD(vsk, peer_waiting_write_detected)) {
+   PKT_FIELD(vsk, peer_waiting_write_detected) = true;
+   if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) {
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+   } else {
+   PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE;
+   if (PKT_FIELD(vsk, write_notify_window) <
+   PKT_FIELD(vsk, write_notify_min_window))
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+
+   }
+   }
+   notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window);
+#else
+   notify_limit = 0;
+#endif
+
+   /*
+* For now we ignore the wait information and just see if the free
+* space exceeds the notify limit.  Note that improving this function
+* to be more intelligent will not require a protocol change and will
+* retain compatibility between endpoints with mixed versions of this
+* function.
+*
+* The notify_limit is used to delay notifications in the case where
+* flow control is enabled. Below the test is expressed in terms of
+* free space in the queue: if free_space > ConsumeSize -
+* write_notify_window then notify An alternate way of expressing this
+* is to rewrite the expression to use the data ready in the receive
+* queue: if write_notify_window > bufferReady then notify as
+* free_space == ConsumeSize - bufferReady.
+*/
+   retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit;
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   if (retval) {
+   /*
+* Once we notify the peer, we reset the detected flag so the
+* next wait will again cause a decrease in the window size.
+*/
+
+   PKT_FIELD(vsk, peer_waiting_write_detected) = false;
+   }
+#endif
+   return retval;
+#else
+   return true;
+#endif
+}
+
+/*
+ *
+ * vsock_vmci_notify_waiting_read --
+ *
+ * Determines if the conditions have been met to notify a waiting reader.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+

[PATCH 2/6] VSOCK: vsock address implementaion.

2012-11-07 Thread George Zhang
VSOCK linux address code implementation.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/vsock_addr.c |  264 
 net/vmw_vsock/vsock_addr.h |   40 +++
 2 files changed, 304 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h

diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
new file mode 100644
index 000..c93a174
--- /dev/null
+++ b/net/vmw_vsock/vsock_addr.c
@@ -0,0 +1,264 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+/*
+ * vsockAddr.c --
+ *
+ * VSockets address implementation.
+ */
+
+/*
+ * These includes come before vsockCommon.h to ensure that VMware's ASSERT
+ * macro is used instead of Linux's irda.h definition.
+ */
+#include 
+#include 
+#include   /* for NULL */
+#include 
+
+#include "vsock_common.h"
+
+/*
+ *
+ * vsock_addr_init --
+ *
+ * Initialize the given address with the given context id and port. This will
+ * clear the address, set the correct family, and add the given values.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port)
+{
+   memset(addr, 0, sizeof *addr);
+
+   addr->svm_family = AF_VSOCK;
+   addr->svm_cid = cid;
+   addr->svm_port = port;
+
+   BUG_ON(vsock_addr_validate(addr) != 0);
+}
+
+/*
+ *
+ * vsock_addr_validate --
+ *
+ * Try to validate the given address.  The address must not be null and must
+ * have the correct address family.  Any reserved fields must be zero.
+ *
+ * Results: 0 on success, EFAULT if the address is null, EAFNOSUPPORT if the
+ * address is of the wrong family, and EINVAL if the reserved fields are not
+ * zero.
+ *
+ * Side effects: None.
+ */
+
+int vsock_addr_validate(const struct sockaddr_vm *addr)
+{
+   if (!addr)
+   return -EFAULT;
+
+   if (addr->svm_family != AF_VSOCK)
+   return -EAFNOSUPPORT;
+
+   if (addr->svm_zero[0] != 0)
+   return -EINVAL;
+
+   return 0;
+}
+
+/*
+ *
+ * vsock_addr_bound --
+ *
+ * Determines whether the provided address is bound.
+ *
+ * Results: TRUE if the address structure is bound, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_bound(const struct sockaddr_vm *addr)
+{
+   BUG_ON(!addr);
+
+   return addr->svm_port != VMADDR_PORT_ANY;
+}
+
+/*
+ *
+ * vsock_addr_unbind --
+ *
+ * Unbind the given addresss.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_addr_unbind(struct sockaddr_vm *addr)
+{
+   vsock_addr_init(addr, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+}
+
+/*
+ *
+ * vsock_addr_equals_addr --
+ *
+ * Determine if the given addresses are equal.
+ *
+ * Results: TRUE if the addresses are equal, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+   BUG_ON(vsock_addr_validate(other) != 0);
+
+   return addr->svm_cid == other->svm_cid &&
+   addr->svm_port == other->svm_port;
+}
+
+/*
+ *
+ * vsock_addr_equals_addr_any --
+ *
+ * Determine if the given addresses are equal. Will accept either an exact
+ * match or one where the rids match and that either the cids match or are set
+ * to VMADDR_CID_ANY.
+ *
+ * Results: TRUE if the addresses are equal, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+   BUG_ON(vsock_addr_validate(other) != 0);
+
+   return (addr->svm_cid == VMADDR_CID_ANY ||
+   other->svm_cid == VMADDR_CID_ANY ||
+   addr->svm_cid == other->svm_cid) &&
+  addr->svm_port == other->svm_port;
+}
+
+/*
+ *
+ * vsock_addr_equals_handle_port --
+ *
+ * Determines if the given address matches the given handle and port.
+ *
+ * Results: TRUE if the address matches the handle and port, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_handle_port(const struct sockaddr_vm *addr,
+  struct vmci_handle handle, u32 port)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+
+

[PATCH 0/6] VSOCK for Linux upstreaming

2012-11-07 Thread George Zhang

* * *
This series of VSOCK linux upstreaming patches include latest udpate from
VMware.

Summary of changes:
- Fix some new sparse issues.
- Remove some unneeded casts for VMCI.
- add more __user annotations for VMCI.
- Remove kernel version-specific bits from vSockets.


* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets (VSOCK)
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vsock kernel
module. The vmw_vmci kernel module has been presented in an early post.


* * *

VMCI Sockets allows virtual machines to communicate with host kernel
modules and the VMware hypervisors. VMCI Sockets kernel module has
dependency on VMCI kernel module. User level applications both in
a virtual machine and on the host can use vmw_vmci through VMCI
Sockets API which facilitates fast and efficient communication
between guest virtual machines and their host. A socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

The VMware VMCI Sockets are similar to other socket types, like
Berkeley UNIX socket interface. The VMCI sockets module supports
both connection-oriented stream sockets like TCP, and connectionless
datagram sockets like UDP. The VSOCK protocol family is defined as
"AF_VSOCK" and the socket operations split for SOCK_DGRAM and
SOCK_STREAM.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.



---

George Zhang (6):
  VSOCK: vsock protocol implementation.
  VSOCK: vsock address implementaion.
  VSOCK: notification implementation.
  VSOCK: statistics implementation.
  VSOCK: utility functions.
  VSOCK: header and config files.


 include/linux/socket.h  |4 
 net/Kconfig |1 
 net/Makefile|1 
 net/vmw_vsock/Kconfig   |   14 
 net/vmw_vsock/Makefile  |4 
 net/vmw_vsock/af_vsock.c| 4135 +++
 net/vmw_vsock/af_vsock.h|  179 ++
 net/vmw_vsock/notify.c  |  984 
 net/vmw_vsock/notify.h  |  130 +
 net/vmw_vsock/notify_qstate.c   |  627 +
 net/vmw_vsock/stats.c   |   37 
 net/vmw_vsock/stats.h   |  219 ++
 net/vmw_vsock/util.c|  626 +
 net/vmw_vsock/util.h|  312 +++
 net/vmw_vsock/vmci_sockets.h|  517 
 net/vmw_vsock/vmci_sockets_packet.h |  106 +
 net/vmw_vsock/vsock_addr.c  |  264 ++
 net/vmw_vsock/vsock_addr.h  |   40 
 net/vmw_vsock/vsock_common.h|  130 +
 net/vmw_vsock/vsock_packet.h|  131 +
 net/vmw_vsock/vsock_version.h   |   29 
 21 files changed, 8489 insertions(+), 1 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/af_vsock.c
 create mode 100644 net/vmw_vsock/af_vsock.h
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

-- 
Signature
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH 12/12] VMCI: Some header and config files.

2012-11-07 Thread George Zhang
VMCI head config patch Adds all the necessary files to enable building of the 
VMCI
module with the Linux Makefiles and Kconfig systems. Also adds the header files 
used
for building modules against the driver.


Signed-off-by: George Zhang 
---
 drivers/misc/Kconfig|1 
 drivers/misc/Makefile   |2 
 drivers/misc/vmw_vmci/Kconfig   |   16 +
 drivers/misc/vmw_vmci/Makefile  |4 
 drivers/misc/vmw_vmci/vmci_common_int.h |   34 +
 include/linux/vmw_vmci_api.h|   82 +++
 include/linux/vmw_vmci_defs.h   |  973 +++
 7 files changed, 1112 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/Kconfig
 create mode 100644 drivers/misc/vmw_vmci/Makefile
 create mode 100644 drivers/misc/vmw_vmci/vmci_common_int.h
 create mode 100644 include/linux/vmw_vmci_api.h
 create mode 100644 include/linux/vmw_vmci_defs.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2661f6e..fe38c7a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -517,4 +517,5 @@ source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
+source "drivers/misc/vmw_vmci/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 456972f..21ed953 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -51,3 +51,5 @@ obj-y += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)+= mei/
+obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
+obj-$(CONFIG_VMWARE_VMCI)  += vmw_vmci/
diff --git a/drivers/misc/vmw_vmci/Kconfig b/drivers/misc/vmw_vmci/Kconfig
new file mode 100644
index 000..55015e7
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Kconfig
@@ -0,0 +1,16 @@
+#
+# VMware VMCI device
+#
+
+config VMWARE_VMCI
+   tristate "VMware VMCI Driver"
+   depends on X86
+   help
+ This is VMware's Virtual Machine Communication Interface.  It enables
+ high-speed communication between host and guest in a virtual
+ environment via the VMCI virtual device.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vmw_vmci.
diff --git a/drivers/misc/vmw_vmci/Makefile b/drivers/misc/vmw_vmci/Makefile
new file mode 100644
index 000..4da9893
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci.o
+vmw_vmci-y += vmci_context.o vmci_datagram.o vmci_doorbell.o \
+   vmci_driver.o vmci_event.o vmci_guest.o vmci_handle_array.o \
+   vmci_host.o vmci_queue_pair.o vmci_resource.o vmci_route.o
diff --git a/drivers/misc/vmw_vmci/vmci_common_int.h 
b/drivers/misc/vmw_vmci/vmci_common_int.h
new file mode 100644
index 000..77667ec
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_common_int.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef _VMCI_COMMONINT_H_
+#define _VMCI_COMMONINT_H_
+
+#include 
+
+#define ASSERT(cond) BUG_ON(!(cond))
+
+#define PCI_VENDOR_ID_VMWARE   0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMCI  0x0740
+#define VMCI_DRIVER_VERSION_STRING "1.0.0.0-k"
+#define MODULE_NAME "vmw_vmci"
+
+/* Print magic... whee! */
+#ifdef pr_fmt
+#undef pr_fmt
+#define pr_fmt(fmt) MODULE_NAME ": " fmt
+#endif
+
+#endif /* _VMCI_COMMONINT_H_ */
diff --git a/include/linux/vmw_vmci_api.h b/include/linux/vmw_vmci_api.h
new file mode 100644
index 000..193129d
--- /dev/null
+++ b/include/linux/vmw_vmci_api.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef __VMW_VMCI_API_H__
+#define __VMW_VMCI_API_H__
+
+#include 
+#include 
+
+#undef  VMCI_KERNEL

[PATCH 11/12] VMCI: host side driver implementation.

2012-11-07 Thread George Zhang
VMCI host side driver code implementation.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_host.c | 1033 +
 1 files changed, 1033 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_host.c

diff --git a/drivers/misc/vmw_vmci/vmci_host.c 
b/drivers/misc/vmw_vmci/vmci_host.c
new file mode 100644
index 000..7580979
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_host.c
@@ -0,0 +1,1033 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_handle_array.h"
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+enum {
+   VMCI_NOTIFY_RESOURCE_QUEUE_PAIR = 0,
+   VMCI_NOTIFY_RESOURCE_DOOR_BELL = 1,
+};
+
+enum {
+   VMCI_NOTIFY_RESOURCE_ACTION_NOTIFY = 0,
+   VMCI_NOTIFY_RESOURCE_ACTION_CREATE = 1,
+   VMCI_NOTIFY_RESOURCE_ACTION_DESTROY = 2,
+};
+
+/*
+ * VMCI driver initialization. This block can also be used to
+ * pass initial group membership etc.
+ */
+struct vmci_init_blk {
+   u32 cid;
+   u32 flags;
+};
+
+/* VMCIqueue_pairAllocInfo_VMToVM */
+struct vmci_qp_alloc_info_vmvm {
+   struct vmci_handle handle;
+   u32 peer;
+   u32 flags;
+   u64 produce_size;
+   u64 consume_size;
+   u64 produce_page_file;/* User VA. */
+   u64 consume_page_file;/* User VA. */
+   u64 produce_page_file_size;  /* Size of the file name array. */
+   u64 consume_page_file_size;  /* Size of the file name array. */
+   s32 result;
+   u32 _pad;
+};
+
+/* VMCISetNotifyInfo: Used to pass notify flag's address to the host driver. */
+struct vmci_set_notify_info {
+   u64 notify_uva;
+   s32 result;
+   u32 _pad;
+};
+
+/*
+ * Per-instance host state
+ */
+struct vmci_host_dev {
+   struct vmci_ctx *context;
+   int user_version;
+   enum vmci_obj_type ct_type;
+   struct mutex lock;  /* Mutex lock for vmci context access */
+};
+
+static struct vmci_ctx *host_context;
+static bool vmci_host_device_initialized;
+static atomic_t vmci_host_active_users = ATOMIC_INIT(0);
+
+/*
+ * Determines whether the VMCI host personality is
+ * available. Since the core functionality of the host driver is
+ * always present, all guests could possibly use the host
+ * personality. However, to minimize the deviation from the
+ * pre-unified driver state of affairs, we only consider the host
+ * device active if there is no active guest device or if there
+ * are VMX'en with active VMCI contexts using the host device.
+ */
+bool vmci_host_code_active(void)
+{
+   return vmci_host_device_initialized &&
+   (!vmci_guest_code_active() ||
+atomic_read(&vmci_host_active_users) > 0);
+}
+
+/*
+ * Called on open of /dev/vmci.
+ */
+static int vmci_host_open(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev;
+
+   vmci_host_dev = kzalloc(sizeof(struct vmci_host_dev), GFP_KERNEL);
+   if (vmci_host_dev == NULL)
+   return -ENOMEM;
+
+   vmci_host_dev->ct_type = VMCIOBJ_NOT_SET;
+   mutex_init(&vmci_host_dev->lock);
+   filp->private_data = vmci_host_dev;
+
+   return 0;
+}
+
+/*
+ * Called on close of /dev/vmci, most often when the process
+ * exits.
+ */
+static int vmci_host_close(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev = filp->private_data;
+
+   if (vmci_host_dev->ct_type == VMCIOBJ_CONTEXT) {
+   vmci_ctx_destroy(vmci_host_dev->context);
+   vmci_host_dev->context = NULL;
+
+   /*
+* The number of active contexts is used to track whether any
+* VMX'en are using the host personality. It is incremented when
+* a context is created through the IOCTL_VMCI_INIT_CONTEXT
+* ioctl.
+*/
+   atomic_dec(&vmci_host_active_users);
+   }
+ 

[PATCH 10/12] VMCI: guest side driver implementation.

2012-11-07 Thread George Zhang
VMCI guest side driver code implementation.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_guest.c |  762 
 1 files changed, 762 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_guest.c

diff --git a/drivers/misc/vmw_vmci/vmci_guest.c 
b/drivers/misc/vmw_vmci/vmci_guest.c
new file mode 100644
index 000..eedbe4d
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -0,0 +1,762 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+static bool vmci_disable_msi;
+module_param_named(disable_msi, vmci_disable_msi, bool, 0);
+MODULE_PARM_DESC(disable_msi, "Disable MSI use in driver - (default=0)");
+
+static bool vmci_disable_msix;
+module_param_named(disable_msix, vmci_disable_msix, bool, 0);
+MODULE_PARM_DESC(disable_msix, "Disable MSI-X use in driver - (default=0)");
+
+static u32 ctx_update_sub_id = VMCI_INVALID_ID;
+static u32 vm_context_id = VMCI_INVALID_ID;
+
+struct vmci_guest_device {
+   struct device *dev; /* PCI device we are attached to */
+   void __iomem *iobase;
+
+   unsigned int irq;
+   unsigned int intr_type;
+   bool exclusive_vectors;
+   struct msix_entry msix_entries[VMCI_MAX_INTRS];
+
+   struct tasklet_struct datagram_tasklet;
+   struct tasklet_struct bm_tasklet;
+
+   void *data_buffer;
+   void *notification_bitmap;
+};
+
+/* vmci_dev singleton device and supporting data*/
+static struct vmci_guest_device *vmci_dev_g;
+static DEFINE_SPINLOCK(vmci_dev_spinlock);
+
+static atomic_t vmci_num_guest_devices = ATOMIC_INIT(0);
+
+bool vmci_guest_code_active(void)
+{
+   return atomic_read(&vmci_num_guest_devices) != 0;
+}
+
+u32 vmci_get_vm_context_id(void)
+{
+   if (vm_context_id == VMCI_INVALID_ID) {
+   u32 result;
+   struct vmci_datagram get_cid_msg;
+   get_cid_msg.dst =
+   vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
+VMCI_GET_CONTEXT_ID);
+   get_cid_msg.src = VMCI_ANON_SRC_HANDLE;
+   get_cid_msg.payload_size = 0;
+   result = vmci_send_datagram(&get_cid_msg);
+   if (result >= 0)
+   vm_context_id = result;
+   }
+   return vm_context_id;
+}
+
+/*
+ * VM to hypervisor call mechanism. We use the standard VMware naming
+ * convention since shared code is calling this function as well.
+ */
+int vmci_send_datagram(struct vmci_datagram *dg)
+{
+   unsigned long flags;
+   int result;
+
+   /* Check args. */
+   if (dg == NULL)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* Need to acquire spinlock on the device because the datagram
+* data may be spread over multiple pages and the monitor may
+* interleave device user rpc calls from multiple
+* VCPUs. Acquiring the spinlock precludes that
+* possibility. Disabling interrupts to avoid incoming
+* datagrams during a "rep out" and possibly landing up in
+* this function.
+*/
+   spin_lock_irqsave(&vmci_dev_spinlock, flags);
+
+   if (vmci_dev_g) {
+   iowrite8_rep(vmci_dev_g->iobase + VMCI_DATA_OUT_ADDR,
+dg, VMCI_DG_SIZE(dg));
+   result = ioread32(vmci_dev_g->iobase + VMCI_RESULT_LOW_ADDR);
+   } else {
+   result = VMCI_ERROR_UNAVAILABLE;
+   }
+
+   spin_unlock_irqrestore(&vmci_dev_spinlock, flags);
+
+   return result;
+}
+EXPORT_SYMBOL_GPL(vmci_send_datagram);
+
+/*
+ * Gets called with the new context id if updated or resumed.
+ * Context id.
+ */
+static void vmci_guest_cid_update(u32 sub_id,
+ const struct vmci_event_data *event_data,
+ void *client_data)
+{
+   const struct vmci_event_payld_ctx *ev_payload =
+   vmci_event_data_const_payload(event_data);
+
+   if (sub_id != ctx_update_sub_id) {

[PATCH 09/12] VMCI: routing implementation.

2012-11-07 Thread George Zhang
VMCI routing code is responsible for routing between various hosts/guests as 
well as
routing in nested scenarios.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_route.c |  229 
 drivers/misc/vmw_vmci/vmci_route.h |   30 +
 2 files changed, 259 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.h

diff --git a/drivers/misc/vmw_vmci/vmci_route.c 
b/drivers/misc/vmw_vmci/vmci_route.c
new file mode 100644
index 000..adf2f9f
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_route.c
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+/*
+ * Make a routing decision for the given source and destination handles.
+ * This will try to determine the route using the handles and the available
+ * devices.  Will set the source context if it is invalid.
+ */
+int vmci_route(struct vmci_handle *src,
+  const struct vmci_handle *dst,
+  bool from_guest,
+  enum vmci_route *route)
+{
+   bool has_host_device = vmci_host_code_active();
+   bool has_guest_device = vmci_guest_code_active();
+
+   *route = VMCI_ROUTE_NONE;
+
+   /*
+* "from_guest" is only ever set to true by
+* IOCTL_VMCI_DATAGRAM_SEND (or by the vmkernel equivalent),
+* which comes from the VMX, so we know it is coming from a
+* guest.
+*
+* To avoid inconsistencies, test these once.  We will test
+* them again when we do the actual send to ensure that we do
+* not touch a non-existent device.
+*/
+
+   /* Must have a valid destination context. */
+   if (VMCI_INVALID_ID == dst->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /* Anywhere to hypervisor. */
+   if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
+
+   /*
+* If this message already came from a guest then we
+* cannot send it to the hypervisor.  It must come
+* from a local client.
+*/
+   if (from_guest)
+   return VMCI_ERROR_DST_UNREACHABLE;
+
+   /*
+* We must be acting as a guest in order to send to
+* the hypervisor.
+*/
+   if (!has_guest_device)
+   return VMCI_ERROR_DEVICE_NOT_FOUND;
+
+   /* And we cannot send if the source is the host context. */
+   if (VMCI_HOST_CONTEXT_ID == src->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* If the client passed the ANON source handle then
+* respect it (both context and resource are invalid).
+* However, if they passed only an invalid context,
+* then they probably mean ANY, in which case we
+* should set the real context here before passing it
+* down.
+*/
+   if (VMCI_INVALID_ID == src->context &&
+   VMCI_INVALID_ID != src->resource)
+   src->context = vmci_get_context_id();
+
+   /* Send from local client down to the hypervisor. */
+   *route = VMCI_ROUTE_AS_GUEST;
+   return VMCI_SUCCESS;
+   }
+
+   /* Anywhere to local client on host. */
+   if (VMCI_HOST_CONTEXT_ID == dst->context) {
+   /*
+* If it is not from a guest but we are acting as a
+* guest, then we need to send it down to the host.
+* Note that if we are also acting as a host then this
+* will prevent us from sending from local client to
+* local client, but we accept that restriction as a
+* way to remove any ambiguity from the host context.
+*/
+   if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* If the hypervisor is the source, this is
+* host local communication. The hypervisor
+* may send vmci event datagrams to the host
+* its

[PATCH 08/12] VMCI: resource object implementation.

2012-11-07 Thread George Zhang
VMCI resource tracks all used resources within the vmci code.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_resource.c |  232 +
 drivers/misc/vmw_vmci/vmci_resource.h |   59 
 2 files changed, 291 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.h

diff --git a/drivers/misc/vmw_vmci/vmci_resource.c 
b/drivers/misc/vmw_vmci/vmci_resource.c
new file mode 100644
index 000..b241dde
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_resource.c
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+
+
+#define VMCI_RESOURCE_HASH_BITS 7
+#define VMCI_RESOURCE_HASH_BUCKETS  (1 << VMCI_RESOURCE_HASH_BITS)
+
+struct vmci_hash_table {
+   spinlock_t lock;
+   struct hlist_head entries[VMCI_RESOURCE_HASH_BUCKETS];
+};
+
+static struct vmci_hash_table vmci_resource_table = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_resource_table.lock),
+};
+
+static unsigned int vmci_resource_hash(struct vmci_handle handle)
+{
+   return hash_32(VMCI_HANDLE_TO_RESOURCE_ID(handle),
+  VMCI_RESOURCE_HASH_BITS);
+}
+
+/*
+ * Gets a resource (if one exists) matching given handle from the hash table.
+ */
+static struct vmci_resource *vmci_resource_lookup(struct vmci_handle handle)
+{
+   struct vmci_resource *r, *resource = NULL;
+   struct hlist_node *node;
+   unsigned int idx = vmci_resource_hash(handle);
+
+   rcu_read_lock();
+   hlist_for_each_entry_rcu(r, node,
+&vmci_resource_table.entries[idx], node) {
+   u32 rid = VMCI_HANDLE_TO_RESOURCE_ID(r->handle);
+   u32 cid = VMCI_HANDLE_TO_CONTEXT_ID(r->handle);
+
+   if (rid == VMCI_HANDLE_TO_RESOURCE_ID(handle) &&
+   (cid == VMCI_HANDLE_TO_CONTEXT_ID(handle) ||
+cid == VMCI_INVALID_ID)) {
+   resource = r;
+   break;
+   }
+   }
+   rcu_read_unlock();
+
+   return resource;
+}
+
+/*
+ * Find an unused resource ID and return it. The first
+ * VMCI_RESERVED_RESOURCE_ID_MAX are reserved so we start from
+ * its value + 1.
+ * Returns VMCI resource id on success, VMCI_INVALID_ID on failure.
+ */
+static u32 vmci_resource_find_id(u32 context_id)
+{
+   static u32 resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   u32 old_rid = resource_id;
+   u32 current_rid;
+
+   /*
+* Generate a unique resource ID.  Keep on trying until we wrap around
+* in the RID space.
+*/
+   BUG_ON(old_rid <= VMCI_RESERVED_RESOURCE_ID_MAX);
+
+   do {
+   struct vmci_handle handle;
+
+   current_rid = resource_id;
+   resource_id++;
+   if (unlikely(resource_id == VMCI_INVALID_ID)) {
+   /* Skip the reserved rids. */
+   resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   }
+
+   handle = vmci_make_handle(context_id, current_rid);
+   if (!vmci_resource_lookup(handle))
+   return current_rid;
+   } while (resource_id != old_rid);
+
+   return VMCI_INVALID_ID;
+}
+
+
+int vmci_resource_add(struct vmci_resource *resource,
+ enum vmci_resource_type resource_type,
+ struct vmci_handle handle)
+
+{
+   unsigned int idx;
+   int result;
+
+   spin_lock(&vmci_resource_table.lock);
+
+   if (handle.resource == VMCI_INVALID_ID) {
+   handle.resource = vmci_resource_find_id(handle.context);
+   if (handle.resource == VMCI_INVALID_ID) {
+   result = VMCI_ERROR_NO_HANDLE;
+   goto out;
+   }
+   } else if (vmci_resource_lookup(handle)) {
+   result = VMCI_ERROR_ALREADY_EXISTS;
+   goto out;
+   }
+
+   resource->handle = handle;
+   resource->type = resource_type;
+   INIT_HLIST_NODE(&resource->node);
+   kref_init(&resource->kref);
+   init_completion(&resource->done);
+
+   idx = vmci_resource_hash(resource->handle);
+ 

[PATCH 06/12] VMCI: handle array implementation.

2012-11-07 Thread George Zhang
VMCI handle code adds support for dynamic arrays that will grow if they need to.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_handle_array.c |  142 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   52 +++
 2 files changed, 194 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.h

diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c 
b/drivers/misc/vmw_vmci/vmci_handle_array.c
new file mode 100644
index 000..9122373
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_handle_array.c
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include 
+#include "vmci_handle_array.h"
+
+static size_t handle_arr_calc_size(size_t capacity)
+{
+   return sizeof(struct vmci_handle_arr) +
+   capacity * sizeof(struct vmci_handle);
+}
+
+struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity)
+{
+   struct vmci_handle_arr *array;
+
+   if (capacity == 0)
+   capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
+
+   array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC);
+   if (!array)
+   return NULL;
+
+   array->capacity = capacity;
+   array->size = 0;
+
+   return array;
+}
+
+void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
+{
+   kfree(array);
+}
+
+void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
+ struct vmci_handle handle)
+{
+   struct vmci_handle_arr *array = *array_ptr;
+
+   if (unlikely(array->size >= array->capacity)) {
+   /* reallocate. */
+   struct vmci_handle_arr *new_array;
+   size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT;
+   size_t new_size = handle_arr_calc_size(new_capacity);
+
+   new_array = krealloc(array, new_size, GFP_ATOMIC);
+   if (!new_array)
+   return;
+
+   new_array->capacity = new_capacity;
+   *array_ptr = array = new_array;
+   }
+
+   array->entries[array->size] = handle;
+   array->size++;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
+ */
+struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
+   struct vmci_handle entry_handle)
+{
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+   size_t i;
+
+   for (i = 0; i < array->size; i++) {
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle)) {
+   handle = array->entries[i];
+   array->size--;
+   array->entries[i] = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   break;
+   }
+   }
+
+   return handle;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
+ */
+struct vmci_handle vmci_handle_arr_remove_tail(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;
+}
+
+/*
+ * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
+ */
+struct vmci_handle
+vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index)
+{
+   if (unlikely(index >= array->size))
+   return VMCI_INVALID_HANDLE;
+
+   return array->entries[index];
+}
+
+bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
+  struct vmci_handle entry_handle)
+{
+   size_t i;
+
+   for (i = 0; i < array->size; i++)
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle))
+   return true;
+
+   return false;
+}
+
+/*
+ * NULL if the array is empty. Otherwise, a pointer to the array
+ * of VMCI handles in the handle array.
+ */
+struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array)
+{
+   if (array->size)
+   return array->entries;
+
+   return NULL;
+}
diff --git a/drivers/m

[PATCH 05/12] VMCI: event handling implementation.

2012-11-07 Thread George Zhang
VMCI event code that manages event handlers and handles callbacks when specific
events fire.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_event.c |  229 
 drivers/misc/vmw_vmci/vmci_event.h |   25 
 2 files changed, 254 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.h

diff --git a/drivers/misc/vmw_vmci/vmci_event.c 
b/drivers/misc/vmw_vmci/vmci_event.c
new file mode 100644
index 000..e956c18
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_event.c
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define EVENT_MAGIC 0xEABE
+#define VMCI_EVENT_MAX_ATTEMPTS 10
+
+struct vmci_subscription {
+   u32 id;
+   u32 event;
+   vmci_event_cb callback;
+   void *callback_data;
+   struct list_head node;  /* on one of subscriber lists */
+};
+
+static struct list_head subscriber_array[VMCI_EVENT_MAX];
+static DEFINE_MUTEX(subscriber_mutex);
+
+int __init vmci_event_init(void)
+{
+   int i;
+
+   for (i = 0; i < VMCI_EVENT_MAX; i++)
+   INIT_LIST_HEAD(&subscriber_array[i]);
+
+   return VMCI_SUCCESS;
+}
+
+void vmci_event_exit(void)
+{
+   int e;
+
+   /* We free all memory at exit. */
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur, *p2;
+   list_for_each_entry_safe(cur, p2, &subscriber_array[e], node) {
+
+   /*
+* We should never get here because all events
+* should have been unregistered before we try
+* to unload the driver module.
+*/
+   pr_warn("Unexpected free events occurring.\n");
+   list_del(&cur->node);
+   kfree(cur);
+   }
+   }
+}
+
+/*
+ * Find entry. Assumes subscriber_mutex is held.
+ */
+static struct vmci_subscription *event_find(u32 sub_id)
+{
+   int e;
+
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur;
+   list_for_each_entry(cur, &subscriber_array[e], node) {
+   if (cur->id == sub_id)
+   return cur;
+   }
+   }
+   return NULL;
+}
+
+/*
+ * Actually delivers the events to the subscribers.
+ * The callback function for each subscriber is invoked.
+ */
+static void event_deliver(struct vmci_event_msg *event_msg)
+{
+   struct vmci_subscription *cur;
+   struct list_head *subscriber_list;
+
+   rcu_read_lock();
+   subscriber_list = &subscriber_array[event_msg->event_data.event];
+   list_for_each_entry_rcu(cur, subscriber_list, node) {
+   BUG_ON(cur->event != event_msg->event_data.event);
+
+   cur->callback(cur->id, &event_msg->event_data,
+ cur->callback_data);
+   }
+   rcu_read_unlock();
+}
+
+/*
+ * Dispatcher for the VMCI_EVENT_RECEIVE datagrams. Calls all
+ * subscribers for given event.
+ */
+int vmci_event_dispatch(struct vmci_datagram *msg)
+{
+   struct vmci_event_msg *event_msg = (struct vmci_event_msg *)msg;
+
+   BUG_ON(msg->src.context != VMCI_HYPERVISOR_CONTEXT_ID ||
+  msg->dst.resource != VMCI_EVENT_HANDLER);
+
+   if (msg->payload_size < sizeof(u32) ||
+   msg->payload_size > sizeof(struct vmci_event_data_max))
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (!VMCI_EVENT_VALID(event_msg->event_data.event))
+   return VMCI_ERROR_EVENT_UNKNOWN;
+
+   event_deliver(event_msg);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * vmci_event_subscribe() - Subscribe to a given event.
+ * @event:  The event to subscribe to.
+ * @callback:   The callback to invoke upon the event.
+ * @callback_data:  Data to pass to the callback.
+ * @subscription_id:ID used to track subscription.  Used with
+ *  vmci_event_unsubscribe()
+ *
+ * Subscribes to the provided event. The callback specified will be
+ * fired from RCU critical section and therefore must not sleep.
+ */
+int vmci_event_sub

[PATCH 04/12] VMCI: device driver implementaton.

2012-11-07 Thread George Zhang
VMCI driver code implementes both the host and guest personalities of the VMCI 
driver.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_driver.c |  116 +++
 drivers/misc/vmw_vmci/vmci_driver.h |   50 +++
 2 files changed, 166 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.h

diff --git a/drivers/misc/vmw_vmci/vmci_driver.c 
b/drivers/misc/vmw_vmci/vmci_driver.c
new file mode 100644
index 000..8c5db38
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.c
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+static bool vmci_disable_host;
+module_param_named(disable_host, vmci_disable_host, bool, 0);
+MODULE_PARM_DESC(disable_host,
+"Disable driver host personality (default=enabled)");
+
+static bool vmci_disable_guest;
+module_param_named(disable_guest, vmci_disable_guest, bool, 0);
+MODULE_PARM_DESC(disable_guest,
+"Disable driver guest personality (default=enabled)");
+
+static bool vmci_guest_personality_initialized;
+static bool vmci_host_personality_initialized;
+
+/*
+ * vmci_get_context_id() - Gets the current context ID.
+ *
+ * Returns the current context ID.  Note that since this is accessed only
+ * from code running in the host, this always returns the host context ID.
+ */
+u32 vmci_get_context_id(void)
+{
+   if (vmci_guest_code_active())
+   return vmci_get_vm_context_id();
+   else if (vmci_host_code_active())
+   return VMCI_HOST_CONTEXT_ID;
+
+   return VMCI_INVALID_ID;
+}
+EXPORT_SYMBOL_GPL(vmci_get_context_id);
+
+static int __init vmci_drv_init(void)
+{
+   int vmci_err;
+   int error;
+
+   vmci_err = vmci_event_init();
+   if (vmci_err < VMCI_SUCCESS) {
+   pr_err("Failed to initialize VMCIEvent (result=%d).\n", 
vmci_err);
+   return -EINVAL;
+   }
+
+   if (!vmci_disable_guest) {
+   error = vmci_guest_init();
+   if (error) {
+   pr_warn("Failed to initialize guest personality 
(err=%d).\n",
+   error);
+   } else {
+   vmci_guest_personality_initialized = true;
+   pr_info("Guest personality initialized and is %s\n",
+   vmci_guest_code_active() ?
+   "active" : "inactive");
+   }
+   }
+
+   if (!vmci_disable_host) {
+   error = vmci_host_init();
+   if (error) {
+   pr_warn("Unable to initialize host personality 
(err=%d).\n",
+   error);
+   } else {
+   vmci_host_personality_initialized = true;
+   pr_info("Initialized host personality\n");
+   }
+   }
+
+   if (!vmci_guest_personality_initialized &&
+   !vmci_host_personality_initialized) {
+   vmci_event_exit();
+   return -ENODEV;
+   }
+
+   return 0;
+}
+module_init(vmci_drv_init);
+
+static void __exit vmci_drv_exit(void)
+{
+   if (vmci_guest_personality_initialized)
+   vmci_guest_exit();
+
+   if (vmci_host_personality_initialized)
+   vmci_host_exit();
+
+   vmci_event_exit();
+}
+module_exit(vmci_drv_exit);
+
+MODULE_AUTHOR("VMware, Inc.");
+MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
+MODULE_VERSION(VMCI_DRIVER_VERSION_STRING);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/vmw_vmci/vmci_driver.h 
b/drivers/misc/vmw_vmci/vmci_driver.h
new file mode 100644
index 000..f69156a
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.h
@@ -0,0 +1,50 @@
+/*
+ * 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 u

[PATCH 03/12] VMCI: doorbell implementation.

2012-11-07 Thread George Zhang
VMCI doorbell code allows for notifcations between host and guest.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_doorbell.c |  605 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   51 +++
 2 files changed, 656 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.h

diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.c 
b/drivers/misc/vmw_vmci/vmci_doorbell.c
new file mode 100644
index 000..eb87ca6
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -0,0 +1,605 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+
+#define VMCI_DOORBELL_INDEX_BITS   6
+#define VMCI_DOORBELL_INDEX_TABLE_SIZE (1 << VMCI_DOORBELL_INDEX_BITS)
+#define VMCI_DOORBELL_HASH(_idx)   hash_32(_idx, VMCI_DOORBELL_INDEX_BITS)
+
+/*
+ * DoorbellEntry describes the a doorbell notification handle allocated by the
+ * host.
+ */
+struct dbell_entry {
+   struct vmci_resource resource;
+   struct hlist_node node;
+   struct work_struct work;
+   vmci_callback notify_cb;
+   void *client_data;
+   u32 idx;
+   u32 priv_flags;
+   bool run_delayed;
+   atomic_t active;/* Only used by guest personality */
+};
+
+/* The VMCI index table keeps track of currently registered doorbells. */
+struct dbell_index_table {
+   spinlock_t lock;/* Index table lock */
+   struct hlist_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
+};
+
+static struct dbell_index_table vmci_doorbell_it = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_doorbell_it.lock),
+};
+
+/*
+ * The max_notify_idx is one larger than the currently known bitmap index in
+ * use, and is used to determine how much of the bitmap needs to be scanned.
+ */
+static u32 max_notify_idx;
+
+/*
+ * The notify_idx_count is used for determining whether there are free entries
+ * within the bitmap (if notify_idx_count + 1 < max_notify_idx).
+ */
+static u32 notify_idx_count;
+
+/*
+ * The last_notify_idx_reserved is used to track the last index handed out - in
+ * the case where multiple handles share a notification index, we hand out
+ * indexes round robin based on last_notify_idx_reserved.
+ */
+static u32 last_notify_idx_reserved;
+
+/* This is a one entry cache used to by the index allocation. */
+static u32 last_notify_idx_released = PAGE_SIZE;
+
+
+/*
+ * Utility function that retrieves the privilege flags associated
+ * with a given doorbell handle. For guest endpoints, the
+ * privileges are determined by the context ID, but for host
+ * endpoints privileges are associated with the complete
+ * handle. Hypervisor endpoints are not yet supported.
+ */
+int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags)
+{
+   if (priv_flags == NULL || handle.context == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (handle.context == VMCI_HOST_CONTEXT_ID) {
+   struct dbell_entry *entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DOORBELL);
+   if (!resource)
+   return VMCI_ERROR_NOT_FOUND;
+
+   entry = container_of(resource, struct dbell_entry, resource);
+   *priv_flags = entry->priv_flags;
+   vmci_resource_put(resource);
+   } else if (handle.context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* Hypervisor endpoints for notifications are not
+* supported (yet).
+*/
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   *priv_flags = vmci_context_get_priv_flags(handle.context);
+   }
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Find doorbell entry by bitmap index.
+ */
+static struct dbell_entry *dbell_index_table_find(u32 idx)
+{
+   u32 bucket = VMCI_DOORBELL_HASH(idx);
+   struct dbell_entry *dbell;
+   struct hlist_node *node;
+
+   hlist_for_each_entry(dbell, node, &vmci_doorbell

[PATCH 02/12] VMCI: datagram implementation.

2012-11-07 Thread George Zhang
VMCI datagram Implements datagrams to allow data to be sent between host and 
guest.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_datagram.c |  506 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   52 +++
 2 files changed, 558 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.h

diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c 
b/drivers/misc/vmw_vmci/vmci_datagram.c
new file mode 100644
index 000..d755e31
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -0,0 +1,506 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+#include "vmci_route.h"
+
+/*
+ * struct datagram_entry describes the datagram entity. It is used for datagram
+ * entities created only on the host.
+ */
+struct datagram_entry {
+   struct vmci_resource resource;
+   u32 flags;
+   bool run_delayed;
+   vmci_datagram_recv_cb recv_cb;
+   void *client_data;
+   u32 priv_flags;
+};
+
+struct delayed_datagram_info {
+   struct datagram_entry *entry;
+   struct vmci_datagram msg;
+   struct work_struct work;
+   bool in_dg_host_queue;
+};
+
+/* Number of in-flight host->host datagrams */
+static atomic_t delayed_dg_host_queue_size = ATOMIC_INIT(0);
+
+/*
+ * Create a datagram entry given a handle pointer.
+ */
+static int dg_create_handle(u32 resource_id,
+   u32 flags,
+   u32 priv_flags,
+   vmci_datagram_recv_cb recv_cb,
+   void *client_data, struct vmci_handle *out_handle)
+{
+   int result;
+   u32 context_id;
+   struct vmci_handle handle;
+   struct datagram_entry *entry;
+
+   BUG_ON(!recv_cb);
+   BUG_ON(!out_handle);
+   BUG_ON(priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS);
+
+   if ((flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if ((flags & VMCI_FLAG_ANYCID_DG_HND) != 0) {
+   context_id = VMCI_INVALID_ID;
+   } else {
+   context_id = vmci_get_context_id();
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_RESOURCES;
+   }
+
+   handle = vmci_make_handle(context_id, resource_id);
+
+   entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+   if (!entry) {
+   pr_warn("Failed allocating memory for datagram entry.\n");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   entry->run_delayed = (flags & VMCI_FLAG_DG_DELAYED_CB) ? true : false;
+   entry->flags = flags;
+   entry->recv_cb = recv_cb;
+   entry->client_data = client_data;
+   entry->priv_flags = priv_flags;
+
+   /* Make datagram resource live. */
+   result = vmci_resource_add(&entry->resource,
+  VMCI_RESOURCE_TYPE_DATAGRAM,
+  handle);
+   if (result != VMCI_SUCCESS) {
+   pr_warn("Failed to add new resource (handle=0x%x:0x%x), error: 
%d\n",
+   handle.context, handle.resource, result);
+   kfree(entry);
+   return result;
+   }
+
+   *out_handle = vmci_resource_handle(&entry->resource);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Internal utility function with the same purpose as
+ * vmci_datagram_get_priv_flags that also takes a context_id.
+ */
+static int vmci_datagram_get_priv_flags(u32 context_id,
+   struct vmci_handle handle,
+   u32 *priv_flags)
+{
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (context_id == VMCI_HOST_CONTEXT_ID) {
+   struct datagram_entry *src_entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DATAGRAM);
+   if (!resource)
+   return VMCI_ERROR_I

[PATCH 01/12] VMCI: context implementation.

2012-11-07 Thread George Zhang
VMCI Context code maintains state for vmci and allows the driver to communicate 
with
multiple VMs.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_context.c | 1246 ++
 drivers/misc/vmw_vmci/vmci_context.h |  183 +
 2 files changed, 1429 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.h

diff --git a/drivers/misc/vmw_vmci/vmci_context.c 
b/drivers/misc/vmw_vmci/vmci_context.c
new file mode 100644
index 000..a46bfaa
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_context.c
@@ -0,0 +1,1246 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+/*
+ * List of current VMCI contexts.  Contexts can be added by
+ * vmci_ctx_create() and removed via vmci_ctx_destroy().
+ * These, along with context lookup, are protected by the
+ * list structure's lock.
+ */
+static struct {
+   struct list_head head;
+   spinlock_t lock; /* Spinlock for context list operations */
+} ctx_list = {
+   .head = LIST_HEAD_INIT(ctx_list.head),
+   .lock = __SPIN_LOCK_UNLOCKED(ctx_list.lock),
+};
+
+/* Used by contexts that did not set up notify flag pointers */
+static bool ctx_dummy_notify;
+
+static void ctx_signal_notify(struct vmci_ctx *context)
+{
+   *context->notify = true;
+}
+
+static void ctx_clear_notify(struct vmci_ctx *context)
+{
+   *context->notify = false;
+}
+
+/*
+ * If nothing requires the attention of the guest, clears both
+ * notify flag and call.
+ */
+static void ctx_clear_notify_call(struct vmci_ctx *context)
+{
+   if (context->pending_datagrams == 0 &&
+   vmci_handle_arr_get_size(context->pending_doorbell_array) == 0)
+   ctx_clear_notify(context);
+}
+
+/*
+ * Sets the context's notify flag iff datagrams are pending for this
+ * context.  Called from vmci_setup_notify().
+ */
+void vmci_ctx_check_signal_notify(struct vmci_ctx *context)
+{
+   spin_lock(&context->lock);
+   if (context->pending_datagrams)
+   ctx_signal_notify(context);
+   spin_unlock(&context->lock);
+}
+
+/*
+ * Allocates and initializes a VMCI context.
+ */
+struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags,
+uintptr_t event_hnd,
+int user_version,
+const struct cred *cred)
+{
+   struct vmci_ctx *context;
+   int error;
+
+   if (cid == VMCI_INVALID_ID) {
+   pr_devel("Invalid context ID for VMCI context.\n");
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   if (priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
+   pr_devel("Invalid flag (flags=0x%x) for VMCI context.\n",
+priv_flags);
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   if (user_version == 0) {
+   pr_devel("Invalid suer_version %d\n", user_version);
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   context = kzalloc(sizeof(*context), GFP_KERNEL);
+   if (!context) {
+   pr_warn("Failed to allocate memory for VMCI context.\n");
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   kref_init(&context->kref);
+   spin_lock_init(&context->lock);
+   INIT_LIST_HEAD(&context->list_item);
+   INIT_LIST_HEAD(&context->datagram_queue);
+   INIT_LIST_HEAD(&context->notifier_list);
+
+   /* Initialize host-specific VMCI context. */
+   init_waitqueue_head(&context->host_context.wait_queue);
+
+   context->queue_pair_array = vmci_handle_arr_create(0);
+   if (!context->queue_pair_array) {
+   error = -ENOMEM;
+   goto err_free_ctx;
+   }
+
+   context->doorbell_array = vmci_handle_arr_create(0);
+   if (!context->doorbell_array) {
+   error = -ENOMEM;
+   goto err_

[PATCH 00/12] VMCI for Linux upstreaming

2012-11-07 Thread George Zhang

* * *
This series of VMCI linux upstreaming patches include latest udpate from
VMware.

Summary of changes:
- Fix some new sparse issues.
- Remove some unneeded casts for VMCI.
- add more __user annotations for VMCI.
- Remove kernel version-specific bits from vSockets.


* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vmci kernel
module. The vmw_vsock kernel module will be presented in a later post.


* * *

VMCI allows virtual machines to communicate with host kernel modules
and the VMware hypervisors. User level applications both in a virtual
machine and on the host can use vmw_vmci through VMCI Sockets, a socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

In a virtual machine, VMCI is exposed as a regular PCI device. The
primary communication mechanisms supported are a point-to-point
bidirectional transport based on a pair of memory-mapped queues, and
asynchronous notifications in the form of datagrams and
doorbells. These features are available to kernel level components
such as HGFS and VMCI Sockets through the VMCI kernel API. In addition
to this, the VMCI kernel API provides support for receiving events
related to the state of the VMCI communication channels, and the
virtual machine itself.

Outside the virtual machine, the host side support of the VMCI kernel
module makes the same VMCI kernel API available to VMCI endpoints on
the host. In addition to this, the host side manages each VMCI device
in a virtual machine through a context object. This context object
serves to identify the virtual machine for communication, and to track
the resource consumption of the given VMCI device. Both operations
related to communication between the virtual machine and the host
kernel, and those related to the management of the VMCI device state
in the host kernel, are invoked by the user level component of the
hypervisor through a set of ioctls on the VMCI device node.  To
provide seamless support for nested virtualization, where a virtual
machine may use both a VMCI PCI device to talk to its hypervisor, and
the VMCI host side support to run nested virtual machines, the VMCI
host and virtual machine support are combined in a single kernel
module.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.



---

George Zhang (12):
  VMCI: context implementation.
  VMCI: datagram implementation.
  VMCI: doorbell implementation.
  VMCI: device driver implementaton.
  VMCI: event handling implementation.
  VMCI: handle array implementation.
  VMCI: queue pairs implementation.
  VMCI: resource object implementation.
  VMCI: routing implementation.
  VMCI: guest side driver implementation.
  VMCI: host side driver implementation.
  VMCI: Some header and config files.


 drivers/misc/Kconfig  |1 
 drivers/misc/Makefile |2 
 drivers/misc/vmw_vmci/Kconfig |   16 
 drivers/misc/vmw_vmci/Makefile|4 
 drivers/misc/vmw_vmci/vmci_common_int.h   |   34 
 drivers/misc/vmw_vmci/vmci_context.c  | 1246 ++
 drivers/misc/vmw_vmci/vmci_context.h  |  183 ++
 drivers/misc/vmw_vmci/vmci_datagram.c |  506 
 drivers/misc/vmw_vmci/vmci_datagram.h |   52 
 drivers/misc/vmw_vmci/vmci_doorbell.c |  605 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   51 
 drivers/misc/vmw_vmci/vmci_driver.c   |  116 +
 drivers/misc/vmw_vmci/vmci_driver.h   |   50 
 drivers/misc/vmw_vmci/vmci_event.c|  229 ++
 drivers/misc/vmw_vmci/vmci_event.h|   25 
 drivers/misc/vmw_vmci/vmci_guest.c|  762 ++
 drivers/misc/vmw_vmci/vmci_handle_array.c |  142 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   52 
 drivers/misc/vmw_vmci/vmci_host.c | 1033 +
 drivers/misc/vmw_vmci/vmci_queue_pair.c   | 3506 +
 drivers/misc/vmw_vmci/vmci_queue_pair.h   |  191 ++
 drivers/misc/vmw_vmci/vmci_resource.c |  232 ++
 drivers/misc/vmw

Re: [PATCH 0/6] VSOCK for Linux upstreaming

2012-11-05 Thread George Zhang
Sasha,
There is a 'brief' implementation notes aboutVSOCK protocol family
in af_vsock.c. More about user space layer socket programming is from
VMCI Socket Programming Guide. (remove crosst...@vmware.com for email bouncing).
thanks,
George

- Original Message -
From: "Sasha Levin" 
To: "George Zhang" 
Cc: net...@vger.kernel.org, linux-ker...@vger.kernel.org, 
virtualization@lists.linux-foundation.org, pv-driv...@vmware.com, 
vm-crosst...@vmware.com, da...@davemloft.net, gre...@linuxfoundation.org
Sent: Monday, November 5, 2012 10:23:02 AM
Subject: Re: [PATCH 0/6] VSOCK for Linux upstreaming

Hi George,

On Mon, Nov 5, 2012 at 1:00 PM, George Zhang  wrote:
> For additional information about the use of VMCI and in particular
> VMCI Sockets, please refer to the VMCI Socket Programming Guide
> available at https://www.vmware.com/support/developer/vmci-sdk/.

Is there documentation about the protocol itself? I couldn't find it
on the link above.


Thanks,
Sasha
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


Re: [PATCH 0/6] VSOCK for Linux upstreaming

2012-11-05 Thread George Zhang
David,
We will fix this bounces and remove the email: crosst...@vmware.com.
Thanks,
george zhang

- Original Message -
From: "David Miller" 
To: georgezh...@vmware.com
Cc: net...@vger.kernel.org, linux-ker...@vger.kernel.org, 
virtualization@lists.linux-foundation.org, pv-driv...@vmware.com, 
vm-crosst...@vmware.com, gre...@linuxfoundation.org
Sent: Monday, November 5, 2012 10:10:37 AM
Subject: Re: [PATCH 0/6] VSOCK for Linux upstreaming

From: David Miller 
Date: Mon, 05 Nov 2012 13:09:17 -0500 (EST)

> The big and only question is whether anyone can actually use any of
> this stuff without your proprietary bits?

And BTW vm-crosst...@vmware.com bounces, take it out of the CC: list
on all future emails.
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH 6/6] VSOCK: header and config files.

2012-11-05 Thread George Zhang
VSOCK header files, Makefiles and Kconfig systems for Linux VSocket module.


Signed-off-by: George Zhang 
---
 include/linux/socket.h  |4 
 net/Kconfig |1 
 net/Makefile|1 
 net/vmw_vsock/Kconfig   |   14 +
 net/vmw_vsock/Makefile  |4 
 net/vmw_vsock/notify_qstate.c   |  627 +++
 net/vmw_vsock/vmci_sockets.h|  517 +
 net/vmw_vsock/vmci_sockets_packet.h |  106 ++
 net/vmw_vsock/vsock_common.h|  130 +++
 net/vmw_vsock/vsock_packet.h|  131 +++
 net/vmw_vsock/vsock_version.h   |   29 ++
 11 files changed, 1563 insertions(+), 1 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 25d6322..57bc85e 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -195,7 +195,8 @@ struct ucred {
 #define AF_CAIF37  /* CAIF sockets */
 #define AF_ALG 38  /* Algorithm sockets*/
 #define AF_NFC 39  /* NFC sockets  */
-#define AF_MAX 40  /* For now.. */
+#define AF_VSOCK   40  /* VMCI sockets */
+#define AF_MAX 41  /* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC  AF_UNSPEC
@@ -238,6 +239,7 @@ struct ucred {
 #define PF_CAIFAF_CAIF
 #define PF_ALG AF_ALG
 #define PF_NFC AF_NFC
+#define PF_VSOCK   AF_VSOCK
 #define PF_MAX AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/net/Kconfig b/net/Kconfig
index 245831b..75b8d5e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -216,6 +216,7 @@ source "net/dcb/Kconfig"
 source "net/dns_resolver/Kconfig"
 source "net/batman-adv/Kconfig"
 source "net/openvswitch/Kconfig"
+source "net/vmw_vsock/Kconfig"
 
 config RPS
boolean
diff --git a/net/Makefile b/net/Makefile
index 4f4ee08..cae59f4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_CEPH_LIB)+= ceph/
 obj-$(CONFIG_BATMAN_ADV)   += batman-adv/
 obj-$(CONFIG_NFC)  += nfc/
 obj-$(CONFIG_OPENVSWITCH)  += openvswitch/
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock/
diff --git a/net/vmw_vsock/Kconfig b/net/vmw_vsock/Kconfig
new file mode 100644
index 000..95e2568
--- /dev/null
+++ b/net/vmw_vsock/Kconfig
@@ -0,0 +1,14 @@
+#
+# Vsock protocol
+#
+
+config VMWARE_VSOCK
+   tristate "Virtual Socket protocol"
+   depends on VMWARE_VMCI
+   help
+ Virtual Socket Protocol is a socket protocol similar to TCP/IP
+ allowing comunication between Virtual Machines and VMware
+ hypervisor.
+
+ To compile this driver as a module, choose M here: the module
+ will be called vsock. If unsure, say N.
diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile
new file mode 100644
index 000..4e940fe
--- /dev/null
+++ b/net/vmw_vsock/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock.o
+
+vmw_vsock-y += af_vsock.o notify.o notify_qstate.o stats.o util.o \
+   vsock_addr.o
diff --git a/net/vmw_vsock/notify_qstate.c b/net/vmw_vsock/notify_qstate.c
new file mode 100644
index 000..9cc4b58
--- /dev/null
+++ b/net/vmw_vsock/notify_qstate.c
@@ -0,0 +1,627 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * notifyQState.c --
+ *
+ * Linux control notifications based on Queuepair state for the VMCI Stream
+ * Sockets protocol.
+ */
+
+#include 
+
+#include 
+
+#include   /* for NULL */
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) \
+   (vsk)->notify.pkt_q_state.field_name
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effe

[PATCH 5/6] VSOCK: utility functions.

2012-11-05 Thread George Zhang
VSOCK utility functions for Linux VSocket module.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/util.c |  626 ++
 net/vmw_vsock/util.h |  312 +
 2 files changed, 938 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h

diff --git a/net/vmw_vsock/util.c b/net/vmw_vsock/util.c
new file mode 100644
index 000..1c42b23
--- /dev/null
+++ b/net/vmw_vsock/util.c
@@ -0,0 +1,626 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+/*
+ * util.c --
+ *
+ * Utility functions for Linux VSocket module.
+ */
+
+#include 
+#include 
+#include 
+#include   /* for NULL */
+#include 
+
+#include "af_vsock.h"
+#include "util.h"
+
+struct list_head vsock_bind_table[VSOCK_HASH_SIZE + 1];
+struct list_head vsock_connected_table[VSOCK_HASH_SIZE];
+
+DEFINE_SPINLOCK(vsock_table_lock);
+
+/*
+ *
+ * vsock_vmci_log_pkt --
+ *
+ * Logs the provided packet.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_vmci_log_pkt(char const *function, u32 line, vsock_packet *pkt)
+{
+   char buf[256];
+   char *cur = buf;
+   int left = sizeof buf;
+   int written = 0;
+   char *type_strings[] = {
+   [VSOCK_PACKET_TYPE_INVALID] = "INVALID",
+   [VSOCK_PACKET_TYPE_REQUEST] = "REQUEST",
+   [VSOCK_PACKET_TYPE_NEGOTIATE] = "NEGOTIATE",
+   [VSOCK_PACKET_TYPE_OFFER] = "OFFER",
+   [VSOCK_PACKET_TYPE_ATTACH] = "ATTACH",
+   [VSOCK_PACKET_TYPE_WROTE] = "WROTE",
+   [VSOCK_PACKET_TYPE_READ] = "READ",
+   [VSOCK_PACKET_TYPE_RST] = "RST",
+   [VSOCK_PACKET_TYPE_SHUTDOWN] = "SHUTDOWN",
+   [VSOCK_PACKET_TYPE_WAITING_WRITE] = "WAITING_WRITE",
+   [VSOCK_PACKET_TYPE_WAITING_READ] = "WAITING_READ",
+   [VSOCK_PACKET_TYPE_REQUEST2] = "REQUEST2",
+   [VSOCK_PACKET_TYPE_NEGOTIATE2] = "NEGOTIATE2",
+   };
+
+   written = snprintf(cur, left, "PKT: %u:%u -> %u:%u",
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.src),
+  pkt->src_port,
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.dst),
+  pkt->dst_port);
+   if (written >= left)
+   goto error;
+
+   left -= written;
+   cur += written;
+
+   switch (pkt->type) {
+   case VSOCK_PACKET_TYPE_REQUEST:
+   case VSOCK_PACKET_TYPE_NEGOTIATE:
+   written = snprintf(cur, left, ", %s, size = %" FMT64 "u",
+  type_strings[pkt->type], pkt->u.size);
+   break;
+
+   case VSOCK_PACKET_TYPE_OFFER:
+   case VSOCK_PACKET_TYPE_ATTACH:
+   written = snprintf(cur, left, ", %s, handle = %u:%u",
+  type_strings[pkt->type],
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->u.handle),
+  VMCI_HANDLE_TO_RESOURCE_ID(pkt->u.handle));
+   break;
+
+   case VSOCK_PACKET_TYPE_WROTE:
+   case VSOCK_PACKET_TYPE_READ:
+   case VSOCK_PACKET_TYPE_RST:
+   written = snprintf(cur, left, ", %s", type_strings[pkt->type]);
+   break;
+   case VSOCK_PACKET_TYPE_SHUTDOWN: {
+   bool recv;
+   bool send;
+
+   recv = pkt->u.mode & RCV_SHUTDOWN;
+   send = pkt->u.mode & SEND_SHUTDOWN;
+   written = snprintf(cur, left, ", %s, mode = %c%c",
+  type_strings[pkt->type],
+  recv ? 'R' : ' ', send ? 'S' : ' ');
+   }
+   break;
+
+   case VSOCK_PACKET_TYPE_WAITING_WRITE:
+   case VSOCK_PACKET_TYPE_WAITING_READ:
+   written = snprintf(cur, left, ", %s, generation = %" FMT64 "u, "
+  "offset = %" FMT64 "u",
+  type_strings[pkt->type],
+  pkt->u.wait.generation, pkt->u.wait.offset)

[PATCH 4/6] VSOCK: statistics implementation.

2012-11-05 Thread George Zhang
VSOCK stats for VMCI Stream Sockets protocol.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/stats.c |   37 
 net/vmw_vsock/stats.h |  219 +
 2 files changed, 256 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h

diff --git a/net/vmw_vsock/stats.c b/net/vmw_vsock/stats.c
new file mode 100644
index 000..2d172d5
--- /dev/null
+++ b/net/vmw_vsock/stats.c
@@ -0,0 +1,37 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * stats.c --
+ *
+ * Linux stats for the VMCI Stream Sockets protocol.
+ */
+
+#include 
+
+#include 
+#include   /* for NULL */
+#include 
+
+#include "af_vsock.h"
+#include "stats.h"
+
+#ifdef VSOCK_GATHER_STATISTICS
+u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+atomic64_t vsock_stats_consume_total;
+atomic64_t vsock_stats_produce_total;
+#endif
diff --git a/net/vmw_vsock/stats.h b/net/vmw_vsock/stats.h
new file mode 100644
index 000..2f9d44c
--- /dev/null
+++ b/net/vmw_vsock/stats.h
@@ -0,0 +1,219 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * stats.h --
+ *
+ * Stats functions for Linux vsock module.
+ */
+
+#ifndef __STATS_H__
+#define __STATS_H__
+
+#include 
+
+#include "vsock_common.h"
+#include "vsock_packet.h"
+
+/*
+ * Define VSOCK_GATHER_STATISTICS to turn on statistics gathering. Currently
+ * this consists of 3 types of stats: 1. The number of control datagram
+ * messages sent. 2. The level of queuepair fullness (in 10% buckets) whenever
+ * data is about to be enqueued or dequeued from the queuepair. 3. The total
+ * number of bytes enqueued/dequeued.
+ */
+
+#ifdef VSOCK_GATHER_STATISTICS
+
+#define VSOCK_NUM_QUEUE_LEVEL_BUCKETS 10
+extern u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+extern u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern atomic64_t vsock_stats_consume_total;
+extern atomic64_t vsock_stats_produce_total;
+
+#define VSOCK_STATS_STREAM_CONSUME_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->consume_size,\
+   vmci_qpair_consume_buf_ready((vsk)->qpair), \
+   vsock_stats_consume_queue_hist)
+#define VSOCK_STATS_STREAM_PRODUCE_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->produce_size,\
+   vmci_qpair_produce_buf_ready((vsk)->qpair), \
+   vsock_stats_produce_queue_hist)
+#define VSOCK_STATS_CTLPKT_LOG(pkt_type)   \
+   do {\
+   ++vsock_stats_ctl_pkt_count[pkt_type];  \
+   } while (0)
+#define VSOCK_STATS_STREAM_CONSUME(bytes)  \
+   atomic64_add(&vsock_stats_consume_total, bytes)
+#define VSOCK_STATS_STREAM_PRODUCE(bytes)  \
+   atomic64_add(&vsock_stats_produce_total, bytes)
+#define VSOCK_STATS_CTLPKT_DUMP_ALL() vsock_vmci_stats_ctl_pkt_dump_all()
+#define VSOCK_STATS_HIST_DUMP_ALL()   vsock_vmci_stats_hist_dump_all()
+#define VSOCK_STATS_TOTALS_DUMP_ALL() vsock_vmci_stats_totals_dump_all()
+#define VSOCK_STATS_RESET()   vsock_vmci_stats_reset()
+
+/*
+ *
+ * vsock_vmci_stats_update_queue_bucket_count --
+ *
+ * Given a queue, determine how much data is enqueued and add that to the
+ * specified queue level statistic bucket.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */

[PATCH 3/6] VSOCK: notification implementation.

2012-11-05 Thread George Zhang
VSOCK control notifications for VMCI Stream Sockets protocol.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/notify.c |  984 
 net/vmw_vsock/notify.h |  130 ++
 2 files changed, 1114 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h

diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c
new file mode 100644
index 000..5c69c7c
--- /dev/null
+++ b/net/vmw_vsock/notify.c
@@ -0,0 +1,984 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * notify.c --
+ *
+ * Linux control notifications for the VMCI Stream Sockets protocol.
+ */
+
+#include 
+
+#include 
+#include   /* for NULL */
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) \
+   (vsk)->notify.pkt.field_name
+
+#define VSOCK_MAX_DGRAM_RESENDS   10
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+   bool retval;
+   u64 notify_limit;
+
+   if (!PKT_FIELD(vsk, peer_waiting_write))
+   return false;
+
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   /*
+* When the sender blocks, we take that as a sign that the sender is
+* faster than the receiver. To reduce the transmit rate of the sender,
+* we delay the sending of the read notification by decreasing the
+* write_notify_window. The notification is delayed until the number of
+* bytes used in the queue drops below the write_notify_window.
+*/
+
+   if (!PKT_FIELD(vsk, peer_waiting_write_detected)) {
+   PKT_FIELD(vsk, peer_waiting_write_detected) = true;
+   if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) {
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+   } else {
+   PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE;
+   if (PKT_FIELD(vsk, write_notify_window) <
+   PKT_FIELD(vsk, write_notify_min_window))
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+
+   }
+   }
+   notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window);
+#else
+   notify_limit = 0;
+#endif
+
+   /*
+* For now we ignore the wait information and just see if the free
+* space exceeds the notify limit.  Note that improving this function
+* to be more intelligent will not require a protocol change and will
+* retain compatibility between endpoints with mixed versions of this
+* function.
+*
+* The notify_limit is used to delay notifications in the case where
+* flow control is enabled. Below the test is expressed in terms of
+* free space in the queue: if free_space > ConsumeSize -
+* write_notify_window then notify An alternate way of expressing this
+* is to rewrite the expression to use the data ready in the receive
+* queue: if write_notify_window > bufferReady then notify as
+* free_space == ConsumeSize - bufferReady.
+*/
+   retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit;
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   if (retval) {
+   /*
+* Once we notify the peer, we reset the detected flag so the
+* next wait will again cause a decrease in the window size.
+*/
+
+   PKT_FIELD(vsk, peer_waiting_write_detected) = false;
+   }
+#endif
+   return retval;
+#else
+   return true;
+#endif
+}
+
+/*
+ *
+ * vsock_vmci_notify_waiting_read --
+ *
+ * Determines if the conditions have been met to notify a waiting reader.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+

[PATCH 2/6] VSOCK: vsock address implementaion.

2012-11-05 Thread George Zhang
VSOCK linux address code implementation.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/vsock_addr.c |  264 
 net/vmw_vsock/vsock_addr.h |   40 +++
 2 files changed, 304 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h

diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
new file mode 100644
index 000..c93a174
--- /dev/null
+++ b/net/vmw_vsock/vsock_addr.c
@@ -0,0 +1,264 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+/*
+ * vsockAddr.c --
+ *
+ * VSockets address implementation.
+ */
+
+/*
+ * These includes come before vsockCommon.h to ensure that VMware's ASSERT
+ * macro is used instead of Linux's irda.h definition.
+ */
+#include 
+#include 
+#include   /* for NULL */
+#include 
+
+#include "vsock_common.h"
+
+/*
+ *
+ * vsock_addr_init --
+ *
+ * Initialize the given address with the given context id and port. This will
+ * clear the address, set the correct family, and add the given values.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port)
+{
+   memset(addr, 0, sizeof *addr);
+
+   addr->svm_family = AF_VSOCK;
+   addr->svm_cid = cid;
+   addr->svm_port = port;
+
+   BUG_ON(vsock_addr_validate(addr) != 0);
+}
+
+/*
+ *
+ * vsock_addr_validate --
+ *
+ * Try to validate the given address.  The address must not be null and must
+ * have the correct address family.  Any reserved fields must be zero.
+ *
+ * Results: 0 on success, EFAULT if the address is null, EAFNOSUPPORT if the
+ * address is of the wrong family, and EINVAL if the reserved fields are not
+ * zero.
+ *
+ * Side effects: None.
+ */
+
+int vsock_addr_validate(const struct sockaddr_vm *addr)
+{
+   if (!addr)
+   return -EFAULT;
+
+   if (addr->svm_family != AF_VSOCK)
+   return -EAFNOSUPPORT;
+
+   if (addr->svm_zero[0] != 0)
+   return -EINVAL;
+
+   return 0;
+}
+
+/*
+ *
+ * vsock_addr_bound --
+ *
+ * Determines whether the provided address is bound.
+ *
+ * Results: TRUE if the address structure is bound, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_bound(const struct sockaddr_vm *addr)
+{
+   BUG_ON(!addr);
+
+   return addr->svm_port != VMADDR_PORT_ANY;
+}
+
+/*
+ *
+ * vsock_addr_unbind --
+ *
+ * Unbind the given addresss.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_addr_unbind(struct sockaddr_vm *addr)
+{
+   vsock_addr_init(addr, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+}
+
+/*
+ *
+ * vsock_addr_equals_addr --
+ *
+ * Determine if the given addresses are equal.
+ *
+ * Results: TRUE if the addresses are equal, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+   BUG_ON(vsock_addr_validate(other) != 0);
+
+   return addr->svm_cid == other->svm_cid &&
+   addr->svm_port == other->svm_port;
+}
+
+/*
+ *
+ * vsock_addr_equals_addr_any --
+ *
+ * Determine if the given addresses are equal. Will accept either an exact
+ * match or one where the rids match and that either the cids match or are set
+ * to VMADDR_CID_ANY.
+ *
+ * Results: TRUE if the addresses are equal, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+   BUG_ON(vsock_addr_validate(other) != 0);
+
+   return (addr->svm_cid == VMADDR_CID_ANY ||
+   other->svm_cid == VMADDR_CID_ANY ||
+   addr->svm_cid == other->svm_cid) &&
+  addr->svm_port == other->svm_port;
+}
+
+/*
+ *
+ * vsock_addr_equals_handle_port --
+ *
+ * Determines if the given address matches the given handle and port.
+ *
+ * Results: TRUE if the address matches the handle and port, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_handle_port(const struct sockaddr_vm *addr,
+  struct vmci_handle handle, u32 port)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+
+

[PATCH 0/6] VSOCK for Linux upstreaming

2012-11-05 Thread George Zhang
* * *
This series of VSOCK linux upstreaming patches include latest udpate from
VMware.

Summary of changes:
- Add include/linux/socket.h for AF_VSOCK.
- Cleanup some comments.
- Cleanup makefiles.



* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets (VSOCK)
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vsock kernel
module. The vmw_vmci kernel module has been presented in an early post.


* * *

VMCI Sockets allows virtual machines to communicate with host kernel
modules and the VMware hypervisors. VMCI Sockets kernel module has
dependency on VMCI kernel module. User level applications both in
a virtual machine and on the host can use vmw_vmci through VMCI
Sockets API which facilitates fast and efficient communication
between guest virtual machines and their host. A socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

The VMware VMCI Sockets are similar to other socket types, like
Berkeley UNIX socket interface. The VMCI sockets module supports
both connection-oriented stream sockets like TCP, and connectionless
datagram sockets like UDP. The VSOCK protocol family is defined as
"AF_VSOCK" and the socket operations split for SOCK_DGRAM and
SOCK_STREAM.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.



---

George Zhang (6):
  VSOCK: vsock protocol implementation.
  VSOCK: vsock address implementaion.
  VSOCK: notification implementation.
  VSOCK: statistics implementation.
  VSOCK: utility functions.
  VSOCK: header and config files.


 include/linux/socket.h  |4 
 net/Kconfig |1 
 net/Makefile|1 
 net/vmw_vsock/Kconfig   |   14 
 net/vmw_vsock/Makefile  |4 
 net/vmw_vsock/af_vsock.c| 4165 +++
 net/vmw_vsock/af_vsock.h|  179 ++
 net/vmw_vsock/notify.c  |  984 
 net/vmw_vsock/notify.h  |  130 +
 net/vmw_vsock/notify_qstate.c   |  627 +
 net/vmw_vsock/stats.c   |   37 
 net/vmw_vsock/stats.h   |  219 ++
 net/vmw_vsock/util.c|  626 +
 net/vmw_vsock/util.h|  312 +++
 net/vmw_vsock/vmci_sockets.h|  517 
 net/vmw_vsock/vmci_sockets_packet.h |  106 +
 net/vmw_vsock/vsock_addr.c  |  264 ++
 net/vmw_vsock/vsock_addr.h  |   40 
 net/vmw_vsock/vsock_common.h|  130 +
 net/vmw_vsock/vsock_packet.h|  131 +
 net/vmw_vsock/vsock_version.h   |   29 
 21 files changed, 8519 insertions(+), 1 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/af_vsock.c
 create mode 100644 net/vmw_vsock/af_vsock.h
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

-- 
Signature
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH 12/12] VMCI: Some header and config files.

2012-11-01 Thread George Zhang
VMCI head config patch Adds all the necessary files to enable building of the
VMCI module with the Linux Makefiles and Kconfig systems. Also adds the header
files used for building modules against the driver.


Signed-off-by: George Zhang 
---
 drivers/misc/Kconfig|1 
 drivers/misc/Makefile   |2 
 drivers/misc/vmw_vmci/Kconfig   |   16 +
 drivers/misc/vmw_vmci/Makefile  |4 
 drivers/misc/vmw_vmci/vmci_common_int.h |   34 +
 include/linux/vmw_vmci_api.h|   82 +++
 include/linux/vmw_vmci_defs.h   |  973 +++
 7 files changed, 1112 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/Kconfig
 create mode 100644 drivers/misc/vmw_vmci/Makefile
 create mode 100644 drivers/misc/vmw_vmci/vmci_common_int.h
 create mode 100644 include/linux/vmw_vmci_api.h
 create mode 100644 include/linux/vmw_vmci_defs.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2661f6e..fe38c7a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -517,4 +517,5 @@ source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
+source "drivers/misc/vmw_vmci/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 456972f..21ed953 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -51,3 +51,5 @@ obj-y += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)+= mei/
+obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
+obj-$(CONFIG_VMWARE_VMCI)  += vmw_vmci/
diff --git a/drivers/misc/vmw_vmci/Kconfig b/drivers/misc/vmw_vmci/Kconfig
new file mode 100644
index 000..55015e7
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Kconfig
@@ -0,0 +1,16 @@
+#
+# VMware VMCI device
+#
+
+config VMWARE_VMCI
+   tristate "VMware VMCI Driver"
+   depends on X86
+   help
+ This is VMware's Virtual Machine Communication Interface.  It enables
+ high-speed communication between host and guest in a virtual
+ environment via the VMCI virtual device.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vmw_vmci.
diff --git a/drivers/misc/vmw_vmci/Makefile b/drivers/misc/vmw_vmci/Makefile
new file mode 100644
index 000..4da9893
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci.o
+vmw_vmci-y += vmci_context.o vmci_datagram.o vmci_doorbell.o \
+   vmci_driver.o vmci_event.o vmci_guest.o vmci_handle_array.o \
+   vmci_host.o vmci_queue_pair.o vmci_resource.o vmci_route.o
diff --git a/drivers/misc/vmw_vmci/vmci_common_int.h 
b/drivers/misc/vmw_vmci/vmci_common_int.h
new file mode 100644
index 000..77667ec
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_common_int.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef _VMCI_COMMONINT_H_
+#define _VMCI_COMMONINT_H_
+
+#include 
+
+#define ASSERT(cond) BUG_ON(!(cond))
+
+#define PCI_VENDOR_ID_VMWARE   0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMCI  0x0740
+#define VMCI_DRIVER_VERSION_STRING "1.0.0.0-k"
+#define MODULE_NAME "vmw_vmci"
+
+/* Print magic... whee! */
+#ifdef pr_fmt
+#undef pr_fmt
+#define pr_fmt(fmt) MODULE_NAME ": " fmt
+#endif
+
+#endif /* _VMCI_COMMONINT_H_ */
diff --git a/include/linux/vmw_vmci_api.h b/include/linux/vmw_vmci_api.h
new file mode 100644
index 000..193129d
--- /dev/null
+++ b/include/linux/vmw_vmci_api.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef __VMW_VMCI_API_H__
+#define __VMW_VMCI_API_H__
+
+#include 
+#include 
+
+#undef  VMCI_KERNEL

[PATCH 11/12] VMCI: host side driver implementation.

2012-11-01 Thread George Zhang
VMCI host side driver code implementation.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_host.c | 1036 +
 1 files changed, 1036 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_host.c

diff --git a/drivers/misc/vmw_vmci/vmci_host.c 
b/drivers/misc/vmw_vmci/vmci_host.c
new file mode 100644
index 000..82a8ef9
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_host.c
@@ -0,0 +1,1036 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_handle_array.h"
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+enum {
+   VMCI_NOTIFY_RESOURCE_QUEUE_PAIR = 0,
+   VMCI_NOTIFY_RESOURCE_DOOR_BELL = 1,
+};
+
+enum {
+   VMCI_NOTIFY_RESOURCE_ACTION_NOTIFY = 0,
+   VMCI_NOTIFY_RESOURCE_ACTION_CREATE = 1,
+   VMCI_NOTIFY_RESOURCE_ACTION_DESTROY = 2,
+};
+
+/*
+ * VMCI driver initialization. This block can also be used to
+ * pass initial group membership etc.
+ */
+struct vmci_init_blk {
+   u32 cid;
+   u32 flags;
+};
+
+/* VMCIqueue_pairAllocInfo_VMToVM */
+struct vmci_qp_alloc_info_vmvm {
+   struct vmci_handle handle;
+   u32 peer;
+   u32 flags;
+   u64 produce_size;
+   u64 consume_size;
+   u64 produce_page_file;/* User VA. */
+   u64 consume_page_file;/* User VA. */
+   u64 produce_page_file_size;  /* Size of the file name array. */
+   u64 consume_page_file_size;  /* Size of the file name array. */
+   s32 result;
+   u32 _pad;
+};
+
+/* VMCISetNotifyInfo: Used to pass notify flag's address to the host driver. */
+struct vmci_set_notify_info {
+   u64 notify_uva;
+   s32 result;
+   u32 _pad;
+};
+
+/*
+ * Per-instance host state
+ */
+struct vmci_host_dev {
+   struct vmci_ctx *context;
+   int user_version;
+   enum vmci_obj_type ct_type;
+   struct mutex lock;  /* Mutex lock for vmci context access */
+};
+
+static struct vmci_ctx *host_context;
+static bool vmci_host_device_initialized;
+static atomic_t vmci_host_active_users = ATOMIC_INIT(0);
+
+/*
+ * Determines whether the VMCI host personality is
+ * available. Since the core functionality of the host driver is
+ * always present, all guests could possibly use the host
+ * personality. However, to minimize the deviation from the
+ * pre-unified driver state of affairs, we only consider the host
+ * device active if there is no active guest device or if there
+ * are VMX'en with active VMCI contexts using the host device.
+ */
+bool vmci_host_code_active(void)
+{
+   return vmci_host_device_initialized &&
+   (!vmci_guest_code_active() ||
+atomic_read(&vmci_host_active_users) > 0);
+}
+
+/*
+ * Called on open of /dev/vmci.
+ */
+static int vmci_host_open(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev;
+
+   vmci_host_dev = kzalloc(sizeof(struct vmci_host_dev), GFP_KERNEL);
+   if (vmci_host_dev == NULL)
+   return -ENOMEM;
+
+   vmci_host_dev->ct_type = VMCIOBJ_NOT_SET;
+   mutex_init(&vmci_host_dev->lock);
+   filp->private_data = vmci_host_dev;
+
+   return 0;
+}
+
+/*
+ * Called on close of /dev/vmci, most often when the process
+ * exits.
+ */
+static int vmci_host_close(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev = filp->private_data;
+
+   if (vmci_host_dev->ct_type == VMCIOBJ_CONTEXT) {
+   vmci_ctx_destroy(vmci_host_dev->context);
+   vmci_host_dev->context = NULL;
+
+   /*
+* The number of active contexts is used to track whether any
+* VMX'en are using the host personality. It is incremented when
+* a context is created through the IOCTL_VMCI_INIT_CONTEXT
+* ioctl.
+*/
+   atomic_dec(&vmci_host_active_users);
+   }
+ 

[PATCH 10/12] VMCI: guest side driver implementation.

2012-11-01 Thread George Zhang
VMCI guest side driver code implementation.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_guest.c |  762 
 1 files changed, 762 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_guest.c

diff --git a/drivers/misc/vmw_vmci/vmci_guest.c 
b/drivers/misc/vmw_vmci/vmci_guest.c
new file mode 100644
index 000..eedbe4d
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -0,0 +1,762 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+static bool vmci_disable_msi;
+module_param_named(disable_msi, vmci_disable_msi, bool, 0);
+MODULE_PARM_DESC(disable_msi, "Disable MSI use in driver - (default=0)");
+
+static bool vmci_disable_msix;
+module_param_named(disable_msix, vmci_disable_msix, bool, 0);
+MODULE_PARM_DESC(disable_msix, "Disable MSI-X use in driver - (default=0)");
+
+static u32 ctx_update_sub_id = VMCI_INVALID_ID;
+static u32 vm_context_id = VMCI_INVALID_ID;
+
+struct vmci_guest_device {
+   struct device *dev; /* PCI device we are attached to */
+   void __iomem *iobase;
+
+   unsigned int irq;
+   unsigned int intr_type;
+   bool exclusive_vectors;
+   struct msix_entry msix_entries[VMCI_MAX_INTRS];
+
+   struct tasklet_struct datagram_tasklet;
+   struct tasklet_struct bm_tasklet;
+
+   void *data_buffer;
+   void *notification_bitmap;
+};
+
+/* vmci_dev singleton device and supporting data*/
+static struct vmci_guest_device *vmci_dev_g;
+static DEFINE_SPINLOCK(vmci_dev_spinlock);
+
+static atomic_t vmci_num_guest_devices = ATOMIC_INIT(0);
+
+bool vmci_guest_code_active(void)
+{
+   return atomic_read(&vmci_num_guest_devices) != 0;
+}
+
+u32 vmci_get_vm_context_id(void)
+{
+   if (vm_context_id == VMCI_INVALID_ID) {
+   u32 result;
+   struct vmci_datagram get_cid_msg;
+   get_cid_msg.dst =
+   vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
+VMCI_GET_CONTEXT_ID);
+   get_cid_msg.src = VMCI_ANON_SRC_HANDLE;
+   get_cid_msg.payload_size = 0;
+   result = vmci_send_datagram(&get_cid_msg);
+   if (result >= 0)
+   vm_context_id = result;
+   }
+   return vm_context_id;
+}
+
+/*
+ * VM to hypervisor call mechanism. We use the standard VMware naming
+ * convention since shared code is calling this function as well.
+ */
+int vmci_send_datagram(struct vmci_datagram *dg)
+{
+   unsigned long flags;
+   int result;
+
+   /* Check args. */
+   if (dg == NULL)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* Need to acquire spinlock on the device because the datagram
+* data may be spread over multiple pages and the monitor may
+* interleave device user rpc calls from multiple
+* VCPUs. Acquiring the spinlock precludes that
+* possibility. Disabling interrupts to avoid incoming
+* datagrams during a "rep out" and possibly landing up in
+* this function.
+*/
+   spin_lock_irqsave(&vmci_dev_spinlock, flags);
+
+   if (vmci_dev_g) {
+   iowrite8_rep(vmci_dev_g->iobase + VMCI_DATA_OUT_ADDR,
+dg, VMCI_DG_SIZE(dg));
+   result = ioread32(vmci_dev_g->iobase + VMCI_RESULT_LOW_ADDR);
+   } else {
+   result = VMCI_ERROR_UNAVAILABLE;
+   }
+
+   spin_unlock_irqrestore(&vmci_dev_spinlock, flags);
+
+   return result;
+}
+EXPORT_SYMBOL_GPL(vmci_send_datagram);
+
+/*
+ * Gets called with the new context id if updated or resumed.
+ * Context id.
+ */
+static void vmci_guest_cid_update(u32 sub_id,
+ const struct vmci_event_data *event_data,
+ void *client_data)
+{
+   const struct vmci_event_payld_ctx *ev_payload =
+   vmci_event_data_const_payload(event_data);
+
+   if (sub_id != ctx_update_sub_id) {

[PATCH 09/12] VMCI: routing implementation.

2012-11-01 Thread George Zhang
VMCI routing code is responsible for routing between various hosts/guests as
well as routing in nested scenarios.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_route.c |  233 
 drivers/misc/vmw_vmci/vmci_route.h |   30 +
 2 files changed, 263 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.h

diff --git a/drivers/misc/vmw_vmci/vmci_route.c 
b/drivers/misc/vmw_vmci/vmci_route.c
new file mode 100644
index 000..7917d5e
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_route.c
@@ -0,0 +1,233 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+/*
+ * Make a routing decision for the given source and destination handles.
+ * This will try to determine the route using the handles and the available
+ * devices.  Will set the source context if it is invalid.
+ */
+int vmci_route(struct vmci_handle *src,
+  const struct vmci_handle *dst,
+  bool from_guest,
+  enum vmci_route *route)
+{
+   bool has_host_device = vmci_host_code_active();
+   bool has_guest_device = vmci_guest_code_active();
+
+   *route = VMCI_ROUTE_NONE;
+
+   /*
+* "from_guest" is only ever set to true by
+* IOCTL_VMCI_DATAGRAM_SEND (or by the vmkernel equivalent),
+* which comes from the VMX, so we know it is coming from a
+* guest.
+*
+* To avoid inconsistencies, test these once.  We will test
+* them again when we do the actual send to ensure that we do
+* not touch a non-existent device.
+*/
+
+   /* Must have a valid destination context. */
+   if (VMCI_INVALID_ID == dst->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /* Anywhere to hypervisor. */
+   if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
+
+   /*
+* If this message already came from a guest then we
+* cannot send it to the hypervisor.  It must come
+* from a local client.
+*/
+   if (from_guest)
+   return VMCI_ERROR_DST_UNREACHABLE;
+
+   /*
+* We must be acting as a guest in order to send to
+* the hypervisor.
+*/
+   if (!has_guest_device)
+   return VMCI_ERROR_DEVICE_NOT_FOUND;
+
+   /* And we cannot send if the source is the host context. */
+   if (VMCI_HOST_CONTEXT_ID == src->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* If the client passed the ANON source handle then
+* respect it (both context and resource are invalid).
+* However, if they passed only an invalid context,
+* then they probably mean ANY, in which case we
+* should set the real context here before passing it
+* down.
+*/
+   if (VMCI_INVALID_ID == src->context &&
+   VMCI_INVALID_ID != src->resource)
+   src->context = vmci_get_context_id();
+
+   /* Send from local client down to the hypervisor. */
+   *route = VMCI_ROUTE_AS_GUEST;
+   return VMCI_SUCCESS;
+   }
+
+   /* Anywhere to local client on host. */
+   if (VMCI_HOST_CONTEXT_ID == dst->context) {
+   /*
+* If it is not from a guest but we are acting as a
+* guest, then we need to send it down to the host.
+* Note that if we are also acting as a host then this
+* will prevent us from sending from local client to
+* local client, but we accept that restriction as a
+* way to remove any ambiguity from the host context.
+*/
+   if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* If the hypervisor is the source, this is
+* host local communication. The hypervisor
+* may send vmci event datagrams to the host
+* its

[PATCH 08/12] VMCI: resource object implementation.

2012-11-01 Thread George Zhang
VMCI resource tracks all used resources within the vmci code.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_resource.c |  232 +
 drivers/misc/vmw_vmci/vmci_resource.h |   59 
 2 files changed, 291 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.h

diff --git a/drivers/misc/vmw_vmci/vmci_resource.c 
b/drivers/misc/vmw_vmci/vmci_resource.c
new file mode 100644
index 000..b241dde
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_resource.c
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+
+
+#define VMCI_RESOURCE_HASH_BITS 7
+#define VMCI_RESOURCE_HASH_BUCKETS  (1 << VMCI_RESOURCE_HASH_BITS)
+
+struct vmci_hash_table {
+   spinlock_t lock;
+   struct hlist_head entries[VMCI_RESOURCE_HASH_BUCKETS];
+};
+
+static struct vmci_hash_table vmci_resource_table = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_resource_table.lock),
+};
+
+static unsigned int vmci_resource_hash(struct vmci_handle handle)
+{
+   return hash_32(VMCI_HANDLE_TO_RESOURCE_ID(handle),
+  VMCI_RESOURCE_HASH_BITS);
+}
+
+/*
+ * Gets a resource (if one exists) matching given handle from the hash table.
+ */
+static struct vmci_resource *vmci_resource_lookup(struct vmci_handle handle)
+{
+   struct vmci_resource *r, *resource = NULL;
+   struct hlist_node *node;
+   unsigned int idx = vmci_resource_hash(handle);
+
+   rcu_read_lock();
+   hlist_for_each_entry_rcu(r, node,
+&vmci_resource_table.entries[idx], node) {
+   u32 rid = VMCI_HANDLE_TO_RESOURCE_ID(r->handle);
+   u32 cid = VMCI_HANDLE_TO_CONTEXT_ID(r->handle);
+
+   if (rid == VMCI_HANDLE_TO_RESOURCE_ID(handle) &&
+   (cid == VMCI_HANDLE_TO_CONTEXT_ID(handle) ||
+cid == VMCI_INVALID_ID)) {
+   resource = r;
+   break;
+   }
+   }
+   rcu_read_unlock();
+
+   return resource;
+}
+
+/*
+ * Find an unused resource ID and return it. The first
+ * VMCI_RESERVED_RESOURCE_ID_MAX are reserved so we start from
+ * its value + 1.
+ * Returns VMCI resource id on success, VMCI_INVALID_ID on failure.
+ */
+static u32 vmci_resource_find_id(u32 context_id)
+{
+   static u32 resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   u32 old_rid = resource_id;
+   u32 current_rid;
+
+   /*
+* Generate a unique resource ID.  Keep on trying until we wrap around
+* in the RID space.
+*/
+   BUG_ON(old_rid <= VMCI_RESERVED_RESOURCE_ID_MAX);
+
+   do {
+   struct vmci_handle handle;
+
+   current_rid = resource_id;
+   resource_id++;
+   if (unlikely(resource_id == VMCI_INVALID_ID)) {
+   /* Skip the reserved rids. */
+   resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   }
+
+   handle = vmci_make_handle(context_id, current_rid);
+   if (!vmci_resource_lookup(handle))
+   return current_rid;
+   } while (resource_id != old_rid);
+
+   return VMCI_INVALID_ID;
+}
+
+
+int vmci_resource_add(struct vmci_resource *resource,
+ enum vmci_resource_type resource_type,
+ struct vmci_handle handle)
+
+{
+   unsigned int idx;
+   int result;
+
+   spin_lock(&vmci_resource_table.lock);
+
+   if (handle.resource == VMCI_INVALID_ID) {
+   handle.resource = vmci_resource_find_id(handle.context);
+   if (handle.resource == VMCI_INVALID_ID) {
+   result = VMCI_ERROR_NO_HANDLE;
+   goto out;
+   }
+   } else if (vmci_resource_lookup(handle)) {
+   result = VMCI_ERROR_ALREADY_EXISTS;
+   goto out;
+   }
+
+   resource->handle = handle;
+   resource->type = resource_type;
+   INIT_HLIST_NODE(&resource->node);
+   kref_init(&resource->kref);
+   init_completion(&resource->done);
+
+   idx = vmci_resource_hash(resource->handle);
+ 

[PATCH 06/12] VMCI: handle array implementation.

2012-11-01 Thread George Zhang
VMCI handle code adds support for dynamic arrays that will grow if they need to.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_handle_array.c |  142 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   52 +++
 2 files changed, 194 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.h

diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c 
b/drivers/misc/vmw_vmci/vmci_handle_array.c
new file mode 100644
index 000..9122373
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_handle_array.c
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include 
+#include "vmci_handle_array.h"
+
+static size_t handle_arr_calc_size(size_t capacity)
+{
+   return sizeof(struct vmci_handle_arr) +
+   capacity * sizeof(struct vmci_handle);
+}
+
+struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity)
+{
+   struct vmci_handle_arr *array;
+
+   if (capacity == 0)
+   capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
+
+   array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC);
+   if (!array)
+   return NULL;
+
+   array->capacity = capacity;
+   array->size = 0;
+
+   return array;
+}
+
+void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
+{
+   kfree(array);
+}
+
+void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
+ struct vmci_handle handle)
+{
+   struct vmci_handle_arr *array = *array_ptr;
+
+   if (unlikely(array->size >= array->capacity)) {
+   /* reallocate. */
+   struct vmci_handle_arr *new_array;
+   size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT;
+   size_t new_size = handle_arr_calc_size(new_capacity);
+
+   new_array = krealloc(array, new_size, GFP_ATOMIC);
+   if (!new_array)
+   return;
+
+   new_array->capacity = new_capacity;
+   *array_ptr = array = new_array;
+   }
+
+   array->entries[array->size] = handle;
+   array->size++;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
+ */
+struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
+   struct vmci_handle entry_handle)
+{
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+   size_t i;
+
+   for (i = 0; i < array->size; i++) {
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle)) {
+   handle = array->entries[i];
+   array->size--;
+   array->entries[i] = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   break;
+   }
+   }
+
+   return handle;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
+ */
+struct vmci_handle vmci_handle_arr_remove_tail(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;
+}
+
+/*
+ * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
+ */
+struct vmci_handle
+vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index)
+{
+   if (unlikely(index >= array->size))
+   return VMCI_INVALID_HANDLE;
+
+   return array->entries[index];
+}
+
+bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
+  struct vmci_handle entry_handle)
+{
+   size_t i;
+
+   for (i = 0; i < array->size; i++)
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle))
+   return true;
+
+   return false;
+}
+
+/*
+ * NULL if the array is empty. Otherwise, a pointer to the array
+ * of VMCI handles in the handle array.
+ */
+struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array)
+{
+   if (array->size)
+   return array->entries;
+
+   return NULL;
+}
diff --git a/drivers/m

[PATCH 05/12] VMCI: event handling implementation.

2012-11-01 Thread George Zhang
VMCI event code that manages event handlers and handles callbacks when specific
events fire.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_event.c |  229 
 drivers/misc/vmw_vmci/vmci_event.h |   25 
 2 files changed, 254 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.h

diff --git a/drivers/misc/vmw_vmci/vmci_event.c 
b/drivers/misc/vmw_vmci/vmci_event.c
new file mode 100644
index 000..e956c18
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_event.c
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define EVENT_MAGIC 0xEABE
+#define VMCI_EVENT_MAX_ATTEMPTS 10
+
+struct vmci_subscription {
+   u32 id;
+   u32 event;
+   vmci_event_cb callback;
+   void *callback_data;
+   struct list_head node;  /* on one of subscriber lists */
+};
+
+static struct list_head subscriber_array[VMCI_EVENT_MAX];
+static DEFINE_MUTEX(subscriber_mutex);
+
+int __init vmci_event_init(void)
+{
+   int i;
+
+   for (i = 0; i < VMCI_EVENT_MAX; i++)
+   INIT_LIST_HEAD(&subscriber_array[i]);
+
+   return VMCI_SUCCESS;
+}
+
+void vmci_event_exit(void)
+{
+   int e;
+
+   /* We free all memory at exit. */
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur, *p2;
+   list_for_each_entry_safe(cur, p2, &subscriber_array[e], node) {
+
+   /*
+* We should never get here because all events
+* should have been unregistered before we try
+* to unload the driver module.
+*/
+   pr_warn("Unexpected free events occurring.\n");
+   list_del(&cur->node);
+   kfree(cur);
+   }
+   }
+}
+
+/*
+ * Find entry. Assumes subscriber_mutex is held.
+ */
+static struct vmci_subscription *event_find(u32 sub_id)
+{
+   int e;
+
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur;
+   list_for_each_entry(cur, &subscriber_array[e], node) {
+   if (cur->id == sub_id)
+   return cur;
+   }
+   }
+   return NULL;
+}
+
+/*
+ * Actually delivers the events to the subscribers.
+ * The callback function for each subscriber is invoked.
+ */
+static void event_deliver(struct vmci_event_msg *event_msg)
+{
+   struct vmci_subscription *cur;
+   struct list_head *subscriber_list;
+
+   rcu_read_lock();
+   subscriber_list = &subscriber_array[event_msg->event_data.event];
+   list_for_each_entry_rcu(cur, subscriber_list, node) {
+   BUG_ON(cur->event != event_msg->event_data.event);
+
+   cur->callback(cur->id, &event_msg->event_data,
+ cur->callback_data);
+   }
+   rcu_read_unlock();
+}
+
+/*
+ * Dispatcher for the VMCI_EVENT_RECEIVE datagrams. Calls all
+ * subscribers for given event.
+ */
+int vmci_event_dispatch(struct vmci_datagram *msg)
+{
+   struct vmci_event_msg *event_msg = (struct vmci_event_msg *)msg;
+
+   BUG_ON(msg->src.context != VMCI_HYPERVISOR_CONTEXT_ID ||
+  msg->dst.resource != VMCI_EVENT_HANDLER);
+
+   if (msg->payload_size < sizeof(u32) ||
+   msg->payload_size > sizeof(struct vmci_event_data_max))
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (!VMCI_EVENT_VALID(event_msg->event_data.event))
+   return VMCI_ERROR_EVENT_UNKNOWN;
+
+   event_deliver(event_msg);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * vmci_event_subscribe() - Subscribe to a given event.
+ * @event:  The event to subscribe to.
+ * @callback:   The callback to invoke upon the event.
+ * @callback_data:  Data to pass to the callback.
+ * @subscription_id:ID used to track subscription.  Used with
+ *  vmci_event_unsubscribe()
+ *
+ * Subscribes to the provided event. The callback specified will be
+ * fired from RCU critical section and therefore must not sleep.
+ */
+int vmci_event_sub

[PATCH 04/12] VMCI: device driver implementaton.

2012-11-01 Thread George Zhang
VMCI driver code implementes both the host and guest personalities of
the VMCI driver.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_driver.c |  116 +++
 drivers/misc/vmw_vmci/vmci_driver.h |   50 +++
 2 files changed, 166 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.h

diff --git a/drivers/misc/vmw_vmci/vmci_driver.c 
b/drivers/misc/vmw_vmci/vmci_driver.c
new file mode 100644
index 000..8c5db38
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.c
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+static bool vmci_disable_host;
+module_param_named(disable_host, vmci_disable_host, bool, 0);
+MODULE_PARM_DESC(disable_host,
+"Disable driver host personality (default=enabled)");
+
+static bool vmci_disable_guest;
+module_param_named(disable_guest, vmci_disable_guest, bool, 0);
+MODULE_PARM_DESC(disable_guest,
+"Disable driver guest personality (default=enabled)");
+
+static bool vmci_guest_personality_initialized;
+static bool vmci_host_personality_initialized;
+
+/*
+ * vmci_get_context_id() - Gets the current context ID.
+ *
+ * Returns the current context ID.  Note that since this is accessed only
+ * from code running in the host, this always returns the host context ID.
+ */
+u32 vmci_get_context_id(void)
+{
+   if (vmci_guest_code_active())
+   return vmci_get_vm_context_id();
+   else if (vmci_host_code_active())
+   return VMCI_HOST_CONTEXT_ID;
+
+   return VMCI_INVALID_ID;
+}
+EXPORT_SYMBOL_GPL(vmci_get_context_id);
+
+static int __init vmci_drv_init(void)
+{
+   int vmci_err;
+   int error;
+
+   vmci_err = vmci_event_init();
+   if (vmci_err < VMCI_SUCCESS) {
+   pr_err("Failed to initialize VMCIEvent (result=%d).\n", 
vmci_err);
+   return -EINVAL;
+   }
+
+   if (!vmci_disable_guest) {
+   error = vmci_guest_init();
+   if (error) {
+   pr_warn("Failed to initialize guest personality 
(err=%d).\n",
+   error);
+   } else {
+   vmci_guest_personality_initialized = true;
+   pr_info("Guest personality initialized and is %s\n",
+   vmci_guest_code_active() ?
+   "active" : "inactive");
+   }
+   }
+
+   if (!vmci_disable_host) {
+   error = vmci_host_init();
+   if (error) {
+   pr_warn("Unable to initialize host personality 
(err=%d).\n",
+   error);
+   } else {
+   vmci_host_personality_initialized = true;
+   pr_info("Initialized host personality\n");
+   }
+   }
+
+   if (!vmci_guest_personality_initialized &&
+   !vmci_host_personality_initialized) {
+   vmci_event_exit();
+   return -ENODEV;
+   }
+
+   return 0;
+}
+module_init(vmci_drv_init);
+
+static void __exit vmci_drv_exit(void)
+{
+   if (vmci_guest_personality_initialized)
+   vmci_guest_exit();
+
+   if (vmci_host_personality_initialized)
+   vmci_host_exit();
+
+   vmci_event_exit();
+}
+module_exit(vmci_drv_exit);
+
+MODULE_AUTHOR("VMware, Inc.");
+MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
+MODULE_VERSION(VMCI_DRIVER_VERSION_STRING);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/vmw_vmci/vmci_driver.h 
b/drivers/misc/vmw_vmci/vmci_driver.h
new file mode 100644
index 000..f69156a
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.h
@@ -0,0 +1,50 @@
+/*
+ * 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 u

[PATCH 03/12] VMCI: doorbell implementation.

2012-11-01 Thread George Zhang
VMCI doorbell code allows for notifcations between host and guest.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_doorbell.c |  645 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   53 +++
 2 files changed, 698 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.h

diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.c 
b/drivers/misc/vmw_vmci/vmci_doorbell.c
new file mode 100644
index 000..a54ec1e
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -0,0 +1,645 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+
+#define VMCI_DOORBELL_INDEX_BITS   6
+#define VMCI_DOORBELL_INDEX_TABLE_SIZE (1 << VMCI_DOORBELL_INDEX_BITS)
+#define VMCI_DOORBELL_HASH(_idx)   hash_32(_idx, VMCI_DOORBELL_INDEX_BITS)
+
+/*
+ * DoorbellEntry describes the a doorbell notification handle allocated by the
+ * host.
+ */
+struct dbell_entry {
+   struct vmci_resource resource;
+   struct hlist_node node;
+   struct work_struct work;
+   vmci_callback notify_cb;
+   void *client_data;
+   u32 idx;
+   u32 priv_flags;
+   bool run_delayed;
+   atomic_t active;/* Only used by guest personality */
+};
+
+/* The VMCI index table keeps track of currently registered doorbells. */
+struct dbell_index_table {
+   spinlock_t lock;/* Index table lock */
+   struct hlist_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
+};
+
+static struct dbell_index_table vmci_doorbell_it = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_doorbell_it.lock),
+};
+
+/*
+ * The max_notify_idx is one larger than the currently known bitmap index in
+ * use, and is used to determine how much of the bitmap needs to be scanned.
+ */
+static u32 max_notify_idx;
+
+/*
+ * The notify_idx_count is used for determining whether there are free entries
+ * within the bitmap (if notify_idx_count + 1 < max_notify_idx).
+ */
+static u32 notify_idx_count;
+
+/*
+ * The last_notify_idx_reserved is used to track the last index handed out - in
+ * the case where multiple handles share a notification index, we hand out
+ * indexes round robin based on last_notify_idx_reserved.
+ */
+static u32 last_notify_idx_reserved;
+
+/* This is a one entry cache used to by the index allocation. */
+static u32 last_notify_idx_released = PAGE_SIZE;
+
+
+/*
+ * Utility function that retrieves the privilege flags associated
+ * with a given doorbell handle. For guest endpoints, the
+ * privileges are determined by the context ID, but for host
+ * endpoints privileges are associated with the complete
+ * handle. Hypervisor endpoints are not yet supported.
+ */
+int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags)
+{
+   if (priv_flags == NULL || handle.context == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (handle.context == VMCI_HOST_CONTEXT_ID) {
+   struct dbell_entry *entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DOORBELL);
+   if (!resource)
+   return VMCI_ERROR_NOT_FOUND;
+
+   entry = container_of(resource, struct dbell_entry, resource);
+   *priv_flags = entry->priv_flags;
+   vmci_resource_put(resource);
+   } else if (handle.context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* Hypervisor endpoints for notifications are not
+* supported (yet).
+*/
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   *priv_flags = vmci_context_get_priv_flags(handle.context);
+   }
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Find doorbell entry by bitmap index.
+ */
+static struct dbell_entry *dbell_index_table_find(u32 idx)
+{
+   u32 bucket = VMCI_DOORBELL_HASH(idx);
+   struct dbell_entry *dbell;
+   struct hlist_node *node;
+
+   hlist_for_each_entry(dbell, node, &vmci_doorbell

[PATCH 02/12] VMCI: datagram implementation.

2012-11-01 Thread George Zhang
VMCI datagram Implements datagrams to allow data to be sent between host
and guest.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_datagram.c |  506 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   52 +++
 2 files changed, 558 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.h

diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c 
b/drivers/misc/vmw_vmci/vmci_datagram.c
new file mode 100644
index 000..d755e31
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -0,0 +1,506 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+#include "vmci_route.h"
+
+/*
+ * struct datagram_entry describes the datagram entity. It is used for datagram
+ * entities created only on the host.
+ */
+struct datagram_entry {
+   struct vmci_resource resource;
+   u32 flags;
+   bool run_delayed;
+   vmci_datagram_recv_cb recv_cb;
+   void *client_data;
+   u32 priv_flags;
+};
+
+struct delayed_datagram_info {
+   struct datagram_entry *entry;
+   struct vmci_datagram msg;
+   struct work_struct work;
+   bool in_dg_host_queue;
+};
+
+/* Number of in-flight host->host datagrams */
+static atomic_t delayed_dg_host_queue_size = ATOMIC_INIT(0);
+
+/*
+ * Create a datagram entry given a handle pointer.
+ */
+static int dg_create_handle(u32 resource_id,
+   u32 flags,
+   u32 priv_flags,
+   vmci_datagram_recv_cb recv_cb,
+   void *client_data, struct vmci_handle *out_handle)
+{
+   int result;
+   u32 context_id;
+   struct vmci_handle handle;
+   struct datagram_entry *entry;
+
+   BUG_ON(!recv_cb);
+   BUG_ON(!out_handle);
+   BUG_ON(priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS);
+
+   if ((flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if ((flags & VMCI_FLAG_ANYCID_DG_HND) != 0) {
+   context_id = VMCI_INVALID_ID;
+   } else {
+   context_id = vmci_get_context_id();
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_RESOURCES;
+   }
+
+   handle = vmci_make_handle(context_id, resource_id);
+
+   entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+   if (!entry) {
+   pr_warn("Failed allocating memory for datagram entry.\n");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   entry->run_delayed = (flags & VMCI_FLAG_DG_DELAYED_CB) ? true : false;
+   entry->flags = flags;
+   entry->recv_cb = recv_cb;
+   entry->client_data = client_data;
+   entry->priv_flags = priv_flags;
+
+   /* Make datagram resource live. */
+   result = vmci_resource_add(&entry->resource,
+  VMCI_RESOURCE_TYPE_DATAGRAM,
+  handle);
+   if (result != VMCI_SUCCESS) {
+   pr_warn("Failed to add new resource (handle=0x%x:0x%x), error: 
%d\n",
+   handle.context, handle.resource, result);
+   kfree(entry);
+   return result;
+   }
+
+   *out_handle = vmci_resource_handle(&entry->resource);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Internal utility function with the same purpose as
+ * vmci_datagram_get_priv_flags that also takes a context_id.
+ */
+static int vmci_datagram_get_priv_flags(u32 context_id,
+   struct vmci_handle handle,
+   u32 *priv_flags)
+{
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (context_id == VMCI_HOST_CONTEXT_ID) {
+   struct datagram_entry *src_entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DATAGRAM);
+   if (!resource)
+   return VMCI_ERROR_I

[PATCH 01/12] VMCI: context implementation.

2012-11-01 Thread George Zhang
VMCI Context code maintains state for vmci and allows the driver to communicate
with multiple VMs.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_context.c | 1247 ++
 drivers/misc/vmw_vmci/vmci_context.h |  183 +
 2 files changed, 1430 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.h

diff --git a/drivers/misc/vmw_vmci/vmci_context.c 
b/drivers/misc/vmw_vmci/vmci_context.c
new file mode 100644
index 000..0df23e0
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_context.c
@@ -0,0 +1,1247 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+/*
+ * List of current VMCI contexts.  Contexts can be added by
+ * vmci_ctx_create() and removed via vmci_ctx_destroy().
+ * These, along with context lookup, are protected by the
+ * list structure's lock.
+ */
+static struct {
+   struct list_head head;
+   spinlock_t lock; /* Spinlock for context list operations */
+} ctx_list = {
+   .head = LIST_HEAD_INIT(ctx_list.head),
+   .lock = __SPIN_LOCK_UNLOCKED(ctx_list.lock),
+};
+
+/* Used by contexts that did not set up notify flag pointers */
+static bool ctx_dummy_notify;
+
+static void ctx_signal_notify(struct vmci_ctx *context)
+{
+   *context->notify = true;
+}
+
+static void ctx_clear_notify(struct vmci_ctx *context)
+{
+   *context->notify = false;
+}
+
+/*
+ * If nothing requires the attention of the guest, clears both
+ * notify flag and call.
+ */
+static void ctx_clear_notify_call(struct vmci_ctx *context)
+{
+   if (context->pending_datagrams == 0 &&
+   vmci_handle_arr_get_size(context->pending_doorbell_array) == 0)
+   ctx_clear_notify(context);
+}
+
+/*
+ * Sets the context's notify flag iff datagrams are pending for this
+ * context.  Called from vmci_setup_notify().
+ */
+void vmci_ctx_check_signal_notify(struct vmci_ctx *context)
+{
+   spin_lock(&context->lock);
+   if (context->pending_datagrams)
+   ctx_signal_notify(context);
+   spin_unlock(&context->lock);
+}
+
+/*
+ * Allocates and initializes a VMCI context.
+ */
+struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags,
+uintptr_t event_hnd,
+int user_version,
+const struct cred *cred)
+{
+   struct vmci_ctx *context;
+   int error;
+
+   if (cid == VMCI_INVALID_ID) {
+   pr_devel("Invalid context ID for VMCI context.\n");
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   if (priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
+   pr_devel("Invalid flag (flags=0x%x) for VMCI context.\n",
+priv_flags);
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   if (user_version == 0) {
+   pr_devel("Invalid suer_version %d\n", user_version);
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   context = kzalloc(sizeof(*context), GFP_KERNEL);
+   if (!context) {
+   pr_warn("Failed to allocate memory for VMCI context.\n");
+   error = -EINVAL;
+   goto err_out;
+   }
+
+   kref_init(&context->kref);
+   spin_lock_init(&context->lock);
+   INIT_LIST_HEAD(&context->list_item);
+   INIT_LIST_HEAD(&context->datagram_queue);
+   INIT_LIST_HEAD(&context->notifier_list);
+
+   /* Initialize host-specific VMCI context. */
+   init_waitqueue_head(&context->host_context.wait_queue);
+
+   context->queue_pair_array = vmci_handle_arr_create(0);
+   if (!context->queue_pair_array) {
+   error = -ENOMEM;
+   goto err_free_ctx;
+   }
+
+   context->doorbell_array = vmci_handle_arr_create(0);
+   if (!context->doorbell_array) {
+   error = -ENOMEM;
+   goto err_

[PATCH 00/12] VMCI for Linux upstreaming

2012-11-01 Thread George Zhang


* * *
This series of VMCI linux upstreaming patches include latest udpate from
VMware.

Summary of changes:
- Use RCU for context lookup.
- Remove redundant init()/empty functions.
- Remove unnecessary ASSERTs.
- Remove delayed event callbacks.
- Cleanup some comments.
- Cleanup makefiles.
- Drop -I$(src)/shared custom flags from Makefile for VSOCK.
- Rename vmci_ctx_init_ctx() to vmci_ctx_create().
- Get rid of vmci_ctx_init().
- Rename vmci_ctx_release() to vmci_ctx_put().



* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vmci kernel
module. The vmw_vsock kernel module will be presented in a later post.


* * *

VMCI allows virtual machines to communicate with host kernel modules
and the VMware hypervisors. User level applications both in a virtual
machine and on the host can use vmw_vmci through VMCI Sockets, a socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

In a virtual machine, VMCI is exposed as a regular PCI device. The
primary communication mechanisms supported are a point-to-point
bidirectional transport based on a pair of memory-mapped queues, and
asynchronous notifications in the form of datagrams and
doorbells. These features are available to kernel level components
such as HGFS and VMCI Sockets through the VMCI kernel API. In addition
to this, the VMCI kernel API provides support for receiving events
related to the state of the VMCI communication channels, and the
virtual machine itself.

Outside the virtual machine, the host side support of the VMCI kernel
module makes the same VMCI kernel API available to VMCI endpoints on
the host. In addition to this, the host side manages each VMCI device
in a virtual machine through a context object. This context object
serves to identify the virtual machine for communication, and to track
the resource consumption of the given VMCI device. Both operations
related to communication between the virtual machine and the host
kernel, and those related to the management of the VMCI device state
in the host kernel, are invoked by the user level component of the
hypervisor through a set of ioctls on the VMCI device node.  To
provide seamless support for nested virtualization, where a virtual
machine may use both a VMCI PCI device to talk to its hypervisor, and
the VMCI host side support to run nested virtual machines, the VMCI
host and virtual machine support are combined in a single kernel
module.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.


---

George Zhang (12):
  VMCI: context implementation.
  VMCI: datagram implementation.
  VMCI: doorbell implementation.
  VMCI: device driver implementaton.
  VMCI: event handling implementation.
  VMCI: handle array implementation.
  VMCI: queue pairs implementation.
  VMCI: resource object implementation.
  VMCI: routing implementation.
  VMCI: guest side driver implementation.
  VMCI: host side driver implementation.
  VMCI: Some header and config files.


 drivers/misc/Kconfig  |1 
 drivers/misc/Makefile |2 
 drivers/misc/vmw_vmci/Kconfig |   16 
 drivers/misc/vmw_vmci/Makefile|4 
 drivers/misc/vmw_vmci/vmci_common_int.h   |   34 
 drivers/misc/vmw_vmci/vmci_context.c  | 1247 ++
 drivers/misc/vmw_vmci/vmci_context.h  |  183 ++
 drivers/misc/vmw_vmci/vmci_datagram.c |  506 
 drivers/misc/vmw_vmci/vmci_datagram.h |   52 
 drivers/misc/vmw_vmci/vmci_doorbell.c |  645 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   53 
 drivers/misc/vmw_vmci/vmci_driver.c   |  116 +
 drivers/misc/vmw_vmci/vmci_driver.h   |   50 
 drivers/misc/vmw_vmci/vmci_event.c|  229 ++
 drivers/misc/vmw_vmci/vmci_event.h|   25 
 drivers/misc/vmw_vmci/vmci_guest.c|  762 ++
 drivers/misc/vmw_vmci/vmci_handle_array.c |  142 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   52 
 drivers

[PATCH 12/12] VMCI: Some header and config files.

2012-10-29 Thread George Zhang
VMCI head config patch Adds all the necessary files to enable building of the
VMCI module with the Linux Makefiles and Kconfig systems. Also adds the header
files used for building modules against the driver.


Signed-off-by: George Zhang 
---
 drivers/misc/Kconfig|1 
 drivers/misc/Makefile   |2 
 drivers/misc/vmw_vmci/Kconfig   |   16 +
 drivers/misc/vmw_vmci/Makefile  |   43 +
 drivers/misc/vmw_vmci/vmci_common_int.h |   34 +
 include/linux/vmw_vmci_api.h|   85 +++
 include/linux/vmw_vmci_defs.h   |  977 +++
 7 files changed, 1158 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/Kconfig
 create mode 100644 drivers/misc/vmw_vmci/Makefile
 create mode 100644 drivers/misc/vmw_vmci/vmci_common_int.h
 create mode 100644 include/linux/vmw_vmci_api.h
 create mode 100644 include/linux/vmw_vmci_defs.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2661f6e..fe38c7a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -517,4 +517,5 @@ source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
+source "drivers/misc/vmw_vmci/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 456972f..21ed953 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -51,3 +51,5 @@ obj-y += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)+= mei/
+obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
+obj-$(CONFIG_VMWARE_VMCI)  += vmw_vmci/
diff --git a/drivers/misc/vmw_vmci/Kconfig b/drivers/misc/vmw_vmci/Kconfig
new file mode 100644
index 000..55015e7
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Kconfig
@@ -0,0 +1,16 @@
+#
+# VMware VMCI device
+#
+
+config VMWARE_VMCI
+   tristate "VMware VMCI Driver"
+   depends on X86
+   help
+ This is VMware's Virtual Machine Communication Interface.  It enables
+ high-speed communication between host and guest in a virtual
+ environment via the VMCI virtual device.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vmw_vmci.
diff --git a/drivers/misc/vmw_vmci/Makefile b/drivers/misc/vmw_vmci/Makefile
new file mode 100644
index 000..be09746
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Makefile
@@ -0,0 +1,43 @@
+
+#
+# Linux driver for VMware's VMCI device.
+#
+# Copyright (C) 2007-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 of the License 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, GOOD TITLE or
+# NON INFRINGEMENT.  See the GNU General Public License for more
+# details.
+#
+# Maintained by: Andrew Stiegmann 
+#
+
+
+#
+# Makefile for the VMware VMCI
+#
+
+obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci.o
+
+vmw_vmci-y += vmci_context.o
+vmw_vmci-y += vmci_datagram.o
+vmw_vmci-y += vmci_doorbell.o
+vmw_vmci-y += vmci_driver.o
+vmw_vmci-y += vmci_event.o
+vmw_vmci-y += vmci_guest.o
+vmw_vmci-y += vmci_handle_array.o
+vmw_vmci-y += vmci_host.o
+vmw_vmci-y += vmci_queue_pair.o
+vmw_vmci-y += vmci_resource.o
+vmw_vmci-y += vmci_route.o
+
+vmci:
+   $(MAKE) -C ../../.. SUBDIRS=$$PWD CONFIG_VMWARE_VMCI=m modules
+
+clean:
+   $(MAKE) -C ../../.. SUBDIRS=$$PWD CONFIG_VMWARE_VMCI=m clean
diff --git a/drivers/misc/vmw_vmci/vmci_common_int.h 
b/drivers/misc/vmw_vmci/vmci_common_int.h
new file mode 100644
index 000..77667ec
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_common_int.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef _VMCI_COMMONINT_H_
+#define _VMCI_COMMONINT_H_
+
+#include 
+
+#define ASSERT(cond) BUG_ON(!(cond))
+
+#define PCI_VENDOR_ID_V

[PATCH 11/12] VMCI: host side driver implementation.

2012-10-29 Thread George Zhang
VMCI host side driver code implementation.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_host.c | 1046 +
 1 files changed, 1046 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_host.c

diff --git a/drivers/misc/vmw_vmci/vmci_host.c 
b/drivers/misc/vmw_vmci/vmci_host.c
new file mode 100644
index 000..9cab365
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_host.c
@@ -0,0 +1,1046 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_handle_array.h"
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+enum {
+   VMCI_NOTIFY_RESOURCE_QUEUE_PAIR = 0,
+   VMCI_NOTIFY_RESOURCE_DOOR_BELL = 1,
+};
+
+enum {
+   VMCI_NOTIFY_RESOURCE_ACTION_NOTIFY = 0,
+   VMCI_NOTIFY_RESOURCE_ACTION_CREATE = 1,
+   VMCI_NOTIFY_RESOURCE_ACTION_DESTROY = 2,
+};
+
+/*
+ * VMCI driver initialization. This block can also be used to
+ * pass initial group membership etc.
+ */
+struct vmci_init_blk {
+   u32 cid;
+   u32 flags;
+};
+
+/* VMCIqueue_pairAllocInfo_VMToVM */
+struct vmci_qp_alloc_info_vmvm {
+   struct vmci_handle handle;
+   u32 peer;
+   u32 flags;
+   u64 produce_size;
+   u64 consume_size;
+   u64 produce_page_file;/* User VA. */
+   u64 consume_page_file;/* User VA. */
+   u64 produce_page_file_size;  /* Size of the file name array. */
+   u64 consume_page_file_size;  /* Size of the file name array. */
+   s32 result;
+   u32 _pad;
+};
+
+/* VMCISetNotifyInfo: Used to pass notify flag's address to the host driver. */
+struct vmci_set_notify_info {
+   u64 notify_uva;
+   s32 result;
+   u32 _pad;
+};
+
+/*
+ * Per-instance host state
+ */
+struct vmci_host_dev {
+   struct vmci_ctx *context;
+   int user_version;
+   enum vmci_obj_type ct_type;
+   struct mutex lock;  /* Mutex lock for vmci context access */
+};
+
+static struct vmci_ctx *host_context;
+static bool vmci_host_device_initialized;
+static atomic_t vmci_host_active_users = ATOMIC_INIT(0);
+
+/*
+ * Determines whether the VMCI host personality is
+ * available. Since the core functionality of the host driver is
+ * always present, all guests could possibly use the host
+ * personality. However, to minimize the deviation from the
+ * pre-unified driver state of affairs, we only consider the host
+ * device active if there is no active guest device or if there
+ * are VMX'en with active VMCI contexts using the host device.
+ */
+bool vmci_host_code_active(void)
+{
+   return vmci_host_device_initialized &&
+   (!vmci_guest_code_active() ||
+atomic_read(&vmci_host_active_users) > 0);
+}
+
+/*
+ * Called on open of /dev/vmci.
+ */
+static int vmci_host_open(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev;
+
+   vmci_host_dev = kzalloc(sizeof(struct vmci_host_dev), GFP_KERNEL);
+   if (vmci_host_dev == NULL)
+   return -ENOMEM;
+
+   vmci_host_dev->ct_type = VMCIOBJ_NOT_SET;
+   mutex_init(&vmci_host_dev->lock);
+   filp->private_data = vmci_host_dev;
+
+   return 0;
+}
+
+/*
+ * Called on close of /dev/vmci, most often when the process
+ * exits.
+ */
+static int vmci_host_close(struct inode *inode, struct file *filp)
+{
+   struct vmci_host_dev *vmci_host_dev = filp->private_data;
+
+   ASSERT(vmci_host_dev);
+
+   if (vmci_host_dev->ct_type == VMCIOBJ_CONTEXT) {
+   ASSERT(vmci_host_dev->context);
+
+   vmci_ctx_release_ctx(vmci_host_dev->context);
+   vmci_host_dev->context = NULL;
+
+   /*
+* The number of active contexts is used to track whether any
+* VMX'en are using the host personality. It is incremented when
+* a context is created through the IOCTL_VMCI_INIT_CONTEXT
+* ioctl.

[PATCH 10/12] VMCI: guest side driver implementation.

2012-10-29 Thread George Zhang
VMCI guest side driver code implementation.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_guest.c |  765 
 1 files changed, 765 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_guest.c

diff --git a/drivers/misc/vmw_vmci/vmci_guest.c 
b/drivers/misc/vmw_vmci/vmci_guest.c
new file mode 100644
index 000..23f5e9e
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -0,0 +1,765 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define VMCI_UTIL_NUM_RESOURCES 1
+
+static bool vmci_disable_msi;
+module_param_named(disable_msi, vmci_disable_msi, bool, 0);
+MODULE_PARM_DESC(disable_msi, "Disable MSI use in driver - (default=0)");
+
+static bool vmci_disable_msix;
+module_param_named(disable_msix, vmci_disable_msix, bool, 0);
+MODULE_PARM_DESC(disable_msix, "Disable MSI-X use in driver - (default=0)");
+
+static u32 ctx_update_sub_id = VMCI_INVALID_ID;
+static u32 vm_context_id = VMCI_INVALID_ID;
+
+struct vmci_guest_device {
+   struct device *dev; /* PCI device we are attached to */
+   void __iomem *iobase;
+
+   unsigned int irq;
+   unsigned int intr_type;
+   bool exclusive_vectors;
+   struct msix_entry msix_entries[VMCI_MAX_INTRS];
+
+   struct tasklet_struct datagram_tasklet;
+   struct tasklet_struct bm_tasklet;
+
+   void *data_buffer;
+   void *notification_bitmap;
+};
+
+/* vmci_dev singleton device and supporting data*/
+static struct vmci_guest_device *vmci_dev_g;
+static DEFINE_SPINLOCK(vmci_dev_spinlock);
+
+static atomic_t vmci_num_guest_devices = ATOMIC_INIT(0);
+
+bool vmci_guest_code_active(void)
+{
+   return atomic_read(&vmci_num_guest_devices) != 0;
+}
+
+u32 vmci_get_vm_context_id(void)
+{
+   if (vm_context_id == VMCI_INVALID_ID) {
+   u32 result;
+   struct vmci_datagram get_cid_msg;
+   get_cid_msg.dst =
+   vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
+VMCI_GET_CONTEXT_ID);
+   get_cid_msg.src = VMCI_ANON_SRC_HANDLE;
+   get_cid_msg.payload_size = 0;
+   result = vmci_send_datagram(&get_cid_msg);
+   if (result >= 0)
+   vm_context_id = result;
+   }
+   return vm_context_id;
+}
+
+/*
+ * VM to hypervisor call mechanism. We use the standard VMware naming
+ * convention since shared code is calling this function as well.
+ */
+int vmci_send_datagram(struct vmci_datagram *dg)
+{
+   unsigned long flags;
+   int result;
+
+   /* Check args. */
+   if (dg == NULL)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* Need to acquire spinlock on the device because the datagram
+* data may be spread over multiple pages and the monitor may
+* interleave device user rpc calls from multiple
+* VCPUs. Acquiring the spinlock precludes that
+* possibility. Disabling interrupts to avoid incoming
+* datagrams during a "rep out" and possibly landing up in
+* this function.
+*/
+   spin_lock_irqsave(&vmci_dev_spinlock, flags);
+
+   if (vmci_dev_g) {
+   iowrite8_rep(vmci_dev_g->iobase + VMCI_DATA_OUT_ADDR,
+dg, VMCI_DG_SIZE(dg));
+   result = ioread32(vmci_dev_g->iobase + VMCI_RESULT_LOW_ADDR);
+   } else {
+   result = VMCI_ERROR_UNAVAILABLE;
+   }
+
+   spin_unlock_irqrestore(&vmci_dev_spinlock, flags);
+
+   return result;
+}
+EXPORT_SYMBOL_GPL(vmci_send_datagram);
+
+/*
+ * Gets called with the new context id if updated or resumed.
+ * Context id.
+ */
+static void vmci_guest_cid_update(u32 sub_id,
+ const struct vmci_event_data *event_data,
+ void *client_data)
+{
+   const struct vmci_event_payld_ctx *ev_payload =
+   vmci_event_data_const_payload(event_data);
+
+   if (sub_id != ctx_update_sub_id) {

[PATCH 09/12] VMCI: routing implementation.

2012-10-29 Thread George Zhang
VMCI routing code is responsible for routing between various hosts/guests
as well as routing in nested scenarios.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_route.c |  237 
 drivers/misc/vmw_vmci/vmci_route.h |   30 +
 2 files changed, 267 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.h

diff --git a/drivers/misc/vmw_vmci/vmci_route.c 
b/drivers/misc/vmw_vmci/vmci_route.c
new file mode 100644
index 000..8aa43ee
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_route.c
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+/*
+ * Make a routing decision for the given source and destination handles.
+ * This will try to determine the route using the handles and the available
+ * devices.  Will set the source context if it is invalid.
+ */
+int vmci_route(struct vmci_handle *src,
+  const struct vmci_handle *dst,
+  bool from_guest,
+  enum vmci_route *route)
+{
+   bool has_host_device = vmci_host_code_active();
+   bool has_guest_device = vmci_guest_code_active();
+
+   ASSERT(src);
+   ASSERT(dst);
+   ASSERT(route);
+
+   *route = VMCI_ROUTE_NONE;
+
+   /*
+* "from_guest" is only ever set to true by
+* IOCTL_VMCI_DATAGRAM_SEND (or by the vmkernel equivalent),
+* which comes from the VMX, so we know it is coming from a
+* guest.
+*
+* To avoid inconsistencies, test these once.  We will test
+* them again when we do the actual send to ensure that we do
+* not touch a non-existent device.
+*/
+
+   /* Must have a valid destination context. */
+   if (VMCI_INVALID_ID == dst->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /* Anywhere to hypervisor. */
+   if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
+
+   /*
+* If this message already came from a guest then we
+* cannot send it to the hypervisor.  It must come
+* from a local client.
+*/
+   if (from_guest)
+   return VMCI_ERROR_DST_UNREACHABLE;
+
+   /*
+* We must be acting as a guest in order to send to
+* the hypervisor.
+*/
+   if (!has_guest_device)
+   return VMCI_ERROR_DEVICE_NOT_FOUND;
+
+   /* And we cannot send if the source is the host context. */
+   if (VMCI_HOST_CONTEXT_ID == src->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* If the client passed the ANON source handle then
+* respect it (both context and resource are invalid).
+* However, if they passed only an invalid context,
+* then they probably mean ANY, in which case we
+* should set the real context here before passing it
+* down.
+*/
+   if (VMCI_INVALID_ID == src->context &&
+   VMCI_INVALID_ID != src->resource)
+   src->context = vmci_get_context_id();
+
+   /* Send from local client down to the hypervisor. */
+   *route = VMCI_ROUTE_AS_GUEST;
+   return VMCI_SUCCESS;
+   }
+
+   /* Anywhere to local client on host. */
+   if (VMCI_HOST_CONTEXT_ID == dst->context) {
+   /*
+* If it is not from a guest but we are acting as a
+* guest, then we need to send it down to the host.
+* Note that if we are also acting as a host then this
+* will prevent us from sending from local client to
+* local client, but we accept that restriction as a
+* way to remove any ambiguity from the host context.
+*/
+   if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* If the hypervisor is the source, this is
+* host local communication. The hypervisor
+* may se

[PATCH 08/12] VMCI: resource object implementation.

2012-10-29 Thread George Zhang
VMCI resource tracks all used resources within the vmci code.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_resource.c |  237 +
 drivers/misc/vmw_vmci/vmci_resource.h |   59 
 2 files changed, 296 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.h

diff --git a/drivers/misc/vmw_vmci/vmci_resource.c 
b/drivers/misc/vmw_vmci/vmci_resource.c
new file mode 100644
index 000..a2f5fd0
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_resource.c
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+
+
+#define VMCI_RESOURCE_HASH_BITS 7
+#define VMCI_RESOURCE_HASH_BUCKETS  (1 << VMCI_RESOURCE_HASH_BITS)
+
+struct vmci_hash_table {
+   spinlock_t lock;
+   struct hlist_head entries[VMCI_RESOURCE_HASH_BUCKETS];
+};
+
+static struct vmci_hash_table vmci_resource_table = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_resource_table.lock),
+};
+
+static unsigned int vmci_resource_hash(struct vmci_handle handle)
+{
+   return hash_32(VMCI_HANDLE_TO_RESOURCE_ID(handle),
+  VMCI_RESOURCE_HASH_BITS);
+}
+
+/*
+ * Gets a resource (if one exists) matching given handle from the hash table.
+ */
+static struct vmci_resource *vmci_resource_lookup(struct vmci_handle handle)
+{
+   struct vmci_resource *r, *resource = NULL;
+   struct hlist_node *node;
+   unsigned int idx = vmci_resource_hash(handle);
+
+   BUG_ON(VMCI_HANDLE_EQUAL(handle, VMCI_INVALID_HANDLE));
+
+   rcu_read_lock();
+   hlist_for_each_entry_rcu(r, node,
+&vmci_resource_table.entries[idx], node) {
+   u32 rid = VMCI_HANDLE_TO_RESOURCE_ID(r->handle);
+   u32 cid = VMCI_HANDLE_TO_CONTEXT_ID(r->handle);
+
+   if (rid == VMCI_HANDLE_TO_RESOURCE_ID(handle) &&
+   (cid == VMCI_HANDLE_TO_CONTEXT_ID(handle) ||
+cid == VMCI_INVALID_ID)) {
+   resource = r;
+   break;
+   }
+   }
+   rcu_read_unlock();
+
+   return resource;
+}
+
+/*
+ * Find an unused resource ID and return it. The first
+ * VMCI_RESERVED_RESOURCE_ID_MAX are reserved so we start from
+ * its value + 1.
+ * Returns VMCI resource id on success, VMCI_INVALID_ID on failure.
+ */
+static u32 vmci_resource_find_id(u32 context_id)
+{
+   static u32 resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   u32 old_rid = resource_id;
+   u32 current_rid;
+
+   /*
+* Generate a unique resource ID.  Keep on trying until we wrap around
+* in the RID space.
+*/
+   BUG_ON(old_rid <= VMCI_RESERVED_RESOURCE_ID_MAX);
+
+   do {
+   struct vmci_handle handle;
+
+   current_rid = resource_id;
+   resource_id++;
+   if (unlikely(resource_id == VMCI_INVALID_ID)) {
+   /* Skip the reserved rids. */
+   resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   }
+
+   handle = vmci_make_handle(context_id, current_rid);
+   if (!vmci_resource_lookup(handle))
+   return current_rid;
+   } while (resource_id != old_rid);
+
+   return VMCI_INVALID_ID;
+}
+
+
+int vmci_resource_add(struct vmci_resource *resource,
+ enum vmci_resource_type resource_type,
+ struct vmci_handle handle)
+
+{
+   unsigned int idx;
+   int result;
+
+   BUG_ON(!resource);
+
+   spin_lock(&vmci_resource_table.lock);
+
+   if (handle.resource == VMCI_INVALID_ID) {
+   handle.resource = vmci_resource_find_id(handle.context);
+   if (handle.resource == VMCI_INVALID_ID) {
+   result = VMCI_ERROR_NO_HANDLE;
+   goto out;
+   }
+   } else if (vmci_resource_lookup(handle)) {
+   result = VMCI_ERROR_ALREADY_EXISTS;
+   goto out;
+   }
+
+   resource->handle = handle;
+   resource->type = resource_type;
+   INIT_HLIST_NODE(&resource->node);
+   kref_init(&resource->kref);
+   init

[PATCH 06/12] VMCI: handle array implementation.

2012-10-29 Thread George Zhang
VMCI handle code adds support for dynamic arrays that will grow if they need to.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_handle_array.c |  162 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   46 
 2 files changed, 208 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.h

diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c 
b/drivers/misc/vmw_vmci/vmci_handle_array.c
new file mode 100644
index 000..c7db831
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_handle_array.c
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+#include 
+#include "vmci_handle_array.h"
+
+static size_t handle_arr_calc_size(size_t capacity)
+{
+   return sizeof(struct vmci_handle_arr) +
+   capacity * sizeof(struct vmci_handle);
+}
+
+struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity)
+{
+   struct vmci_handle_arr *array;
+
+   if (capacity == 0)
+   capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
+
+   array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC);
+   if (!array)
+   return NULL;
+
+   array->capacity = capacity;
+   array->size = 0;
+
+   return array;
+}
+
+void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
+{
+   kfree(array);
+}
+
+void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
+ struct vmci_handle handle)
+{
+   struct vmci_handle_arr *array;
+
+   BUG_ON(!array_ptr || !*array_ptr);
+   array = *array_ptr;
+
+   if (unlikely(array->size >= array->capacity)) {
+   /* reallocate. */
+   struct vmci_handle_arr *new_array;
+   size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT;
+   size_t new_size = handle_arr_calc_size(new_capacity);
+
+   new_array = krealloc(array, new_size, GFP_ATOMIC);
+   if (!new_array)
+   return;
+
+   new_array->capacity = new_capacity;
+   *array_ptr = array = new_array;
+   }
+
+   array->entries[array->size] = handle;
+   array->size++;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
+ */
+struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
+   struct vmci_handle entry_handle)
+{
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+   size_t i;
+
+   BUG_ON(!array);
+
+   for (i = 0; i < array->size; i++) {
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle)) {
+   handle = array->entries[i];
+   array->size--;
+   array->entries[i] = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   break;
+   }
+   }
+
+   return handle;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
+ */
+struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array)
+{
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+
+   BUG_ON(!array);
+
+   if (array->size) {
+   array->size--;
+   handle = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   }
+
+   return handle;
+}
+
+/*
+ * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
+ */
+struct vmci_handle
+vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index)
+{
+   BUG_ON(!array);
+
+   if (unlikely(index >= array->size))
+   return VMCI_INVALID_HANDLE;
+
+   return array->entries[index];
+}
+
+size_t vmci_handle_arr_get_size(const struct vmci_handle_arr *array)
+{
+   BUG_ON(!array);
+
+   return array->size;
+}
+
+bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
+  struct vmci_handle entry_handle)
+{
+   size_t i;
+
+   BUG_ON(!array);
+
+   for (i = 0; i < array->size; i++)
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle))
+   return true;
+
+   return false;
+}
+
+/*
+ * NULL if the array 

[PATCH 05/12] VMCI: event handling implementation.

2012-10-29 Thread George Zhang
VMCI event code that manages event handlers and handles callbacks when specific 
events fire.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_event.c |  371 
 drivers/misc/vmw_vmci/vmci_event.h |   25 ++
 2 files changed, 396 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.h

diff --git a/drivers/misc/vmw_vmci/vmci_event.c 
b/drivers/misc/vmw_vmci/vmci_event.c
new file mode 100644
index 000..a058b6f
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_event.c
@@ -0,0 +1,371 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define EVENT_MAGIC 0xEABE
+#define VMCI_EVENT_MAX_ATTEMPTS 10
+
+struct vmci_subscription {
+   u32 id;
+   u32 event;
+   struct kref kref;
+   struct completion done; /* unregistered, ready to be freed */
+   vmci_event_cb callback;
+   void *callback_data;
+   struct list_head node;  /* on one of subscriber lists */
+   bool run_delayed;
+};
+
+static struct list_head subscriber_array[VMCI_EVENT_MAX];
+static DEFINE_MUTEX(subscriber_mutex);
+
+struct delayed_event_info {
+   struct work_struct work;
+   struct vmci_subscription *sub;
+   u8 event_payload[sizeof(struct vmci_event_data_max)];
+};
+
+int __init vmci_event_init(void)
+{
+   int i;
+
+   for (i = 0; i < VMCI_EVENT_MAX; i++)
+   INIT_LIST_HEAD(&subscriber_array[i]);
+
+   return VMCI_SUCCESS;
+}
+
+void vmci_event_exit(void)
+{
+   int e;
+
+   /* We free all memory at exit. */
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur, *p2;
+   list_for_each_entry_safe(cur, p2, &subscriber_array[e], node) {
+
+   /*
+* We should never get here because all events
+* should have been unregistered before we try
+* to unload the driver module.  Also, delayed
+* callbacks could still be firing so this
+* cleanup would not be safe.  Still it is
+* better to free the memory than not ... so
+* we leave this code in just in case
+*/
+   pr_warn("Unexpected free events occuring.\n");
+   kfree(cur);
+   }
+   }
+
+}
+
+/*
+ * Gets a reference to the given VMCISubscription.
+ */
+static struct vmci_subscription *event_get(struct vmci_subscription *entry)
+{
+   kref_get(&entry->kref);
+
+   return entry;
+}
+
+static void event_signal_destroy(struct kref *kref)
+{
+   struct vmci_subscription *entry =
+   container_of(kref, struct vmci_subscription, kref);
+
+   complete(&entry->done);
+}
+
+/*
+ * Releases the given VMCISubscription.
+ * Fires the destroy event if the reference count has gone to zero.
+ */
+static void event_release(struct vmci_subscription *entry)
+{
+   kref_put(&entry->kref, event_signal_destroy);
+}
+
+/*
+ * Find entry. Assumes lock is held.
+ */
+static struct vmci_subscription *event_find(u32 sub_id)
+{
+   int e;
+
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur;
+   list_for_each_entry(cur, &subscriber_array[e], node) {
+   if (cur->id == sub_id)
+   return cur;
+   }
+   }
+   return NULL;
+}
+
+/*
+ * Calls the specified callback in a delayed context.
+ */
+static void event_delayed_dispatch(struct work_struct *work)
+{
+   struct delayed_event_info *event_info =
+   container_of(work, struct delayed_event_info, work);
+   struct vmci_subscription *sub = event_info->sub;
+   struct vmci_event_data *ed;
+
+   BUG_ON(!sub);
+
+   ed = (struct vmci_event_data *)event_info->event_payload;
+
+   sub->callback(sub->id, ed, sub->callback_data);
+   event_release(sub);
+
+   kfree(event_info);
+}
+
+static void event_schedule_delayed(const struct vmci_event_msg *event_msg,
+  struct vmci_subscri

[PATCH 04/12] VMCI: device driver implementaton.

2012-10-29 Thread George Zhang
VMCI driver code implementes both the host and guest personalities of the VMCI 
driver.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_driver.c |  159 +++
 drivers/misc/vmw_vmci/vmci_driver.h |   50 +++
 2 files changed, 209 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_driver.h

diff --git a/drivers/misc/vmw_vmci/vmci_driver.c 
b/drivers/misc/vmw_vmci/vmci_driver.c
new file mode 100644
index 000..1ca0c7e
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_driver.c
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+static bool vmci_disable_host;
+module_param_named(disable_host, vmci_disable_host, bool, 0);
+MODULE_PARM_DESC(disable_host,
+"Disable driver host personality (default=enabled)");
+
+static bool vmci_disable_guest;
+module_param_named(disable_guest, vmci_disable_guest, bool, 0);
+MODULE_PARM_DESC(disable_guest,
+"Disable driver guest personality (default=enabled)");
+
+static bool vmci_guest_personality_initialized;
+static bool vmci_host_personality_initialized;
+
+/*
+ * vmci_get_context_id() - Gets the current context ID.
+ *
+ * Returns the current context ID.  Note that since this is accessed only
+ * from code running in the host, this always returns the host context ID.
+ */
+u32 vmci_get_context_id(void)
+{
+   if (vmci_guest_code_active()) {
+   return vmci_get_vm_context_id();
+   } else if (vmci_host_code_active()) {
+   return VMCI_HOST_CONTEXT_ID;
+   } else {
+   return VMCI_INVALID_ID;
+   }
+}
+EXPORT_SYMBOL_GPL(vmci_get_context_id);
+
+/*
+ * vmci_version() - Returns the version of the driver.
+ *
+ * Returns the version of the VMCI driver.
+ */
+u32 vmci_version(void)
+{
+   return VMCI_VERSION;
+}
+EXPORT_SYMBOL_GPL(vmci_version);
+
+static int __init vmci_core_init(void)
+{
+   int result;
+
+   result = vmci_ctx_init();
+   if (result < VMCI_SUCCESS) {
+   pr_err("Failed to initialize VMCIContext (result=%d).\n",
+   result);
+   return -EINVAL;
+   }
+
+   result = vmci_datagram_init();
+   if (result < VMCI_SUCCESS) {
+   pr_err("Failed to initialize VMCIDatagram (result=%d).\n",
+   result);
+   return -EINVAL;
+   }
+
+   result = vmci_event_init();
+   if (result < VMCI_SUCCESS) {
+   pr_err("Failed to initialize VMCIEvent (result=%d).\n", result);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static void __exit vmci_core_exit(void)
+{
+   vmci_event_exit();
+}
+
+static int __init vmci_drv_init(void)
+{
+   int error;
+
+   error = vmci_core_init();
+   if (error)
+   return error;
+
+   if (!vmci_disable_guest) {
+   error = vmci_guest_init();
+   if (error) {
+   pr_warn("Failed to initialize guest personality 
(err=%d).\n",
+   error);
+   } else {
+   vmci_guest_personality_initialized = true;
+   pr_info("Guest personality initialized and is %s\n",
+   vmci_guest_code_active() ?
+   "active" : "inactive");
+   }
+   }
+
+   if (!vmci_disable_host) {
+   error = vmci_host_init();
+   if (error) {
+   pr_warn("Unable to initialize host personality 
(err=%d).\n",
+   error);
+   } else {
+   vmci_host_personality_initialized = true;
+   pr_info("Initialized host personality\n");
+   }
+   }
+
+   if (!vmci_guest_personality_initialized &&
+   !vmci_host_personality_initialized) {
+   vmci_core_exit();
+   return -ENODEV;
+   }
+
+   pr_debug("Module is initialized\n");
+   return 0;
+}
+module_init(vmci_drv_init);
+
+static void __exit vmci_drv_exit(void)
+{
+

[PATCH 03/12] VMCI: doorbell implementation.

2012-10-29 Thread George Zhang
VMCI doorbell code allows for notifcations between host and guest.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_doorbell.c |  673 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   53 +++
 2 files changed, 726 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.h

diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.c 
b/drivers/misc/vmw_vmci/vmci_doorbell.c
new file mode 100644
index 000..ebe4180
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -0,0 +1,673 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+
+#define VMCI_DOORBELL_INDEX_BITS   6
+#define VMCI_DOORBELL_INDEX_TABLE_SIZE (1 << VMCI_DOORBELL_INDEX_BITS)
+#define VMCI_DOORBELL_HASH(_idx)   hash_32(_idx, VMCI_DOORBELL_INDEX_BITS)
+
+/*
+ * DoorbellEntry describes the a doorbell notification handle allocated by the
+ * host.
+ */
+struct dbell_entry {
+   struct vmci_resource resource;
+   struct hlist_node node;
+   struct work_struct work;
+   vmci_callback notify_cb;
+   void *client_data;
+   u32 idx;
+   u32 priv_flags;
+   bool run_delayed;
+   atomic_t active;/* Only used by guest personality */
+};
+
+/* The VMCI index table keeps track of currently registered doorbells. */
+struct dbell_index_table {
+   spinlock_t lock;/* Index table lock */
+   struct hlist_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
+};
+
+static struct dbell_index_table vmci_doorbell_it = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_doorbell_it.lock),
+};
+
+/*
+ * The max_notify_idx is one larger than the currently known bitmap index in
+ * use, and is used to determine how much of the bitmap needs to be scanned.
+ */
+static u32 max_notify_idx;
+
+/*
+ * The notify_idx_count is used for determining whether there are free entries
+ * within the bitmap (if notify_idx_count + 1 < max_notify_idx).
+ */
+static u32 notify_idx_count;
+
+/*
+ * The last_notify_idx_reserved is used to track the last index handed out - in
+ * the case where multiple handles share a notification index, we hand out
+ * indexes round robin based on last_notify_idx_reserved.
+ */
+static u32 last_notify_idx_reserved;
+
+/* This is a one entry cache used to by the index allocation. */
+static u32 last_notify_idx_released = PAGE_SIZE;
+
+
+/*
+ * Utility function that retrieves the privilege flags associated
+ * with a given doorbell handle. For guest endpoints, the
+ * privileges are determined by the context ID, but for host
+ * endpoints privileges are associated with the complete
+ * handle. Hypervisor endpoints are not yet supported.
+ */
+int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags)
+{
+   if (priv_flags == NULL || handle.context == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (handle.context == VMCI_HOST_CONTEXT_ID) {
+   struct dbell_entry *entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DOORBELL);
+   if (!resource)
+   return VMCI_ERROR_NOT_FOUND;
+
+   entry = container_of(resource, struct dbell_entry, resource);
+   *priv_flags = entry->priv_flags;
+   vmci_resource_put(resource);
+   } else if (handle.context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* Hypervisor endpoints for notifications are not
+* supported (yet).
+*/
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   *priv_flags = vmci_context_get_priv_flags(handle.context);
+   }
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Find doorbell entry by bitmap index.
+ */
+static struct dbell_entry *dbell_index_table_find(u32 idx)
+{
+   u32 bucket = VMCI_DOORBELL_HASH(idx);
+   struct dbell_entry *dbell;
+   struct hlist_node *node;
+
+   BUG_ON(!vmci_guest_code_active());
+
+ 

[PATCH 02/12] VMCI: datagram implementation.

2012-10-29 Thread George Zhang
VMCI datagram Implements datagrams to allow data to be sent between host and 
guest.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_datagram.c |  520 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   55 +++
 2 files changed, 575 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.h

diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c 
b/drivers/misc/vmw_vmci/vmci_datagram.c
new file mode 100644
index 000..55bf882
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -0,0 +1,520 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_resource.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+#include "vmci_route.h"
+
+/*
+ * struct datagram_entry describes the datagram entity. It is used for datagram
+ * entities created only on the host.
+ */
+struct datagram_entry {
+   struct vmci_resource resource;
+   u32 flags;
+   bool run_delayed;
+   vmci_datagram_recv_cb recv_cb;
+   void *client_data;
+   u32 priv_flags;
+};
+
+struct delayed_datagram_info {
+   struct datagram_entry *entry;
+   struct vmci_datagram msg;
+   struct work_struct work;
+   bool in_dg_host_queue;
+};
+
+static atomic_t delayed_dg_host_queue_size;
+
+
+/*
+ * Create a datagram entry given a handle pointer.
+ */
+static int dg_create_handle(u32 resource_id,
+   u32 flags,
+   u32 priv_flags,
+   vmci_datagram_recv_cb recv_cb,
+   void *client_data, struct vmci_handle *out_handle)
+{
+   int result;
+   u32 context_id;
+   struct vmci_handle handle;
+   struct datagram_entry *entry;
+
+   ASSERT(recv_cb != NULL);
+   ASSERT(out_handle != NULL);
+   ASSERT(!(priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS));
+
+   if ((flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if ((flags & VMCI_FLAG_ANYCID_DG_HND) != 0) {
+   context_id = VMCI_INVALID_ID;
+   } else {
+   context_id = vmci_get_context_id();
+   if (context_id == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_RESOURCES;
+   }
+
+   handle = vmci_make_handle(context_id, resource_id);
+
+   entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+   if (!entry) {
+   pr_warn("Failed allocating memory for datagram entry.\n");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   entry->run_delayed = (flags & VMCI_FLAG_DG_DELAYED_CB) ? true : false;
+   entry->flags = flags;
+   entry->recv_cb = recv_cb;
+   entry->client_data = client_data;
+   entry->priv_flags = priv_flags;
+
+   /* Make datagram resource live. */
+   result = vmci_resource_add(&entry->resource,
+  VMCI_RESOURCE_TYPE_DATAGRAM,
+  handle);
+   if (result != VMCI_SUCCESS) {
+   pr_warn("Failed to add new resource (handle=0x%x:0x%x), error: 
%d\n",
+   handle.context, handle.resource, result);
+   kfree(entry);
+   return result;
+   }
+
+   *out_handle = vmci_resource_handle(&entry->resource);
+   return VMCI_SUCCESS;
+}
+
+int __init vmci_datagram_init(void)
+{
+   atomic_set(&delayed_dg_host_queue_size, 0);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Internal utilility function with the same purpose as
+ * vmci_datagram_get_priv_flags that also takes a context_id.
+ */
+static int vmci_datagram_get_priv_flags(u32 context_id,
+   struct vmci_handle handle,
+   u32 *priv_flags)
+{
+   ASSERT(priv_flags);
+   ASSERT(context_id != VMCI_INVALID_ID);
+
+   if (context_id == VMCI_HOST_CONTEXT_ID) {
+   struct datagram_entry *src_entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DATAGRAM);
+  

[PATCH 01/12] VMCI: context implementation.

2012-10-29 Thread George Zhang
VMCI Context code maintains state for vmci and allows the driver to communicate 
with multiple VMs.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_context.c | 1290 ++
 drivers/misc/vmw_vmci/vmci_context.h |  177 +
 2 files changed, 1467 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.h

diff --git a/drivers/misc/vmw_vmci/vmci_context.c 
b/drivers/misc/vmw_vmci/vmci_context.c
new file mode 100644
index 000..d4680dd
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_context.c
@@ -0,0 +1,1290 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+/*
+ * List of current VMCI contexts.
+ */
+static struct {
+   struct list_head head;
+   spinlock_t lock; /* Spinlock for context list operations */
+} ctx_list;
+
+/* Used by contexts that did not set up notify flag pointers */
+static bool ctx_dummy_notify;
+
+static void ctx_signal_notify(struct vmci_ctx *context)
+{
+   *context->notify = true;
+}
+
+static void ctx_clear_notify(struct vmci_ctx *context)
+{
+   *context->notify = false;
+}
+
+/*
+ * If nothing requires the attention of the guest, clears both
+ * notify flag and call.
+ */
+static void ctx_clear_notify_call(struct vmci_ctx *context)
+{
+   if (context->pending_datagrams == 0 &&
+   vmci_handle_arr_get_size(context->pending_doorbell_array) == 0)
+   ctx_clear_notify(context);
+}
+
+/*
+ * Sets the context's notify flag iff datagrams are pending for this
+ * context.  Called from vmci_setup_notify().
+ */
+void vmci_ctx_check_signal_notify(struct vmci_ctx *context)
+{
+   ASSERT(context);
+
+   spin_lock(&context->lock);
+   if (context->pending_datagrams)
+   ctx_signal_notify(context);
+   spin_unlock(&context->lock);
+}
+
+int __init vmci_ctx_init(void)
+{
+   INIT_LIST_HEAD(&ctx_list.head);
+   spin_lock_init(&ctx_list.lock);
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Allocates and initializes a VMCI context.
+ */
+int vmci_ctx_init_ctx(u32 cid,
+ u32 priv_flags,
+ uintptr_t event_hnd,
+ int user_version,
+ const struct cred *cred,
+ struct vmci_ctx **out_context)
+{
+   struct vmci_ctx *context;
+   int result;
+
+   if (priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
+   pr_devel("Invalid flag (flags=0x%x) for VMCI context.\n",
+priv_flags);
+   return VMCI_ERROR_INVALID_ARGS;
+   }
+
+   if (user_version == 0)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   context = kzalloc(sizeof(*context), GFP_KERNEL);
+   if (context == NULL) {
+   pr_warn("Failed to allocate memory for VMCI context.\n");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   INIT_LIST_HEAD(&context->list_item);
+   INIT_LIST_HEAD(&context->datagram_queue);
+
+   context->user_version = user_version;
+
+   context->queue_pair_array = vmci_handle_arr_create(0);
+   if (!context->queue_pair_array) {
+   result = VMCI_ERROR_NO_MEM;
+   goto error;
+   }
+
+   context->doorbell_array = vmci_handle_arr_create(0);
+   if (!context->doorbell_array) {
+   result = VMCI_ERROR_NO_MEM;
+   goto error;
+   }
+
+   context->pending_doorbell_array = vmci_handle_arr_create(0);
+   if (!context->pending_doorbell_array) {
+   result = VMCI_ERROR_NO_MEM;
+   goto error;
+   }
+
+   INIT_LIST_HEAD(&context->notifier_list);
+
+   spin_lock_init(&context->lock);
+
+   kref_init(&context->kref);
+
+   /* Inititialize host-specific VMCI context. */
+   init_waitqueue_head(&context->host_context.wait_queue);
+
+   context->priv_flags = priv_flags;
+
+   if (cred)
+   context->cred = get_cred(cr

[PATCH 00/12] VMCI for Linux upstreaming

2012-10-29 Thread George Zhang
* * *
This series of VMCI linux upstreaming patches include latest udpate from
VMware.
-split guest, host and core driver code into different files
-use EXPORT_SYMBOLS_GPL
-remove vmci_device_get and vmci_device_release APIs
-simplify the event deliver mechanism
-driver ioctl code cleanup
-sparse clean




* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vmci kernel
module. The vmw_vsock kernel module will be presented in a later post.


* * *

VMCI allows virtual machines to communicate with host kernel modules
and the VMware hypervisors. User level applications both in a virtual
machine and on the host can use vmw_vmci through VMCI Sockets, a socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

In a virtual machine, VMCI is exposed as a regular PCI device. The
primary communication mechanisms supported are a point-to-point
bidirectional transport based on a pair of memory-mapped queues, and
asynchronous notifications in the form of datagrams and
doorbells. These features are available to kernel level components
such as HGFS and VMCI Sockets through the VMCI kernel API. In addition
to this, the VMCI kernel API provides support for receiving events
related to the state of the VMCI communication channels, and the
virtual machine itself.

Outside the virtual machine, the host side support of the VMCI kernel
module makes the same VMCI kernel API available to VMCI endpoints on
the host. In addition to this, the host side manages each VMCI device
in a virtual machine through a context object. This context object
serves to identify the virtual machine for communication, and to track
the resource consumption of the given VMCI device. Both operations
related to communication between the virtual machine and the host
kernel, and those related to the management of the VMCI device state
in the host kernel, are invoked by the user level component of the
hypervisor through a set of ioctls on the VMCI device node.  To
provide seamless support for nested virtualization, where a virtual
machine may use both a VMCI PCI device to talk to its hypervisor, and
the VMCI host side support to run nested virtual machines, the VMCI
host and virtual machine support are combined in a single kernel
module.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.



---

George Zhang (12):
  VMCI: context implementation.
  VMCI: datagram implementation.
  VMCI: doorbell implementation.
  VMCI: device driver implementaton.
  VMCI: event handling implementation.
  VMCI: handle array implementation.
  VMCI: queue pairs implementation.
  VMCI: resource object implementation.
  VMCI: routing implementation.
  VMCI: guest side driver implementation.
  VMCI: host side driver implementation.
  VMCI: Some header and config files.


 drivers/misc/Kconfig  |1
 drivers/misc/Makefile |2
 drivers/misc/vmw_vmci/Kconfig |   16
 drivers/misc/vmw_vmci/Makefile|   43
 drivers/misc/vmw_vmci/vmci_common_int.h   |   34
 drivers/misc/vmw_vmci/vmci_context.c  | 1290 +++
 drivers/misc/vmw_vmci/vmci_context.h  |  177 +
 drivers/misc/vmw_vmci/vmci_datagram.c |  520 
 drivers/misc/vmw_vmci/vmci_datagram.h |   55
 drivers/misc/vmw_vmci/vmci_doorbell.c |  673 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   53
 drivers/misc/vmw_vmci/vmci_driver.c   |  159 +
 drivers/misc/vmw_vmci/vmci_driver.h   |   50
 drivers/misc/vmw_vmci/vmci_event.c|  371 +++
 drivers/misc/vmw_vmci/vmci_event.h|   25
 drivers/misc/vmw_vmci/vmci_guest.c|  765 ++
 drivers/misc/vmw_vmci/vmci_handle_array.c |  162 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   46
 drivers/misc/vmw_vmci/vmci_host.c | 1046 +
 drivers/misc/vmw_vmci/vmci_queue_pair.c   | 3556 +
 drivers/misc/vmw_vmci/vmci_queue_pair.h   |  191 ++
 drivers/misc/vmw_vmci/vmci_resource.c |  237 ++
 drivers

[PATCH 6/6] VSOCK: header and config files.

2012-10-15 Thread George Zhang
VSOCK header files, Makefiles and Kconfig systems for Linux VSocket module.


Signed-off-by: George Zhang 
---
 net/Kconfig |1 
 net/Makefile|1 
 net/vmw_vsock/Kconfig   |   14 +
 net/vmw_vsock/Makefile  |8 
 net/vmw_vsock/notify_qstate.c   |  670 +++
 net/vmw_vsock/vmci_sockets.h|  517 +++
 net/vmw_vsock/vmci_sockets_packet.h |  107 ++
 net/vmw_vsock/vsock_common.h|  130 +++
 net/vmw_vsock/vsock_packet.h|  131 +++
 net/vmw_vsock/vsock_version.h   |   29 ++
 10 files changed, 1608 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

diff --git a/net/Kconfig b/net/Kconfig
index 245831b..75b8d5e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -216,6 +216,7 @@ source "net/dcb/Kconfig"
 source "net/dns_resolver/Kconfig"
 source "net/batman-adv/Kconfig"
 source "net/openvswitch/Kconfig"
+source "net/vmw_vsock/Kconfig"
 
 config RPS
boolean
diff --git a/net/Makefile b/net/Makefile
index 4f4ee08..cae59f4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_CEPH_LIB)+= ceph/
 obj-$(CONFIG_BATMAN_ADV)   += batman-adv/
 obj-$(CONFIG_NFC)  += nfc/
 obj-$(CONFIG_OPENVSWITCH)  += openvswitch/
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock/
diff --git a/net/vmw_vsock/Kconfig b/net/vmw_vsock/Kconfig
new file mode 100644
index 000..95e2568
--- /dev/null
+++ b/net/vmw_vsock/Kconfig
@@ -0,0 +1,14 @@
+#
+# Vsock protocol
+#
+
+config VMWARE_VSOCK
+   tristate "Virtual Socket protocol"
+   depends on VMWARE_VMCI
+   help
+ Virtual Socket Protocol is a socket protocol similar to TCP/IP
+ allowing comunication between Virtual Machines and VMware
+ hypervisor.
+
+ To compile this driver as a module, choose M here: the module
+ will be called vsock. If unsure, say N.
diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile
new file mode 100644
index 000..8cb1e1c
--- /dev/null
+++ b/net/vmw_vsock/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_VMWARE_VSOCK) += vmw_vsock.o
+ccflags-y += -I$(src)/shared
+vmw_vsock-y += af_vsock.o
+vmw_vsock-y += notify.o
+vmw_vsock-y += notify_qstate.o
+vmw_vsock-y += stats.o
+vmw_vsock-y += util.o
+vmw_vsock-y += vsock_addr.o
diff --git a/net/vmw_vsock/notify_qstate.c b/net/vmw_vsock/notify_qstate.c
new file mode 100644
index 000..fafb76c
--- /dev/null
+++ b/net/vmw_vsock/notify_qstate.c
@@ -0,0 +1,670 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * notifyQState.c --
+ *
+ * Linux control notifications based on Queuepair state for the VMCI Stream
+ * Sockets protocol.
+ */
+
+#include 
+
+#include 
+
+#include   /* for NULL */
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) \
+   (vsk)->notify.pkt_q_state.field_name
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk)
+{
+   bool retval;
+   u64 notify_limit;
+
+   if (!PKT_FIELD(vsk, peer_waiting_write))
+   return false;
+
+   /*
+* When the sender blocks, we take that as a sign that the sender is
+* faster than the receiver. To reduce the transmit rate of the sender,
+* we delay the sending of the read notification by decreasing the
+* write_notify_window. The notification is delayed until the number of
+* bytes used in the queue drops below the write_notify_window.
+*/
+
+   if (!PKT_FIELD(vsk, peer_waiting_write_detected)) {
+   PKT_FIELD(vsk, peer_waiting_write_detected) = true;
+   if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) {
+

[PATCH 5/6] VSOCK: utility functions.

2012-10-15 Thread George Zhang
VSOCK utility functions for Linux VSocket module.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/util.c |  694 ++
 net/vmw_vsock/util.h |  331 
 2 files changed, 1025 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h

diff --git a/net/vmw_vsock/util.c b/net/vmw_vsock/util.c
new file mode 100644
index 000..036ca4e
--- /dev/null
+++ b/net/vmw_vsock/util.c
@@ -0,0 +1,694 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+/*
+ * util.c --
+ *
+ * Utility functions for Linux VSocket module.
+ */
+
+#include 
+#include 
+#include 
+#include   /* for NULL */
+#include 
+
+#include "af_vsock.h"
+#include "util.h"
+
+struct list_head vsock_bind_table[VSOCK_HASH_SIZE + 1];
+struct list_head vsock_connected_table[VSOCK_HASH_SIZE];
+
+DEFINE_SPINLOCK(vsock_table_lock);
+
+/*
+ *
+ * vsock_vmci_log_pkt --
+ *
+ * Logs the provided packet.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_vmci_log_pkt(char const *function, u32 line, vsock_packet *pkt)
+{
+   char buf[256];
+   char *cur = buf;
+   int left = sizeof buf;
+   int written = 0;
+   char *type_strings[] = {
+   [VSOCK_PACKET_TYPE_INVALID] = "INVALID",
+   [VSOCK_PACKET_TYPE_REQUEST] = "REQUEST",
+   [VSOCK_PACKET_TYPE_NEGOTIATE] = "NEGOTIATE",
+   [VSOCK_PACKET_TYPE_OFFER] = "OFFER",
+   [VSOCK_PACKET_TYPE_ATTACH] = "ATTACH",
+   [VSOCK_PACKET_TYPE_WROTE] = "WROTE",
+   [VSOCK_PACKET_TYPE_READ] = "READ",
+   [VSOCK_PACKET_TYPE_RST] = "RST",
+   [VSOCK_PACKET_TYPE_SHUTDOWN] = "SHUTDOWN",
+   [VSOCK_PACKET_TYPE_WAITING_WRITE] = "WAITING_WRITE",
+   [VSOCK_PACKET_TYPE_WAITING_READ] = "WAITING_READ",
+   [VSOCK_PACKET_TYPE_REQUEST2] = "REQUEST2",
+   [VSOCK_PACKET_TYPE_NEGOTIATE2] = "NEGOTIATE2",
+   };
+
+   written = snprintf(cur, left, "PKT: %u:%u -> %u:%u",
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.src),
+  pkt->src_port,
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->dg.dst),
+  pkt->dst_port);
+   if (written >= left)
+   goto error;
+
+   left -= written;
+   cur += written;
+
+   switch (pkt->type) {
+   case VSOCK_PACKET_TYPE_REQUEST:
+   case VSOCK_PACKET_TYPE_NEGOTIATE:
+   written = snprintf(cur, left, ", %s, size = %" FMT64 "u",
+  type_strings[pkt->type], pkt->u.size);
+   break;
+
+   case VSOCK_PACKET_TYPE_OFFER:
+   case VSOCK_PACKET_TYPE_ATTACH:
+   written = snprintf(cur, left, ", %s, handle = %u:%u",
+  type_strings[pkt->type],
+  VMCI_HANDLE_TO_CONTEXT_ID(pkt->u.handle),
+  VMCI_HANDLE_TO_RESOURCE_ID(pkt->u.handle));
+   break;
+
+   case VSOCK_PACKET_TYPE_WROTE:
+   case VSOCK_PACKET_TYPE_READ:
+   case VSOCK_PACKET_TYPE_RST:
+   written = snprintf(cur, left, ", %s", type_strings[pkt->type]);
+   break;
+   case VSOCK_PACKET_TYPE_SHUTDOWN: {
+   bool recv;
+   bool send;
+
+   recv = pkt->u.mode & RCV_SHUTDOWN;
+   send = pkt->u.mode & SEND_SHUTDOWN;
+   written = snprintf(cur, left, ", %s, mode = %c%c",
+  type_strings[pkt->type],
+  recv ? 'R' : ' ', send ? 'S' : ' ');
+   }
+   break;
+
+   case VSOCK_PACKET_TYPE_WAITING_WRITE:
+   case VSOCK_PACKET_TYPE_WAITING_READ:
+   written = snprintf(cur, left, ", %s, generation = %" FMT64 "u, "
+  "offset = %" FMT64 "u",
+  type_strings[pkt->type],
+  pkt->u.wait.generation, pkt->u.wait.offset)

[PATCH 4/6] VSOCK: statistics implementation.

2012-10-15 Thread George Zhang
VSOCK stats for VMCI Stream Sockets protocol.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/stats.c |   37 
 net/vmw_vsock/stats.h |  222 +
 2 files changed, 259 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h

diff --git a/net/vmw_vsock/stats.c b/net/vmw_vsock/stats.c
new file mode 100644
index 000..2d172d5
--- /dev/null
+++ b/net/vmw_vsock/stats.c
@@ -0,0 +1,37 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * stats.c --
+ *
+ * Linux stats for the VMCI Stream Sockets protocol.
+ */
+
+#include 
+
+#include 
+#include   /* for NULL */
+#include 
+
+#include "af_vsock.h"
+#include "stats.h"
+
+#ifdef VSOCK_GATHER_STATISTICS
+u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+atomic64_t vsock_stats_consume_total;
+atomic64_t vsock_stats_produce_total;
+#endif
diff --git a/net/vmw_vsock/stats.h b/net/vmw_vsock/stats.h
new file mode 100644
index 000..ce6ec7e
--- /dev/null
+++ b/net/vmw_vsock/stats.h
@@ -0,0 +1,222 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * stats.h --
+ *
+ * Stats functions for Linux vsock module.
+ */
+
+#ifndef __STATS_H__
+#define __STATS_H__
+
+#include 
+
+#include "vsock_common.h"
+#include "vsock_packet.h"
+
+/*
+ * Define VSOCK_GATHER_STATISTICS to turn on statistics gathering. Currently
+ * this consists of 3 types of stats: 1. The number of control datagram
+ * messages sent. 2. The level of queuepair fullness (in 10% buckets) whenever
+ * data is about to be enqueued or dequeued from the queuepair. 3. The total
+ * number of bytes enqueued/dequeued.
+ */
+
+#ifdef VSOCK_GATHER_STATISTICS
+
+#define VSOCK_NUM_QUEUE_LEVEL_BUCKETS 10
+extern u64 vsock_stats_ctl_pkt_count[VSOCK_PACKET_TYPE_MAX];
+extern u64 vsock_stats_consume_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern u64 vsock_stats_produce_queue_hist[VSOCK_NUM_QUEUE_LEVEL_BUCKETS];
+extern atomic64_t vsock_stats_consume_total;
+extern atomic64_t vsock_stats_produce_total;
+
+#define VSOCK_STATS_STREAM_CONSUME_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->consume_size,\
+   vmci_qpair_consume_buf_ready((vsk)->qpair), \
+   vsock_stats_consume_queue_hist)
+#define VSOCK_STATS_STREAM_PRODUCE_HIST(vsk)   \
+   vsock_vmci_stats_update_queue_bucket_count((vsk)->qpair,\
+   (vsk)->produce_size,\
+   vmci_qpair_produce_buf_ready((vsk)->qpair), \
+   vsock_stats_produce_queue_hist)
+#define VSOCK_STATS_CTLPKT_LOG(pkt_type)   \
+   do {\
+   ++vsock_stats_ctl_pkt_count[pkt_type];  \
+   } while (0)
+#define VSOCK_STATS_STREAM_CONSUME(bytes)  \
+   atomic64_add(&vsock_stats_consume_total, bytes)
+#define VSOCK_STATS_STREAM_PRODUCE(bytes)  \
+   atomic64_add(&vsock_stats_produce_total, bytes)
+#define VSOCK_STATS_CTLPKT_DUMP_ALL() vsock_vmci_stats_ctl_pkt_dump_all()
+#define VSOCK_STATS_HIST_DUMP_ALL()   vsock_vmci_stats_hist_dump_all()
+#define VSOCK_STATS_TOTALS_DUMP_ALL() vsock_vmci_stats_totals_dump_all()
+#define VSOCK_STATS_RESET()   vsock_vmci_stats_reset()
+
+/*
+ *
+ * vsock_vmci_stats_update_queue_bucket_count --
+ *
+ * Given a queue, determine how much data is enqueued and add that to the
+ * specified queue level statistic bucket.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */

[PATCH 3/6] VSOCK: notification implementation.

2012-10-15 Thread George Zhang
VSOCK control notifications for VMCI Stream Sockets protocol.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/notify.c | 1041 
 net/vmw_vsock/notify.h |  130 ++
 2 files changed, 1171 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h

diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c
new file mode 100644
index 000..03a0a1f
--- /dev/null
+++ b/net/vmw_vsock/notify.c
@@ -0,0 +1,1041 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2009-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.
+ */
+
+/*
+ * notify.c --
+ *
+ * Linux control notifications for the VMCI Stream Sockets protocol.
+ */
+
+#include 
+
+#include 
+#include   /* for NULL */
+#include 
+
+#include "notify.h"
+#include "af_vsock.h"
+
+#define PKT_FIELD(vsk, field_name) \
+   (vsk)->notify.pkt.field_name
+
+#define VSOCK_MAX_DGRAM_RESENDS   10
+
+/*
+ *
+ * vsock_vmci_notify_waiting_write --
+ *
+ * Determines if the conditions have been met to notify a waiting writer.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+   bool retval;
+   u64 notify_limit;
+
+   if (!PKT_FIELD(vsk, peer_waiting_write))
+   return false;
+
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   /*
+* When the sender blocks, we take that as a sign that the sender is
+* faster than the receiver. To reduce the transmit rate of the sender,
+* we delay the sending of the read notification by decreasing the
+* write_notify_window. The notification is delayed until the number of
+* bytes used in the queue drops below the write_notify_window.
+*/
+
+   if (!PKT_FIELD(vsk, peer_waiting_write_detected)) {
+   PKT_FIELD(vsk, peer_waiting_write_detected) = true;
+   if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) {
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+   } else {
+   PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE;
+   if (PKT_FIELD(vsk, write_notify_window) <
+   PKT_FIELD(vsk, write_notify_min_window))
+   PKT_FIELD(vsk, write_notify_window) =
+   PKT_FIELD(vsk, write_notify_min_window);
+
+   }
+   }
+   notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window);
+#else
+   notify_limit = 0;
+#endif
+
+   /*
+* For now we ignore the wait information and just see if the free
+* space exceeds the notify limit.  Note that improving this function
+* to be more intelligent will not require a protocol change and will
+* retain compatibility between endpoints with mixed versions of this
+* function.
+*
+* The notify_limit is used to delay notifications in the case where
+* flow control is enabled. Below the test is expressed in terms of
+* free space in the queue: if free_space > ConsumeSize -
+* write_notify_window then notify An alternate way of expressing this
+* is to rewrite the expression to use the data ready in the receive
+* queue: if write_notify_window > bufferReady then notify as
+* free_space == ConsumeSize - bufferReady.
+*/
+   retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit;
+#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
+   if (retval) {
+   /*
+* Once we notify the peer, we reset the detected flag so the
+* next wait will again cause a decrease in the window size.
+*/
+
+   PKT_FIELD(vsk, peer_waiting_write_detected) = false;
+   }
+#endif
+   return retval;
+#else
+   return true;
+#endif
+}
+
+/*
+ *
+ * vsock_vmci_notify_waiting_read --
+ *
+ * Determines if the conditions have been met to notify a waiting reader.
+ *
+ * Results: true if a notification should be sent, false otherwise.
+ *
+ * Side effects: None.
+ */
+
+static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk)
+{
+#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
+

[PATCH 2/6] VSOCK: vsock address implementaion.

2012-10-15 Thread George Zhang
VSOCK linux address code implementation.


Signed-off-by: George Zhang 
---
 net/vmw_vsock/vsock_addr.c |  264 
 net/vmw_vsock/vsock_addr.h |   40 +++
 2 files changed, 304 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h

diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
new file mode 100644
index 000..c93a174
--- /dev/null
+++ b/net/vmw_vsock/vsock_addr.c
@@ -0,0 +1,264 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-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.
+ */
+
+/*
+ * vsockAddr.c --
+ *
+ * VSockets address implementation.
+ */
+
+/*
+ * These includes come before vsockCommon.h to ensure that VMware's ASSERT
+ * macro is used instead of Linux's irda.h definition.
+ */
+#include 
+#include 
+#include   /* for NULL */
+#include 
+
+#include "vsock_common.h"
+
+/*
+ *
+ * vsock_addr_init --
+ *
+ * Initialize the given address with the given context id and port. This will
+ * clear the address, set the correct family, and add the given values.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_addr_init(struct sockaddr_vm *addr, u32 cid, u32 port)
+{
+   memset(addr, 0, sizeof *addr);
+
+   addr->svm_family = AF_VSOCK;
+   addr->svm_cid = cid;
+   addr->svm_port = port;
+
+   BUG_ON(vsock_addr_validate(addr) != 0);
+}
+
+/*
+ *
+ * vsock_addr_validate --
+ *
+ * Try to validate the given address.  The address must not be null and must
+ * have the correct address family.  Any reserved fields must be zero.
+ *
+ * Results: 0 on success, EFAULT if the address is null, EAFNOSUPPORT if the
+ * address is of the wrong family, and EINVAL if the reserved fields are not
+ * zero.
+ *
+ * Side effects: None.
+ */
+
+int vsock_addr_validate(const struct sockaddr_vm *addr)
+{
+   if (!addr)
+   return -EFAULT;
+
+   if (addr->svm_family != AF_VSOCK)
+   return -EAFNOSUPPORT;
+
+   if (addr->svm_zero[0] != 0)
+   return -EINVAL;
+
+   return 0;
+}
+
+/*
+ *
+ * vsock_addr_bound --
+ *
+ * Determines whether the provided address is bound.
+ *
+ * Results: TRUE if the address structure is bound, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_bound(const struct sockaddr_vm *addr)
+{
+   BUG_ON(!addr);
+
+   return addr->svm_port != VMADDR_PORT_ANY;
+}
+
+/*
+ *
+ * vsock_addr_unbind --
+ *
+ * Unbind the given addresss.
+ *
+ * Results: None.
+ *
+ * Side effects: None.
+ */
+
+void vsock_addr_unbind(struct sockaddr_vm *addr)
+{
+   vsock_addr_init(addr, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+}
+
+/*
+ *
+ * vsock_addr_equals_addr --
+ *
+ * Determine if the given addresses are equal.
+ *
+ * Results: TRUE if the addresses are equal, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+   BUG_ON(vsock_addr_validate(other) != 0);
+
+   return addr->svm_cid == other->svm_cid &&
+   addr->svm_port == other->svm_port;
+}
+
+/*
+ *
+ * vsock_addr_equals_addr_any --
+ *
+ * Determine if the given addresses are equal. Will accept either an exact
+ * match or one where the rids match and that either the cids match or are set
+ * to VMADDR_CID_ANY.
+ *
+ * Results: TRUE if the addresses are equal, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
+   const struct sockaddr_vm *other)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+   BUG_ON(vsock_addr_validate(other) != 0);
+
+   return (addr->svm_cid == VMADDR_CID_ANY ||
+   other->svm_cid == VMADDR_CID_ANY ||
+   addr->svm_cid == other->svm_cid) &&
+  addr->svm_port == other->svm_port;
+}
+
+/*
+ *
+ * vsock_addr_equals_handle_port --
+ *
+ * Determines if the given address matches the given handle and port.
+ *
+ * Results: TRUE if the address matches the handle and port, FALSE otherwise.
+ *
+ * Side effects: None.
+ */
+
+bool vsock_addr_equals_handle_port(const struct sockaddr_vm *addr,
+  struct vmci_handle handle, u32 port)
+{
+   BUG_ON(vsock_addr_validate(addr) != 0);
+
+

[PATCH 0/6] VSOCK for Linux upstreaming

2012-10-15 Thread George Zhang

* * *

In an effort to improve the out-of-the-box experience with Linux
kernels for VMware users, VMware is working on readying the Virtual
Machine Communication Interface (vmw_vmci) and VMCI Sockets (VSOCK)
(vmw_vsock) kernel modules for inclusion in the Linux kernel. The
purpose of this post is to acquire feedback on the vmw_vsock kernel
module. The vmw_vmci kernel module has been presented in an early post.


* * *

VMCI Sockets allows virtual machines to communicate with host kernel
modules and the VMware hypervisors. VMCI Sockets kernel module has
dependency on VMCI kernel module. User level applications both in
a virtual machine and on the host can use vmw_vmci through VMCI
Sockets API which facilitates fast and efficient communication
between guest virtual machines and their host. A socket
address family designed to be compatible with UDP and TCP at the
interface level. Today, VMCI and VMCI Sockets are used by the VMware
shared folders (HGFS) and various VMware Tools components inside the
guest for zero-config, network-less access to VMware host services. In
addition to this, VMware's users are using VMCI Sockets for various
applications, where network access of the virtual machine is
restricted or non-existent. Examples of this are VMs communicating
with device proxies for proprietary hardware running as host
applications and automated testing of applications running within
virtual machines.

The VMware VMCI Sockets are similar to other socket types, like
Berkeley UNIX socket interface. The VMCI sockets module supports
both connection-oriented stream sockets like TCP, and connectionless
datagram sockets like UDP. The VSOCK protocol family is defined as
"AF_VSOCK" and the socket operations split for SOCK_DGRAM and
SOCK_STREAM.

For additional information about the use of VMCI and in particular
VMCI Sockets, please refer to the VMCI Socket Programming Guide
available at https://www.vmware.com/support/developer/vmci-sdk/.



---

George Zhang (6):
  VSOCK: vsock protocol implementation.
  VSOCK: vsock address implementaion.
  VSOCK: notification implementation.
  VSOCK: statistics implementation.
  VSOCK: utility functions.
  VSOCK: header and config files.


 net/Kconfig |1 
 net/Makefile|1 
 net/vmw_vsock/Kconfig   |   14 
 net/vmw_vsock/Makefile  |8 
 net/vmw_vsock/af_vsock.c| 4259 +++
 net/vmw_vsock/af_vsock.h|  179 +
 net/vmw_vsock/notify.c  | 1041 +
 net/vmw_vsock/notify.h  |  130 +
 net/vmw_vsock/notify_qstate.c   |  670 ++
 net/vmw_vsock/stats.c   |   37 
 net/vmw_vsock/stats.h   |  222 ++
 net/vmw_vsock/util.c|  694 ++
 net/vmw_vsock/util.h|  331 +++
 net/vmw_vsock/vmci_sockets.h|  517 
 net/vmw_vsock/vmci_sockets_packet.h |  107 +
 net/vmw_vsock/vsock_addr.c  |  264 ++
 net/vmw_vsock/vsock_addr.h  |   40 
 net/vmw_vsock/vsock_common.h|  130 +
 net/vmw_vsock/vsock_packet.h|  131 +
 net/vmw_vsock/vsock_version.h   |   29 
 20 files changed, 8805 insertions(+), 0 deletions(-)
 create mode 100644 net/vmw_vsock/Kconfig
 create mode 100644 net/vmw_vsock/Makefile
 create mode 100644 net/vmw_vsock/af_vsock.c
 create mode 100644 net/vmw_vsock/af_vsock.h
 create mode 100644 net/vmw_vsock/notify.c
 create mode 100644 net/vmw_vsock/notify.h
 create mode 100644 net/vmw_vsock/notify_qstate.c
 create mode 100644 net/vmw_vsock/stats.c
 create mode 100644 net/vmw_vsock/stats.h
 create mode 100644 net/vmw_vsock/util.c
 create mode 100644 net/vmw_vsock/util.h
 create mode 100644 net/vmw_vsock/vmci_sockets.h
 create mode 100644 net/vmw_vsock/vmci_sockets_packet.h
 create mode 100644 net/vmw_vsock/vsock_addr.c
 create mode 100644 net/vmw_vsock/vsock_addr.h
 create mode 100644 net/vmw_vsock/vsock_common.h
 create mode 100644 net/vmw_vsock/vsock_packet.h
 create mode 100644 net/vmw_vsock/vsock_version.h

-- 
Signature
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH 10/10] VMCI: Some header and config files.

2012-10-15 Thread George Zhang
VMCI header config patch adds all the necessary files to enable building of the 
VMCI
module with the Linux Makefiles and Kconfig systems. Also adds the header
files used for building modules against the driver.


Signed-off-by: George Zhang 
---
 drivers/misc/Kconfig|1 
 drivers/misc/Makefile   |2 
 drivers/misc/vmw_vmci/Kconfig   |   16 +
 drivers/misc/vmw_vmci/Makefile  |   41 +
 drivers/misc/vmw_vmci/vmci_common_int.h |   34 +
 include/linux/vmw_vmci_api.h|   89 +++
 include/linux/vmw_vmci_defs.h   |  971 +++
 7 files changed, 1154 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/Kconfig
 create mode 100644 drivers/misc/vmw_vmci/Makefile
 create mode 100644 drivers/misc/vmw_vmci/vmci_common_int.h
 create mode 100644 include/linux/vmw_vmci_api.h
 create mode 100644 include/linux/vmw_vmci_defs.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2661f6e..fe38c7a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -517,4 +517,5 @@ source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
+source "drivers/misc/vmw_vmci/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 456972f..21ed953 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -51,3 +51,5 @@ obj-y += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)+= mei/
+obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
+obj-$(CONFIG_VMWARE_VMCI)  += vmw_vmci/
diff --git a/drivers/misc/vmw_vmci/Kconfig b/drivers/misc/vmw_vmci/Kconfig
new file mode 100644
index 000..55015e7
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Kconfig
@@ -0,0 +1,16 @@
+#
+# VMware VMCI device
+#
+
+config VMWARE_VMCI
+   tristate "VMware VMCI Driver"
+   depends on X86
+   help
+ This is VMware's Virtual Machine Communication Interface.  It enables
+ high-speed communication between host and guest in a virtual
+ environment via the VMCI virtual device.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vmw_vmci.
diff --git a/drivers/misc/vmw_vmci/Makefile b/drivers/misc/vmw_vmci/Makefile
new file mode 100644
index 000..bcc3b6c
--- /dev/null
+++ b/drivers/misc/vmw_vmci/Makefile
@@ -0,0 +1,41 @@
+
+#
+# Linux driver for VMware's VMCI device.
+#
+# Copyright (C) 2007-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 of the License 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, GOOD TITLE or
+# NON INFRINGEMENT.  See the GNU General Public License for more
+# details.
+#
+# Maintained by: Andrew Stiegmann 
+#
+
+
+#
+# Makefile for the VMware VMCI
+#
+
+obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci.o
+
+vmw_vmci-y += vmci_context.o
+vmw_vmci-y += vmci_datagram.o
+vmw_vmci-y += vmci_doorbell.o
+vmw_vmci-y += vmci_driver.o
+vmw_vmci-y += vmci_event.o
+vmw_vmci-y += vmci_handle_array.o
+vmw_vmci-y += vmci_queue_pair.o
+vmw_vmci-y += vmci_resource.o
+vmw_vmci-y += vmci_route.o
+
+vmci:
+   $(MAKE) -C ../../.. SUBDIRS=$$PWD CONFIG_VMWARE_VMCI=m modules
+
+clean:
+   $(MAKE) -C ../../.. SUBDIRS=$$PWD CONFIG_VMWARE_VMCI=m clean
diff --git a/drivers/misc/vmw_vmci/vmci_common_int.h 
b/drivers/misc/vmw_vmci/vmci_common_int.h
new file mode 100644
index 000..77667ec
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_common_int.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef _VMCI_COMMONINT_H_
+#define _VMCI_COMMONINT_H_
+
+#include 
+
+#define ASSERT(cond) BUG_ON(!(cond))
+
+#define PCI_VENDOR_ID_VMWARE   0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMCI  0x0740
+#define VMC

[PATCH 09/10] VMCI: routing implementation.

2012-10-15 Thread George Zhang
VMCI routing code is responsible for routing between various hosts/guests
as well as routing in nested scenarios.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_route.c |  237 
 drivers/misc/vmw_vmci/vmci_route.h |   30 +
 2 files changed, 267 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_route.h

diff --git a/drivers/misc/vmw_vmci/vmci_route.c 
b/drivers/misc/vmw_vmci/vmci_route.c
new file mode 100644
index 000..8aa43ee
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_route.c
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+/*
+ * Make a routing decision for the given source and destination handles.
+ * This will try to determine the route using the handles and the available
+ * devices.  Will set the source context if it is invalid.
+ */
+int vmci_route(struct vmci_handle *src,
+  const struct vmci_handle *dst,
+  bool from_guest,
+  enum vmci_route *route)
+{
+   bool has_host_device = vmci_host_code_active();
+   bool has_guest_device = vmci_guest_code_active();
+
+   ASSERT(src);
+   ASSERT(dst);
+   ASSERT(route);
+
+   *route = VMCI_ROUTE_NONE;
+
+   /*
+* "from_guest" is only ever set to true by
+* IOCTL_VMCI_DATAGRAM_SEND (or by the vmkernel equivalent),
+* which comes from the VMX, so we know it is coming from a
+* guest.
+*
+* To avoid inconsistencies, test these once.  We will test
+* them again when we do the actual send to ensure that we do
+* not touch a non-existent device.
+*/
+
+   /* Must have a valid destination context. */
+   if (VMCI_INVALID_ID == dst->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /* Anywhere to hypervisor. */
+   if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
+
+   /*
+* If this message already came from a guest then we
+* cannot send it to the hypervisor.  It must come
+* from a local client.
+*/
+   if (from_guest)
+   return VMCI_ERROR_DST_UNREACHABLE;
+
+   /*
+* We must be acting as a guest in order to send to
+* the hypervisor.
+*/
+   if (!has_guest_device)
+   return VMCI_ERROR_DEVICE_NOT_FOUND;
+
+   /* And we cannot send if the source is the host context. */
+   if (VMCI_HOST_CONTEXT_ID == src->context)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   /*
+* If the client passed the ANON source handle then
+* respect it (both context and resource are invalid).
+* However, if they passed only an invalid context,
+* then they probably mean ANY, in which case we
+* should set the real context here before passing it
+* down.
+*/
+   if (VMCI_INVALID_ID == src->context &&
+   VMCI_INVALID_ID != src->resource)
+   src->context = vmci_get_context_id();
+
+   /* Send from local client down to the hypervisor. */
+   *route = VMCI_ROUTE_AS_GUEST;
+   return VMCI_SUCCESS;
+   }
+
+   /* Anywhere to local client on host. */
+   if (VMCI_HOST_CONTEXT_ID == dst->context) {
+   /*
+* If it is not from a guest but we are acting as a
+* guest, then we need to send it down to the host.
+* Note that if we are also acting as a host then this
+* will prevent us from sending from local client to
+* local client, but we accept that restriction as a
+* way to remove any ambiguity from the host context.
+*/
+   if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* If the hypervisor is the source, this is
+* host local communication. The hypervisor
+* may se

[PATCH 08/10] VMCI: resource object implementation.

2012-10-15 Thread George Zhang
VMCI resource tracks all used resources within the vmci code.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_resource.c |  237 +
 drivers/misc/vmw_vmci/vmci_resource.h |   59 
 2 files changed, 296 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_resource.h

diff --git a/drivers/misc/vmw_vmci/vmci_resource.c 
b/drivers/misc/vmw_vmci/vmci_resource.c
new file mode 100644
index 000..a2f5fd0
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_resource.c
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+
+
+#define VMCI_RESOURCE_HASH_BITS 7
+#define VMCI_RESOURCE_HASH_BUCKETS  (1 << VMCI_RESOURCE_HASH_BITS)
+
+struct vmci_hash_table {
+   spinlock_t lock;
+   struct hlist_head entries[VMCI_RESOURCE_HASH_BUCKETS];
+};
+
+static struct vmci_hash_table vmci_resource_table = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_resource_table.lock),
+};
+
+static unsigned int vmci_resource_hash(struct vmci_handle handle)
+{
+   return hash_32(VMCI_HANDLE_TO_RESOURCE_ID(handle),
+  VMCI_RESOURCE_HASH_BITS);
+}
+
+/*
+ * Gets a resource (if one exists) matching given handle from the hash table.
+ */
+static struct vmci_resource *vmci_resource_lookup(struct vmci_handle handle)
+{
+   struct vmci_resource *r, *resource = NULL;
+   struct hlist_node *node;
+   unsigned int idx = vmci_resource_hash(handle);
+
+   BUG_ON(VMCI_HANDLE_EQUAL(handle, VMCI_INVALID_HANDLE));
+
+   rcu_read_lock();
+   hlist_for_each_entry_rcu(r, node,
+&vmci_resource_table.entries[idx], node) {
+   u32 rid = VMCI_HANDLE_TO_RESOURCE_ID(r->handle);
+   u32 cid = VMCI_HANDLE_TO_CONTEXT_ID(r->handle);
+
+   if (rid == VMCI_HANDLE_TO_RESOURCE_ID(handle) &&
+   (cid == VMCI_HANDLE_TO_CONTEXT_ID(handle) ||
+cid == VMCI_INVALID_ID)) {
+   resource = r;
+   break;
+   }
+   }
+   rcu_read_unlock();
+
+   return resource;
+}
+
+/*
+ * Find an unused resource ID and return it. The first
+ * VMCI_RESERVED_RESOURCE_ID_MAX are reserved so we start from
+ * its value + 1.
+ * Returns VMCI resource id on success, VMCI_INVALID_ID on failure.
+ */
+static u32 vmci_resource_find_id(u32 context_id)
+{
+   static u32 resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   u32 old_rid = resource_id;
+   u32 current_rid;
+
+   /*
+* Generate a unique resource ID.  Keep on trying until we wrap around
+* in the RID space.
+*/
+   BUG_ON(old_rid <= VMCI_RESERVED_RESOURCE_ID_MAX);
+
+   do {
+   struct vmci_handle handle;
+
+   current_rid = resource_id;
+   resource_id++;
+   if (unlikely(resource_id == VMCI_INVALID_ID)) {
+   /* Skip the reserved rids. */
+   resource_id = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   }
+
+   handle = vmci_make_handle(context_id, current_rid);
+   if (!vmci_resource_lookup(handle))
+   return current_rid;
+   } while (resource_id != old_rid);
+
+   return VMCI_INVALID_ID;
+}
+
+
+int vmci_resource_add(struct vmci_resource *resource,
+ enum vmci_resource_type resource_type,
+ struct vmci_handle handle)
+
+{
+   unsigned int idx;
+   int result;
+
+   BUG_ON(!resource);
+
+   spin_lock(&vmci_resource_table.lock);
+
+   if (handle.resource == VMCI_INVALID_ID) {
+   handle.resource = vmci_resource_find_id(handle.context);
+   if (handle.resource == VMCI_INVALID_ID) {
+   result = VMCI_ERROR_NO_HANDLE;
+   goto out;
+   }
+   } else if (vmci_resource_lookup(handle)) {
+   result = VMCI_ERROR_ALREADY_EXISTS;
+   goto out;
+   }
+
+   resource->handle = handle;
+   resource->type = resource_type;
+   INIT_HLIST_NODE(&resource->node);
+   kref_init(&resource->kref);
+   init

[PATCH 06/10] VMCI: handle array implementation.

2012-10-15 Thread George Zhang
VMCI handle code adds support for dynamic arrays that will grow if they need to.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_handle_array.c |  162 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   46 
 2 files changed, 208 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_handle_array.h

diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c 
b/drivers/misc/vmw_vmci/vmci_handle_array.c
new file mode 100644
index 000..c7db831
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_handle_array.c
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+#include 
+#include "vmci_handle_array.h"
+
+static size_t handle_arr_calc_size(size_t capacity)
+{
+   return sizeof(struct vmci_handle_arr) +
+   capacity * sizeof(struct vmci_handle);
+}
+
+struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity)
+{
+   struct vmci_handle_arr *array;
+
+   if (capacity == 0)
+   capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
+
+   array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC);
+   if (!array)
+   return NULL;
+
+   array->capacity = capacity;
+   array->size = 0;
+
+   return array;
+}
+
+void vmci_handle_arr_destroy(struct vmci_handle_arr *array)
+{
+   kfree(array);
+}
+
+void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr,
+ struct vmci_handle handle)
+{
+   struct vmci_handle_arr *array;
+
+   BUG_ON(!array_ptr || !*array_ptr);
+   array = *array_ptr;
+
+   if (unlikely(array->size >= array->capacity)) {
+   /* reallocate. */
+   struct vmci_handle_arr *new_array;
+   size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT;
+   size_t new_size = handle_arr_calc_size(new_capacity);
+
+   new_array = krealloc(array, new_size, GFP_ATOMIC);
+   if (!new_array)
+   return;
+
+   new_array->capacity = new_capacity;
+   *array_ptr = array = new_array;
+   }
+
+   array->entries[array->size] = handle;
+   array->size++;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
+ */
+struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array,
+   struct vmci_handle entry_handle)
+{
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+   size_t i;
+
+   BUG_ON(!array);
+
+   for (i = 0; i < array->size; i++) {
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle)) {
+   handle = array->entries[i];
+   array->size--;
+   array->entries[i] = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   break;
+   }
+   }
+
+   return handle;
+}
+
+/*
+ * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
+ */
+struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array)
+{
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+
+   BUG_ON(!array);
+
+   if (array->size) {
+   array->size--;
+   handle = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   }
+
+   return handle;
+}
+
+/*
+ * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
+ */
+struct vmci_handle
+vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index)
+{
+   BUG_ON(!array);
+
+   if (unlikely(index >= array->size))
+   return VMCI_INVALID_HANDLE;
+
+   return array->entries[index];
+}
+
+size_t vmci_handle_arr_get_size(const struct vmci_handle_arr *array)
+{
+   BUG_ON(!array);
+
+   return array->size;
+}
+
+bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array,
+  struct vmci_handle entry_handle)
+{
+   size_t i;
+
+   BUG_ON(!array);
+
+   for (i = 0; i < array->size; i++)
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entry_handle))
+   return true;
+
+   return false;
+}
+
+/*
+ * NULL if the array 

[PATCH 05/10] VMCI: event handling implementation.

2012-10-15 Thread George Zhang
VMCI event code that manages event handlers and handles callbacks when specific 
events fire.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_event.c |  415 
 drivers/misc/vmw_vmci/vmci_event.h |   25 ++
 2 files changed, 440 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_event.h

diff --git a/drivers/misc/vmw_vmci/vmci_event.c 
b/drivers/misc/vmw_vmci/vmci_event.c
new file mode 100644
index 000..977550d
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_event.c
@@ -0,0 +1,415 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+#define EVENT_MAGIC 0xEABE
+#define VMCI_EVENT_MAX_ATTEMPTS 10
+
+struct vmci_subscription {
+   u32 id;
+   u32 event;
+   struct kref kref;
+   struct completion done; /* unregistered, ready to be freed */
+   vmci_event_cb callback;
+   void *callback_data;
+   struct list_head node;  /* on one of subscriber lists */
+   bool run_delayed;
+};
+
+static struct list_head subscriber_array[VMCI_EVENT_MAX];
+static DEFINE_MUTEX(subscriber_mutex);
+
+struct delayed_event_info {
+   struct work_struct work;
+   struct vmci_subscription *sub;
+   u8 event_payload[sizeof(struct vmci_event_data_max)];
+};
+
+struct event_ref {
+   struct vmci_subscription *sub;
+   struct list_head list_item;
+};
+
+int __init vmci_event_init(void)
+{
+   int i;
+
+   for (i = 0; i < VMCI_EVENT_MAX; i++)
+   INIT_LIST_HEAD(&subscriber_array[i]);
+
+   return VMCI_SUCCESS;
+}
+
+void vmci_event_exit(void)
+{
+   int e;
+
+   /* We free all memory at exit. */
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur, *p2;
+   list_for_each_entry_safe(cur, p2, &subscriber_array[e], node) {
+
+   /*
+* We should never get here because all events
+* should have been unregistered before we try
+* to unload the driver module.  Also, delayed
+* callbacks could still be firing so this
+* cleanup would not be safe.  Still it is
+* better to free the memory than not ... so
+* we leave this code in just in case
+*/
+   pr_warn("Unexpected free events occuring.");
+   kfree(cur);
+   }
+   }
+
+}
+
+/*
+ * Gets a reference to the given VMCISubscription.
+ */
+static struct vmci_subscription *event_get(struct vmci_subscription *entry)
+{
+   kref_get(&entry->kref);
+
+   return entry;
+}
+
+static void event_signal_destroy(struct kref *kref)
+{
+   struct vmci_subscription *entry =
+   container_of(kref, struct vmci_subscription, kref);
+
+   complete(&entry->done);
+}
+
+/*
+ * Releases the given VMCISubscription.
+ * Fires the destroy event if the reference count has gone to zero.
+ */
+static void event_release(struct vmci_subscription *entry)
+{
+   kref_put(&entry->kref, event_signal_destroy);
+}
+
+/*
+ * Find entry. Assumes lock is held.
+ */
+static struct vmci_subscription *event_find(u32 sub_id)
+{
+   int e;
+
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur;
+   list_for_each_entry(cur, &subscriber_array[e], node) {
+   if (cur->id == sub_id)
+   return cur;
+   }
+   }
+   return NULL;
+}
+
+/*
+ * Calls the specified callback in a delayed context.
+ */
+static void event_delayed_dispatch(struct work_struct *work)
+{
+   struct delayed_event_info *event_info =
+   container_of(work, struct delayed_event_info, work);
+   struct vmci_subscription *sub = event_info->sub;
+   struct vmci_event_data *ed;
+
+   BUG_ON(!sub);
+
+   ed = (struct vmci_event_data *)event_info->event_payload;
+
+   sub->callback(sub->id, ed, sub->callback_data);
+   event_release(sub);
+
+   kfree(event_info);
+}
+
+/*
+ * Actually delive

[PATCH 03/10] VMCI: doorbell implementation.

2012-10-15 Thread George Zhang
VMCI doorbell code allows for notifcations between host and guest.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_doorbell.c |  674 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   53 +++
 2 files changed, 727 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_doorbell.h

diff --git a/drivers/misc/vmw_vmci/vmci_doorbell.c 
b/drivers/misc/vmw_vmci/vmci_doorbell.c
new file mode 100644
index 000..0a8a6e5
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -0,0 +1,674 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+#include "vmci_route.h"
+
+
+#define VMCI_DOORBELL_INDEX_BITS   6
+#define VMCI_DOORBELL_INDEX_TABLE_SIZE (1 << VMCI_DOORBELL_INDEX_BITS)
+#define VMCI_DOORBELL_HASH(_idx)   hash_32(_idx, VMCI_DOORBELL_INDEX_BITS)
+
+/*
+ * DoorbellEntry describes the a doorbell notification handle allocated by the
+ * host.
+ */
+struct dbell_entry {
+   struct vmci_resource resource;
+   struct hlist_node node;
+   struct work_struct work;
+   vmci_callback notify_cb;
+   void *client_data;
+   u32 idx;
+   u32 priv_flags;
+   bool run_delayed;
+   atomic_t active;/* Only used by guest personality */
+};
+
+/* The VMCI index table keeps track of currently registered doorbells. */
+struct dbell_index_table {
+   spinlock_t lock;/* Index table lock */
+   struct hlist_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
+};
+
+static struct dbell_index_table vmci_doorbell_it = {
+   .lock = __SPIN_LOCK_UNLOCKED(vmci_doorbell_it.lock),
+};
+
+/*
+ * The max_notify_idx is one larger than the currently known bitmap index in
+ * use, and is used to determine how much of the bitmap needs to be scanned.
+ */
+static u32 max_notify_idx;
+
+/*
+ * The notify_idx_count is used for determining whether there are free entries
+ * within the bitmap (if notify_idx_count + 1 < max_notify_idx).
+ */
+static u32 notify_idx_count;
+
+/*
+ * The last_notify_idx_reserved is used to track the last index handed out - in
+ * the case where multiple handles share a notification index, we hand out
+ * indexes round robin based on last_notify_idx_reserved.
+ */
+static u32 last_notify_idx_reserved;
+
+/* This is a one entry cache used to by the index allocation. */
+static u32 last_notify_idx_released = PAGE_SIZE;
+
+
+/*
+ * Utility function that retrieves the privilege flags associated
+ * with a given doorbell handle. For guest endpoints, the
+ * privileges are determined by the context ID, but for host
+ * endpoints privileges are associated with the complete
+ * handle. Hypervisor endpoints are not yet supported.
+ */
+int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags)
+{
+   if (priv_flags == NULL || handle.context == VMCI_INVALID_ID)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   if (handle.context == VMCI_HOST_CONTEXT_ID) {
+   struct dbell_entry *entry;
+   struct vmci_resource *resource;
+
+   resource = vmci_resource_by_handle(handle,
+  VMCI_RESOURCE_TYPE_DOORBELL);
+   if (!resource)
+   return VMCI_ERROR_NOT_FOUND;
+
+   entry = container_of(resource, struct dbell_entry, resource);
+   *priv_flags = entry->priv_flags;
+   vmci_resource_put(resource);
+   } else if (handle.context == VMCI_HYPERVISOR_CONTEXT_ID) {
+   /*
+* Hypervisor endpoints for notifications are not
+* supported (yet).
+*/
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   *priv_flags = vmci_context_get_priv_flags(handle.context);
+   }
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Find doorbell entry by bitmap index.
+ */
+static struct dbell_entry *dbell_index_table_find(u32 idx)
+{
+   u32 bucket = VMCI_DOORBELL_HASH(idx);
+   struct dbell_entry *dbell;
+   struct hlist_node *node;
+
+   BUG_ON(!vmci_guest_code_active());
+
+ 

[PATCH 01/10] VMCI: context implementation.

2012-10-15 Thread George Zhang
VMCI Context code maintains state for vmci and allows the driver to
communicate with multiple VMs.


Signed-off-by: George Zhang 
---
 drivers/misc/vmw_vmci/vmci_context.c | 1291 ++
 drivers/misc/vmw_vmci/vmci_context.h |  177 +
 2 files changed, 1468 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_context.h

diff --git a/drivers/misc/vmw_vmci/vmci_context.c 
b/drivers/misc/vmw_vmci/vmci_context.c
new file mode 100644
index 000..c552dd3
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_context.c
@@ -0,0 +1,1291 @@
+/*
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_queue_pair.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_context.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+
+/*
+ * List of current VMCI contexts.
+ */
+static struct {
+   struct list_head head;
+   spinlock_t lock; /* Spinlock for context list operations */
+} ctx_list;
+
+static void ctx_signal_notify(struct vmci_ctx *context)
+{
+   if (context->notify)
+   *context->notify = true;
+}
+
+static void ctx_clear_notify(struct vmci_ctx *context)
+{
+   if (context->notify)
+   *context->notify = false;
+}
+
+/*
+ * If nothing requires the attention of the guest, clears both
+ * notify flag and call.
+ */
+static void ctx_clear_notify_call(struct vmci_ctx *context)
+{
+   if (context->pending_datagrams == 0 &&
+   vmci_handle_arr_get_size(context->pending_doorbell_array) == 0)
+   ctx_clear_notify(context);
+}
+
+/*
+ * Sets the context's notify flag iff datagrams are pending for this
+ * context.  Called from vmci_setup_notify().
+ */
+void vmci_ctx_check_signal_notify(struct vmci_ctx *context)
+{
+   ASSERT(context);
+
+   spin_lock(&context->lock);
+   if (context->pending_datagrams)
+   ctx_signal_notify(context);
+   spin_unlock(&context->lock);
+}
+
+int __init vmci_ctx_init(void)
+{
+   INIT_LIST_HEAD(&ctx_list.head);
+   spin_lock_init(&ctx_list.lock);
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Allocates and initializes a VMCI context.
+ */
+int vmci_ctx_init_ctx(u32 cid,
+ u32 priv_flags,
+ uintptr_t event_hnd,
+ int user_version,
+ const struct cred *cred,
+ struct vmci_ctx **out_context)
+{
+   struct vmci_ctx *context;
+   int result;
+
+   if (priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
+   pr_devel("Invalid flag (flags=0x%x) for VMCI context.",
+priv_flags);
+   return VMCI_ERROR_INVALID_ARGS;
+   }
+
+   if (user_version == 0)
+   return VMCI_ERROR_INVALID_ARGS;
+
+   context = kzalloc(sizeof(*context), GFP_KERNEL);
+   if (context == NULL) {
+   pr_warn("Failed to allocate memory for VMCI context.");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   INIT_LIST_HEAD(&context->list_item);
+   INIT_LIST_HEAD(&context->datagram_queue);
+
+   context->user_version = user_version;
+
+   context->queue_pair_array = vmci_handle_arr_create(0);
+   if (!context->queue_pair_array) {
+   result = VMCI_ERROR_NO_MEM;
+   goto error;
+   }
+
+   context->doorbell_array = vmci_handle_arr_create(0);
+   if (!context->doorbell_array) {
+   result = VMCI_ERROR_NO_MEM;
+   goto error;
+   }
+
+   context->pending_doorbell_array = vmci_handle_arr_create(0);
+   if (!context->pending_doorbell_array) {
+   result = VMCI_ERROR_NO_MEM;
+   goto error;
+   }
+
+   INIT_LIST_HEAD(&context->notifier_list);
+
+   spin_lock_init(&context->lock);
+
+   kref_init(&context->kref);
+
+   /* Inititialize host-specific VMCI context. */
+   init_waitqueue_head(&context->host_context.wait_queue);
+
+   context->priv_flags = priv_flags;
+
+   if (cred)
+   context->cred = get_cred(cred);
+
+   context->

  1   2   >