[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 =
+   vmci_event_data_const_payload(event_data);
+
+   if (sub_id != ctx_update_sub_id) {
+

[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(event_data);
+
+   if (sub_id != ctx_update_sub_id) {
+   pr_devel("Invalid subscriber (ID=0x%x).\n", sub_

[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) {
+   pr_devel("Invalid subscriber (ID=0x%x).\n", sub_id);
+   return;
+   }
+
+   if (!even

[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) {
+   pr_devel("Invalid subscriber (ID=0x%x).\n", sub_id);
+   return;
+   }
+
+   if (!even

[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) {
+   pr_devel("Invalid subscriber (ID=0x%x).\n", sub_id);
+   return;
+   }
+
+   if (!even