Re: [vmw_vmci 11/11] Apply the header code to make VMCI build

2012-07-27 Thread Andrew Stiegmann


- Original Message -
> From: "Sam Ravnborg" 
> To: "Andrew Stiegmann" 
> Cc: linux-kernel@vger.kernel.org, virtualizat...@lists.linux-foundation.org, 
> pv-driv...@vmware.com,
> vm-crosst...@vmware.com, csch...@vmware.com, gre...@linuxfoundation.org
> Sent: Friday, July 27, 2012 12:53:20 PM
> Subject: Re: [vmw_vmci 11/11] Apply the header code to make VMCI build
> 
> > > > +
> > > > +#define CAN_BLOCK(_f) (!((_f) & VMCI_QPFLAG_NONBLOCK))
> > > > +#define QP_PINNED(_f) ((_f) & VMCI_QPFLAG_PINNED)
> > > 
> > > Looks like poor obscufation.
> > > Use a statis inline function if you need a helper for this.
> > 
> > These definitions are intended more as a helper to make reading the
> > code easier.  IMHO ts a lot easier to read
> > 
> > if (CAN_BLOCK(flags))
> > 
> > compared to
> > 
> > if (!(flags & VMCI_QPFLAG_NONBLOCK))
> > 
> > Wouldn't you agree?  I'm not sure something this simple warrants a
> > static inline
> > function but I don't see any harm in converting it over to that.
> 
> I would put it the other way around. I cannot see that such simple
> stuff warrants a #define.
> A static inline is (almost) always preferable to hide code in a
> macro.
> 
> For once you get better type-checks.
> And semantics are also much simpler. With a macro you can do so many
> silly things.

Fair enough.  I'll make them into static inline functions.

>   Sam
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [vmw_vmci 11/11] Apply the header code to make VMCI build

2012-07-27 Thread Andrew Stiegmann


- Original Message -
> From: "Greg KH" 
> To: "Andrew Stiegmann" 
> Cc: "Sam Ravnborg" , linux-kernel@vger.kernel.org, 
> virtualizat...@lists.linux-foundation.org,
> pv-driv...@vmware.com, vm-crosst...@vmware.com, csch...@vmware.com
> Sent: Friday, July 27, 2012 11:16:39 AM
> Subject: Re: [vmw_vmci 11/11] Apply the header code to make VMCI build
> 
> On Fri, Jul 27, 2012 at 10:20:43AM -0700, Andrew Stiegmann wrote:
> > > The kernel style is to use lower_case for everything.
> > > So this would become:
> > > 
> > > vmci_device_get()
> > > 
> > > This is obviously a very general comment and applies everywhere.
> > 
> > I wish I could lower case these symbols but VMCI has already
> > existed
> > outside the mainline Linux tree for some time now and changing
> > these
> > exported symbols would mean that other drivers that depend on VMCI
> > (vSock, vmhgfs) would need to change as well.   One thought that
> > did
> > come to mind was exporting both VMCI_Device_Get and vmci_device_get
> > but that would likely just confuse people.  So in short I have made
> > function names lower case where possible, but exported symbols
> > could
> > not be changed.
> 
> Not true at all.  You want those drivers to be merged as well, right?
> So they will need to have their functions changed, and their code as
> well.

As previously mentioned VMware is working on upstreaming our vSock driver (one 
of a few drivers that uses vmw_vmci).  However there are no plans to upstream 
the other drivers that depend on vmw_vmci.  Because of this these symbols can 
not change.

> Just wait until we get to the "change your functionality around"
> requests, those will require those drivers to change.  Right now we
> are
> at the "silly and obvious things you did wrong" stage of the review
> process :)
>
> So please fix these, and also, post these drivers as well, so we can
> see
> how they interact with the core code.
> 
> Actually, if you are going to need lots of refactoring for these
> drivers, and the core, I would recommend putting this all in the
> staging
> tree, to allow that to happen over time.  That would ensure that your
> users keep having working systems, and let you modify the interfaces
> better and easier, than having to keep it all out-of-tree.
> 
> What do you think?

We will discuss this internally and let you know.
 
> greg k-h
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [vmw_vmci 11/11] Apply the header code to make VMCI build

2012-07-27 Thread Andrew Stiegmann
Hi Sam,

- Original Message -
> From: "Sam Ravnborg" 
> To: "Andrew Stiegmann (stieg)" 
> Cc: linux-kernel@vger.kernel.org, virtualizat...@lists.linux-foundation.org, 
> pv-driv...@vmware.com,
> vm-crosst...@vmware.com, csch...@vmware.com, gre...@linuxfoundation.org
> Sent: Friday, July 27, 2012 3:34:55 AM
> Subject: Re: [vmw_vmci 11/11] Apply the header code to make VMCI build
> 
> Hi Andrew.
> 
> A few things noted in the following..
> 
> > 
> > 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..af9e413 100644
> > --- a/drivers/misc/Makefile
> > +++ b/drivers/misc/Makefile
> > @@ -51,3 +51,4 @@ obj-y += carma/
> >  obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
> >  obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
> >  obj-$(CONFIG_INTEL_MEI)+= mei/
> > +obj-y  += vmw_vmci/
> 
> Please use obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
> 
> like we do in the other cases. This prevents us from visiting the
> directory
> when this feature is not enabled.

Ok.

> > +++ 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.
> > +#
> > +# You should have received a copy of the GNU General Public
> > License
> > +# along with this program; if not, write to the Free Software
> > +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> > 02110-1301 USA.
> > +#
> > +# The full GNU General Public License is included in this
> > distribution in
> > +# the file called "COPYING".
> > +#
> > +# Maintained by: Andrew Stiegmann 
> > +#
> > +
> Lot's of boilerplate noise for such a simple file...

I removed the section containing FSF address and section below it as well per 
Greg KH's request.

> > +
> > +#
> > +# Makefile for the VMware VMCI
> > +#
> > +
> > +obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci.o
> > +
> > +vmw_vmci-objs += vmci_context.o
> > +vmw_vmci-objs += vmci_datagram.o
> > +vmw_vmci-objs += vmci_doorbell.o
> > +vmw_vmci-objs += vmci_driver.o
> > +vmw_vmci-objs += vmci_event.o
> > +vmw_vmci-objs += vmci_handle_array.o
> > +vmw_vmci-objs += vmci_hash_table.o
> > +vmw_vmci-objs += vmci_queue_pair.o
> > +vmw_vmci-objs += vmci_resource.o
> > +vmw_vmci-objs += vmci_route.o
> 
> please use:
> vmw_vmci-y += vmci_context.o
> vmw_vmci-y += vmci_datagram.o
> vmw_vmci-y += vmci_doorbell.o
> 
> This is recommended these days and allows you to enable/disable
> single files later using a config option.

Ok.
 
> > diff --git a/drivers/misc/vmw_vmci/vmci_common_int.h
> > b/drivers/misc/vmw_vmci/vmci_common_int.h
> > +
> > +#ifndef _VMCI_COMMONINT_H_
> > +#define _VMCI_COMMONINT_H_
> > +
> > +#include 
> > +#include 
> 
> Use inverse chrismas tree here.
> Longer include lines first, and soret alphabetically when
> lines are of the same length.
> This applies likely in many cases.
> 
> > +#include "vmci_handle_array.h"
> > +
> > +#define ASSERT(cond) BUG_ON(!(cond))
> > +
> > +#define CAN_BLOCK(_f) (!((_f) & VMCI_QPFLAG_NONBLOCK))
> > +#

Re: [vmw_vmci 07/11] Apply VMCI hash table

2012-07-26 Thread Andrew Stiegmann
Must have missed it.  Will look into it.

- Original Message -
> From: "Greg KH" 
> To: "Andrew Stiegmann (stieg)" 
> Cc: linux-kernel@vger.kernel.org, virtualizat...@lists.linux-foundation.org, 
> pv-driv...@vmware.com,
> vm-crosst...@vmware.com, csch...@vmware.com
> Sent: Thursday, July 26, 2012 4:49:54 PM
> Subject: Re: [vmw_vmci 07/11] Apply VMCI hash table
> 
> On Thu, Jul 26, 2012 at 04:39:36PM -0700, Andrew Stiegmann (stieg)
> wrote:
> > Implements a hash table for VMCI's use.
> 
> What's wrong with the in-kernel hash table(s)?
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [vmw_vmci 01/11] Apply VMCI context code

2012-07-26 Thread Andrew Stiegmann
Removed.  Thanks.

- Original Message -
> From: "Greg KH" 
> To: "Andrew Stiegmann (stieg)" 
> Cc: linux-kernel@vger.kernel.org, virtualizat...@lists.linux-foundation.org, 
> pv-driv...@vmware.com,
> vm-crosst...@vmware.com, csch...@vmware.com
> Sent: Thursday, July 26, 2012 4:48:50 PM
> Subject: Re: [vmw_vmci 01/11] Apply VMCI context code
> 
> On Thu, Jul 26, 2012 at 04:39:30PM -0700, Andrew Stiegmann (stieg)
> wrote:
> > Context code maintains state for vmci and allows the driver
> > to communicate with multiple VMs.
> > 
> > Signed-off-by: Andrew Stiegmann (stieg) 
> 
> One tiny nit:
> 
> > diff --git a/drivers/misc/vmw_vmci/vmci_context.c
> > b/drivers/misc/vmw_vmci/vmci_context.c
> > new file mode 100644
> > index 000..46faf10
> > --- /dev/null
> > +++ b/drivers/misc/vmw_vmci/vmci_context.c
> > @@ -0,0 +1,1269 @@
> > +/*
> > + * VMware VMCI Driver
> > + *
> > + * Copyright (C) 2012 VMware, Inc. All rights reserved.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > modify it
> > + * under the terms of the GNU General Public License as published
> > by the
> > + * Free Software Foundation version 2 and no later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > but
> > + * WITHOUT ANY WARRANTY; without even the implied warranty of
> > MERCHANTABILITY
> > + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
> > Public License
> > + * for more details.
> > + *
> > + * You should have received a copy of the GNU General Public
> > License along
> > + * with this program; if not, write to the Free Software
> > Foundation, Inc.,
> > + * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
> 
> Are you prepared to track the office movements of the FSF for the
> next
> 40 years to keep this up to date?  If not, please don't include it,
> it's
> not needed at all.
> 
> greg k-h
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[vmw_vmci 11/11] Apply the header code to make VMCI build

2012-07-26 Thread Andrew Stiegmann (stieg)
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: Andrew Stiegmann (stieg) 
---
 drivers/misc/Kconfig|1 +
 drivers/misc/Makefile   |1 +
 drivers/misc/vmw_vmci/Kconfig   |   16 +
 drivers/misc/vmw_vmci/Makefile  |   43 ++
 drivers/misc/vmw_vmci/vmci_common_int.h |   58 ++
 include/linux/vmw_vmci_api.h|   89 +++
 include/linux/vmw_vmci_defs.h   |  921 +++
 7 files changed, 1129 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..af9e413 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -51,3 +51,4 @@ obj-y += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)+= mei/
+obj-y  += 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..19755fb
--- /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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Maintained by: Andrew Stiegmann 
+#
+
+
+#
+# Makefile for the VMware VMCI
+#
+
+obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci.o
+
+vmw_vmci-objs += vmci_context.o
+vmw_vmci-objs += vmci_datagram.o
+vmw_vmci-objs += vmci_doorbell.o
+vmw_vmci-objs += vmci_driver.o
+vmw_vmci-objs += vmci_event.o
+vmw_vmci-objs += vmci_handle_array.o
+vmw_vmci-objs += vmci_hash_table.o
+vmw_vmci-objs += vmci_queue_pair.o
+vmw_vmci-objs += vmci_resource.o
+vmw_vmci-objs += 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..6e82610
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_common_int.h
@@ -0,0 +1,58 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of 

[vmw_vmci 10/11] Apply vmci routing code

2012-07-26 Thread Andrew Stiegmann (stieg)
This code is responsible for routing between various hosts/guests as
well as routing in nested scenarios.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_route.c |  241 
 drivers/misc/vmw_vmci/vmci_route.h |   34 +
 2 files changed, 275 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..b9c301d
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_route.c
@@ -0,0 +1,241 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#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 fromGuest,
+  enum vmci_route *route)
+{
+   bool hasHostDevice = vmci_host_code_active();
+   bool hasGuestDevice = vmci_guest_code_active();
+
+   ASSERT(src);
+   ASSERT(dst);
+   ASSERT(route);
+
+   *route = VMCI_ROUTE_NONE;
+
+   /*
+* "fromGuest" 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 (fromGuest)
+   return VMCI_ERROR_DST_UNREACHABLE;
+
+   /*
+* We must be acting as a guest in order to send to
+* the hypervisor.
+*/
+   if (!hasGuestDevice)
+   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_GetContextID();
+
+   /* 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_CON

[vmw_vmci 06/11] Apply dynamic array code

2012-07-26 Thread Andrew Stiegmann (stieg)
This code adds support for dynamic arrays that will grow if they
need to.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_handle_array.c |  174 +
 drivers/misc/vmw_vmci/vmci_handle_array.h |   50 
 2 files changed, 224 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..e23e82b
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_handle_array.c
@@ -0,0 +1,174 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_handle_array.h"
+
+static unsigned handle_arr_calc_size(uint32_t c)
+{
+   /*
+* Decrement c because vmci_handle_arr already includes
+* one vmci_handle entry.
+*/
+   return sizeof(struct vmci_handle_arr) +
+   --c  * sizeof(struct vmci_handle);
+}
+
+struct vmci_handle_arr *vmci_handle_arr_create(uint32_t capacity)
+{
+   struct vmci_handle_arr *array;
+   uint32_t arr_size;
+
+   if (capacity == 0)
+   capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE;
+
+   arr_size = handle_arr_calc_size(capacity);
+   array = kmalloc(arr_size, 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 **arrayPtr,
+ struct vmci_handle handle)
+{
+   struct vmci_handle_arr *array;
+
+   ASSERT(arrayPtr && *arrayPtr);
+   array = *arrayPtr;
+
+   if (unlikely(array->size >= array->capacity)) {
+   /* reallocate. */
+   struct vmci_handle_arr *newArray;
+   const uint32_t arraySize =
+   handle_arr_calc_size(array->capacity *
+VMCI_ARR_CAP_MULT);
+
+   newArray = kmalloc(arraySize, GFP_ATOMIC);
+   if (!newArray)
+   return;
+
+   memcpy(newArray, array, arraySize);
+   newArray->capacity *= VMCI_ARR_CAP_MULT;
+   kfree(array);
+   *arrayPtr = newArray;
+   array = newArray;
+   }
+
+   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 entryHandle)
+{
+   uint32_t i;
+   struct vmci_handle handle = VMCI_INVALID_HANDLE;
+
+   ASSERT(array);
+   for (i = 0; i < array->size; i++) {
+   if (VMCI_HANDLE_EQUAL(array->entries[i], entryHandle)) {
+   handle = array->entries[i];
+   array->size--;
+   array->entries[i] = array->entries[array->size];
+   array->entries[array->size] = VMCI_INVALID_HANDLE;
+   break;
+   }
+   }
+
+   return handle;
+}
+
+/*
+ * 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,
+ uint32_t index)
+{
+   ASSERT(array);
+
+   if (unlikely(index >= array->size))
+   return VMCI_INVALID_HANDLE;
+
+

[vmw_vmci 01/11] Apply VMCI context code

2012-07-26 Thread Andrew Stiegmann (stieg)
Context code maintains state for vmci and allows the driver
to communicate with multiple VMs.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_context.c | 1269 ++
 drivers/misc/vmw_vmci/vmci_context.h |  161 +
 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..46faf10
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_context.c
@@ -0,0 +1,1269 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_context.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+#include "vmci_queue_pair.h"
+
+/*
+ * List of current VMCI contexts.
+ */
+static struct {
+   struct list_head head;
+   spinlock_t lock;
+   spinlock_t firingLock;
+} 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->pendingDatagrams == 0 &&
+   vmci_handle_arr_get_size(context->pendingDoorbellArray) == 0)
+   ctx_clear_notify(context);
+}
+
+/*
+ * Check if a context with the specified context ID exists.
+ * Assumes the ctx_list.lock is held.
+ */
+static bool ctx_exists_locked(uint32_t cid)
+{
+   struct vmci_ctx *context;
+
+   list_for_each_entry(context, &ctx_list.head, listItem) {
+   if (context->cid == cid)
+   return true;
+   }
+
+   return false;
+}
+
+/*
+ * 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(&ctx_list.lock);
+   if (context->pendingDatagrams)
+   ctx_signal_notify(context);
+   spin_unlock(&ctx_list.lock);
+}
+
+int __init vmci_ctx_init(void)
+{
+   INIT_LIST_HEAD(&ctx_list.head);
+
+   spin_lock_init(&ctx_list.lock);
+   spin_lock_init(&ctx_list.firingLock);
+
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Allocates and initializes a VMCI context.
+ */
+int vmci_ctx_init_ctx(uint32_t cid,
+ uint32_t privFlags,
+ uintptr_t eventHnd,
+ int userVersion,
+ uid_t *user, struct vmci_ctx **outContext)
+{
+   struct vmci_ctx *context;
+   int result;
+
+   if (privFlags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
+   pr_devel("Invalid flag (flags=0x%x) for VMCI context.",
+privFlags);
+   return VMCI_ERROR_INVALID_ARGS;
+   }
+
+   if (userVersion == 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->listItem);
+   INIT_LIST_HEAD(&context->datagramQueue);
+
+   context->userVersion = userVersion;
+
+   context->queuePairArray = vmci_handle_arr_create(0);
+   if (!context->queuePairArray) {
+   result = VMCI_ERROR_NO_MEM;
+   goto error;
+   }
+
+   context->doorbellArray = vmci_handle_arr_create(0);
+   if (!context->doorbellArray) {
+   result = VMCI_ERROR_NO_MEM;
+   goto error;
+   }
+
+   context->pendingD

[vmw_vmci 09/11] Apply VMCI resource code

2012-07-26 Thread Andrew Stiegmann (stieg)
Tracks all used resources within the vmci code.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_resource.c |  194 +
 drivers/misc/vmw_vmci/vmci_resource.h |   62 +++
 2 files changed, 256 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..03d1f44
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_resource.c
@@ -0,0 +1,194 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_hash_table.h"
+#include "vmci_resource.h"
+#include "vmci_driver.h"
+
+/* 0 through VMCI_RESERVED_RESOURCE_ID_MAX are reserved. */
+static uint32_t resourceID = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+static spinlock_t resourceIdLock;
+static struct vmci_hash_table *resourceTable;
+
+/*
+ * Initializes the VMCI Resource Access Control API. Creates a hashtable
+ * to hold all resources, and registers vectors and callbacks for
+ * hypercalls.
+ */
+int __init vmci_resource_init(void)
+{
+   spin_lock_init(&resourceIdLock);
+
+   resourceTable = vmci_hash_create(128);
+   if (resourceTable == NULL) {
+   pr_warn("Failed creating a resource hash table.");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   return VMCI_SUCCESS;
+}
+
+void vmci_resource_exit(void)
+{
+   if (resourceTable)
+   vmci_hash_destroy(resourceTable);
+}
+
+/*
+ * Return resource ID. 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.
+ */
+uint32_t vmci_resource_get_id(uint32_t contextID)
+{
+   uint32_t oldRID = resourceID;
+   uint32_t currentRID;
+   bool foundRID = false;
+
+   /*
+* Generate a unique resource ID.  Keep on trying until we wrap around
+* in the RID space.
+*/
+   ASSERT(oldRID > VMCI_RESERVED_RESOURCE_ID_MAX);
+
+   do {
+   struct vmci_handle handle;
+
+   spin_lock(&resourceIdLock);
+   currentRID = resourceID;
+   handle = vmci_make_handle(contextID, currentRID);
+   resourceID++;
+   if (unlikely(resourceID == VMCI_INVALID_ID)) {
+   /* Skip the reserved rids. */
+
+   resourceID = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
+   }
+   spin_unlock(&resourceIdLock);
+   foundRID = !vmci_hash_exists(resourceTable, handle);
+   } while (!foundRID && resourceID != oldRID);
+
+   return (unlikely(!foundRID)) ? VMCI_INVALID_ID : currentRID;
+}
+
+int vmci_resource_add(struct vmci_resource *resource,
+ enum vmci_resource_type resourceType,
+ struct vmci_handle resourceHandle,
+ VMCIResourceFreeCB containerFreeCB,
+ void *containerObject)
+{
+   int result;
+
+   ASSERT(resource);
+
+   if (VMCI_HANDLE_EQUAL(resourceHandle, VMCI_INVALID_HANDLE)) {
+   pr_devel("Invalid argument resource (handle=0x%x:0x%x)",
+resourceHandle.context, resourceHandle.resource);
+   return VMCI_ERROR_INVALID_ARGS;
+   }
+
+   vmci_hash_init_entry(&resource->hashEntry, resourceHandle);
+   resource->type = resourceType;
+   resource->containerFreeCB = containerFreeCB;
+   resource->containerObject = containerObject;
+
+   /* Add resource to hashtable. */
+   result = vmci_hash_add(resourceTable, &resource->hashEntry);
+   if (result != VMCI_SUCCESS) {
+   pr_devel("Failed to add entry to hash table " \
+"(result=%d).", result);
+   return result;
+   }
+
+   return result;
+}
+
+void vmci_resource_remove(struct vmci_handle resourceHandle,
+ enum vmci_resource_type resourceType)
+{
+   st

[vmw_vmci 02/11] Apply VMCI datagram code

2012-07-26 Thread Andrew Stiegmann (stieg)
Implements datagrams to allow data to be sent between host
and guest.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_datagram.c |  586 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   56 
 2 files changed, 642 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..a804f99
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -0,0 +1,586 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_context.h"
+#include "vmci_datagram.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+#include "vmci_hash_table.h"
+#include "vmci_resource.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;
+   uint32_t flags;
+   bool runDelayed;
+   VMCIDatagramRecvCB recvCB;
+   void *clientData;
+   wait_queue_head_t destroyEvent;
+   uint32_t privFlags;
+};
+
+struct delayed_datagram_info {
+   bool inDGHostQueue;
+   struct datagram_entry *entry;
+   struct vmci_dg msg;
+};
+
+static atomic_t delayedDGHostQueueSize;
+
+static void dg_free_cb(void *clientData)
+{
+   struct datagram_entry *entry = (struct datagram_entry *)clientData;
+   ASSERT(entry);
+
+   /*
+* Entry is freed in VMCIDatagram_DestroyHnd, who waits for
+* the signal.
+*/
+   wake_up(&entry->destroyEvent);
+}
+
+static int dg_release_cb(void *clientData)
+{
+   struct datagram_entry *entry = (struct datagram_entry *)clientData;
+   ASSERT(entry);
+   vmci_resource_release(&entry->resource);
+   return 0;
+}
+
+/*
+ * Create a datagram entry given a handle pointer.
+ */
+static int dg_create_handle(uint32_t resourceID,
+   uint32_t flags,
+   uint32_t privFlags,
+   VMCIDatagramRecvCB recvCB,
+   void *clientData,
+   struct vmci_handle *outHandle)
+{
+   int result;
+   uint32_t contextID;
+   struct vmci_handle handle;
+   struct datagram_entry *entry;
+
+   ASSERT(recvCB != NULL);
+   ASSERT(outHandle != NULL);
+   ASSERT(!(privFlags & ~VMCI_PRIVILEGE_ALL_FLAGS));
+
+   if ((flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0) {
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   if ((flags & VMCI_FLAG_ANYCID_DG_HND) != 0) {
+   contextID = VMCI_INVALID_ID;
+   } else {
+   contextID = VMCI_GetContextID();
+   if (contextID == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_RESOURCES;
+   }
+
+   if (resourceID == VMCI_INVALID_ID) {
+   resourceID = vmci_resource_get_id(contextID);
+   if (resourceID == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_HANDLE;
+   }
+
+   handle = vmci_make_handle(contextID, resourceID);
+   }
+
+   entry = kmalloc(sizeof *entry, GFP_KERNEL);
+   if (entry == NULL) {
+   pr_warn("Failed allocating memory for datagram entry.");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   entry->runDelayed = (flags & VMCI_FLAG_DG_DELAYED_CB) ? true : false;
+   entry->flags = flags;
+   entry->recvCB = recvCB;
+   entry->clientData = clientData;
+   init_waitqueue_head(&entry->destroyEvent);
+   entry->privFlags = privFlags;
+
+   /* Make datagram resource live. */
+   result = vmci_resource_add(&entry->resource,
+  VMCI_RESOURCE_TYPE_DATAGRAM,
+

[vmw_vmci 07/11] Apply VMCI hash table

2012-07-26 Thread Andrew Stiegmann (stieg)
Implements a hash table for VMCI's use.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_hash_table.c |  332 +++
 drivers/misc/vmw_vmci/vmci_hash_table.h |   56 +
 2 files changed, 388 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_hash_table.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_hash_table.h

diff --git a/drivers/misc/vmw_vmci/vmci_hash_table.c 
b/drivers/misc/vmw_vmci/vmci_hash_table.c
new file mode 100644
index 000..a7423df
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_hash_table.c
@@ -0,0 +1,332 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include 
+
+#include "vmci_context.h"
+#include "vmci_common_int.h"
+#include "vmci_driver.h"
+#include "vmci_hash_table.h"
+
+#define VMCI_HANDLE_TO_CONTEXT_ID(_handle) ((_handle).context)
+#define VMCI_HANDLE_TO_RESOURCE_ID(_handle) ((_handle).resource)
+#define VMCI_HASHTABLE_HASH(_h, _sz)   \
+   vmci_hash_calc(VMCI_HANDLE_TO_RESOURCE_ID(_h), (_sz))
+
+struct vmci_hash_table *vmci_hash_create(int size)
+{
+   struct vmci_hash_table *table;
+
+   table = kmalloc(sizeof *table, GFP_KERNEL);
+   if (table == NULL)
+   return NULL;
+
+   table->entries = kcalloc(size, sizeof *table->entries, GFP_KERNEL);
+   if (table->entries == NULL) {
+   kfree(table);
+   return NULL;
+   }
+
+   table->size = size;
+   spin_lock_init(&table->lock);
+
+   return table;
+}
+
+/*
+ * This function should be called at module exit time.
+ * We rely on the module ref count to insure that no one is accessing any
+ * hash table entries at this point in time. Hence we should be able to just
+ * remove all entries from the hash table.
+ */
+void vmci_hash_destroy(struct vmci_hash_table *table)
+{
+   ASSERT(table);
+
+   spin_lock_bh(&table->lock);
+   kfree(table->entries);
+   table->entries = NULL;
+   spin_unlock_bh(&table->lock);
+   kfree(table);
+}
+
+void vmci_hash_init_entry(struct vmci_hash_entry *entry,
+ struct vmci_handle handle)
+{
+   ASSERT(entry);
+   entry->handle = handle;
+   entry->refCount = 0;
+}
+
+/*
+ * Unlocked version of vmci_hash_exists.
+ * True if handle already in hashtable. false otherwise.
+ */
+static bool hash_exists_locked(struct vmci_hash_table *table,
+  struct vmci_handle handle)
+{
+   struct vmci_hash_entry *entry;
+   int idx;
+
+   ASSERT(table);
+
+   idx = VMCI_HASHTABLE_HASH(handle, table->size);
+
+   for (entry = table->entries[idx]; entry; entry = entry->next) {
+   if (VMCI_HANDLE_TO_RESOURCE_ID(entry->handle) ==
+   VMCI_HANDLE_TO_RESOURCE_ID(handle) &&
+   ((VMCI_HANDLE_TO_CONTEXT_ID(entry->handle) ==
+ VMCI_HANDLE_TO_CONTEXT_ID(handle)) ||
+(VMCI_INVALID_ID == VMCI_HANDLE_TO_CONTEXT_ID(handle))
+|| (VMCI_INVALID_ID ==
+VMCI_HANDLE_TO_CONTEXT_ID(entry->handle {
+   return true;
+   }
+   }
+
+   return false;
+}
+
+/*
+ * Assumes caller holds table lock.
+ */
+static int hash_unlink(struct vmci_hash_table *table,
+  struct vmci_hash_entry *entry)
+{
+   int result;
+   struct vmci_hash_entry *prev, *cur;
+   const int idx = VMCI_HASHTABLE_HASH(entry->handle, table->size);
+
+   prev = NULL;
+   cur = table->entries[idx];
+   while (true) {
+   if (cur == NULL) {
+   result = VMCI_ERROR_NOT_FOUND;
+   break;
+   }
+   if (VMCI_HANDLE_EQUAL(cur->handle, entry->handle)) {
+   ASSERT(cur == entry);
+
+   /* Remove entry and break. */
+   if (prev)
+   prev->next = cur->next;
+   else
+   table->entries[idx] = cur->next;
+
+

[vmw_vmci 03/11] Apply VMCI doorbell code

2012-07-26 Thread Andrew Stiegmann (stieg)
Doorbell code allows for notifcations between host and guest.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_doorbell.c |  751 +
 drivers/misc/vmw_vmci/vmci_doorbell.h |   57 +++
 2 files changed, 808 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..389ba4c
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -0,0 +1,751 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_datagram.h"
+#include "vmci_doorbell.h"
+#include "vmci_driver.h"
+#include "vmci_resource.h"
+#include "vmci_route.h"
+
+#define VMCI_DOORBELL_INDEX_TABLE_SIZE (1 << 6)
+#define VMCI_DOORBELL_HASH(_idx)   \
+   vmci_hash_calc((_idx), VMCI_DOORBELL_INDEX_TABLE_SIZE)
+
+/*
+ * DoorbellEntry describes the a doorbell notification handle allocated by the
+ * host.
+ */
+struct dbell_entry {
+   struct vmci_resource resource;
+   uint32_t idx;
+   struct list_head idxListItem;
+   uint32_t privFlags;
+   bool runDelayed;
+   VMCICallback notifyCB;
+   void *clientData;
+   wait_queue_head_t destroyEvent;
+   atomic_t active;/* Only used by guest personality */
+};
+
+/* The VMCI index table keeps track of currently registered doorbells. */
+static struct dbell_index_table {
+   spinlock_t lock;
+   struct list_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
+} vmciDoorbellIT;
+
+/*
+ * The maxNotifyIdx 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 uint32_t maxNotifyIdx;
+
+/*
+ * The notifyIdxCount is used for determining whether there are free entries
+ * within the bitmap (if notifyIdxCount + 1 < maxNotifyIdx).
+ */
+static uint32_t notifyIdxCount;
+
+/*
+ * The lastNotifyIdxReserved 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 lastNotifyIdxReserved.
+ */
+static uint32_t lastNotifyIdxReserved;
+
+/* This is a one entry cache used to by the index allocation. */
+static uint32_t lastNotifyIdxReleased = PAGE_SIZE;
+
+/*
+ * General init code.
+ */
+int __init vmci_dbell_init(void)
+{
+   uint32_t bucket;
+
+   for (bucket = 0; bucket < ARRAY_SIZE(vmciDoorbellIT.entries); ++bucket)
+   INIT_LIST_HEAD(&vmciDoorbellIT.entries[bucket]);
+
+   spin_lock_init(&vmciDoorbellIT.lock);
+   return VMCI_SUCCESS;
+}
+
+/*
+ * Callback to free doorbell entry structure when resource is no longer used,
+ * The entry is freed in VMCIDoorbell_Destroy(), which is waiting on the
+ * signal that gets fired here.
+ */
+static void dbell_free_cb(void *clientData)
+{
+   struct dbell_entry *entry = (struct dbell_entry *)clientData;
+   ASSERT(entry);
+   wake_up(&entry->destroyEvent);
+}
+
+static int dbell_release_cb(void *clientData)
+{
+   struct dbell_entry *entry = (struct dbell_entry *)clientData;
+   ASSERT(entry);
+   vmci_resource_release(&entry->resource);
+   return 0;
+}
+
+/*
+ * 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,
+ uint32_t *privFlags)
+{
+   if (privFlags == 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 =
+ 

[vmw_vmci 00/11] VMCI for Linux

2012-07-26 Thread Andrew Stiegmann (stieg)
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/.

Andrew Stiegmann (stieg) (11):
  Apply VMCI context code
  Apply VMCI datagram code
  Apply VMCI doorbell code
  Apply VMCI driver code
  Apply VMCI event code
  Apply dynamic array code
  Apply VMCI hash table
  Apply VMCI queue pairs
  Apply VMCI resource code
  Apply vmci routing code
  Apply the header code to make VMCI build

 drivers/misc/Kconfig  |1 +
 drivers/misc/Makefile |1 +
 drivers/misc/vmw_vmci/Kconfig |   16 +
 drivers/misc/vmw_vmci/Makefile|   43 +
 drivers/misc/vmw_vmci/vmci_common_int.h   |   58 +
 drivers/misc/vmw_vmci/vmci_context.c  | 1269 +++
 drivers/misc/vmw_vmci/vmci_context.h  |  161 ++
 drivers/misc/vmw_vmci/vmci_datagram.c |  586 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   56 +
 drivers/misc/vmw_vmci/vmci_doorbell.c |  751 ++
 drivers/misc/vmw_vmci/vmci_doorbell.h |   57 +
 drivers/misc/vmw_vmci/vmci_driver.c   | 2298 +++
 drivers/misc/vmw_vmci/vmci_driver.h   |   52 +
 drivers/misc/vmw_vmci/vmci_event.c|  451 
 drivers/misc/vmw_vmci/vmci_event.h|   29 +
 drivers/misc/vmw_vmci/vmci_handle_array.c |  174 ++
 drivers/misc/vmw_vmci/vmci_handle_array.h |   50 +
 drivers/misc/vmw_vmci/vmci_hash_table.c   |  332 +++
 drivers/misc/vmw_vmci/vmci_hash_table.h   |   56 +
 drivers/misc/vmw_vmci/vmci_queue_pair.c   | 3548 +
 drivers/misc/vmw_vmci/vmci_queue_pair.h   |  182 ++
 drivers/misc/vmw_vmci/vmci_resource.c |  194 ++
 drivers/misc/vmw_vmci/vmci_resource.h |   62 +
 drivers/misc/vmw_vmci/vmci_route.c|  241 ++
 drivers/misc/vmw_vmci/vmci_route.h|   34 +
 include/linux/vmw_vmci_api.h  |   89 +
 include/linux/vmw_vmci_defs.h |  921 
 27 files changed, 11712 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 dr

[vmw_vmci 05/11] Apply VMCI event code

2012-07-26 Thread Andrew Stiegmann (stieg)
Code that manages event handlers and handles callbacks when
specific events fire.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_event.c |  451 
 drivers/misc/vmw_vmci/vmci_event.h |   29 +++
 2 files changed, 480 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..bc4e976
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_event.c
@@ -0,0 +1,451 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_event.h"
+#include "vmci_driver.h"
+
+#define EVENT_MAGIC 0xEABE
+#define VMCI_EVENT_MAX_ATTEMPTS 10
+
+struct vmci_subscription {
+   uint32_t id;
+   int refCount;
+   bool runDelayed;
+   wait_queue_head_t destroyEvent;
+   uint32_t event;
+   VMCI_EventCB callback;
+   void *callbackData;
+   struct list_head subscriberListItem;
+};
+
+static struct list_head subscriberArray[VMCI_EVENT_MAX];
+static spinlock_t subscriberLock;
+
+struct delayed_event_info {
+   struct vmci_subscription *sub;
+   uint8_t eventPayload[sizeof(struct vmci_event_data_max)];
+};
+
+struct event_ref {
+   struct vmci_subscription *sub;
+   struct list_head listItem;
+};
+
+int __init vmci_event_init(void)
+{
+   int i;
+
+   for (i = 0; i < VMCI_EVENT_MAX; i++)
+   INIT_LIST_HEAD(&subscriberArray[i]);
+
+   spin_lock_init(&subscriberLock);
+   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, &subscriberArray[e],
+subscriberListItem) {
+
+   /*
+* 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 void event_get(struct vmci_subscription *entry)
+{
+   ASSERT(entry);
+
+   entry->refCount++;
+}
+
+/*
+ * Releases the given VMCISubscription.
+ * Fires the destroy event if the reference count has gone to zero.
+ */
+static void event_release(struct vmci_subscription *entry)
+{
+   ASSERT(entry);
+   ASSERT(entry->refCount > 0);
+
+   entry->refCount--;
+   if (entry->refCount == 0)
+   wake_up(&entry->destroyEvent);
+}
+
+/*
+ * Callback to release the event entry reference. It is called by the
+ * VMCI_WaitOnEvent function before it blocks.
+ */
+static int event_release_cb(void *clientData)
+{
+   struct vmci_subscription *sub = (struct vmci_subscription *)clientData;
+
+   ASSERT(sub);
+
+   spin_lock_bh(&subscriberLock);
+   event_release(sub);
+   spin_unlock_bh(&subscriberLock);
+
+   return 0;
+}
+
+/*
+ * Find entry. Assumes lock is held.
+ * Increments the VMCISubscription refcount if an entry is found.
+ */
+static struct vmci_subscription *event_find(uint32_t subID)
+{
+   int e;
+
+   for (e = 0; e < VMCI_EVENT_MAX; e++) {
+   struct vmci_subscription *cur;
+   list_for_each_entry(cur, &subscriberArray[e],
+   subscriberListItem) {
+   if (cur->id == subID) {
+   event_get(cur);
+