From: Don Slutz <dslutz@verizon.com>
To: xen-devel@lists.xen.org
Cc: Keir Fraser <keir@xen.org>,
	Ian Campbell <ian.campbell@citrix.com>,
	Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
	Eddie Dong <eddie.dong@intel.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	Don Slutz <dslutz@verizon.com>, Jan Beulich <jbeulich@suse.com>,
	Jun Nakajima <jun.nakajima@intel.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Subject: [RFC PATCH 10/10] Add VMware guest info access
Date: Thu, 12 Dec 2013 14:15:18 -0500	[thread overview]
Message-ID: <1386875718-28166-11-git-send-email-dslutz@terremark.com> (raw)
In-Reply-To: <1386875718-28166-1-git-send-email-dslutz@terremark.com>
From: Don Slutz <dslutz@verizon.com>
Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 tools/libxc/xc_domain.c         | 112 ++++++++++++++++++++++++++++++
 tools/libxc/xenctrl.h           |  24 +++++++
 xen/arch/x86/hvm/hvm.c          | 148 ++++++++++++++++++++++++++++++++++++++++
 xen/include/public/hvm/hvm_op.h |  18 +++++
 4 files changed, 302 insertions(+)
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 1ccafc5..0437c6f 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1246,6 +1246,118 @@ int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long
     return rc;
 }
 
+int xc_set_vmport_guest_info(xc_interface *handle,
+                             domid_t dom,
+                             unsigned int key_len,
+                             char *key,
+                             unsigned int val_len,
+                             char *val)
+{
+    DECLARE_HYPERCALL;
+    DECLARE_HYPERCALL_BUFFER(xen_hvm_vmport_guest_info_t, arg);
+    int rc;
+
+    if ((key_len < 1) ||
+        (key_len > VMPORT_GUEST_INFO_KEY_MAX) ||
+        (val_len > VMPORT_GUEST_INFO_VAL_MAX)) {
+        return -1;
+    }
+
+    arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
+    if ( arg == NULL )
+        return -1;
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_set_vmport_guest_info;
+    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+    arg->domid = dom;
+    arg->key_length = key_len;
+    arg->value_length = val_len;
+    memcpy(arg->data, key, key_len);
+    memcpy(&arg->data[key_len], val, val_len);
+    rc = do_xen_hypercall(handle, &hypercall);
+    xc_hypercall_buffer_free(handle, arg);
+    return rc;
+}
+
+int xc_get_vmport_guest_info(xc_interface *handle,
+                             domid_t dom,
+                             unsigned int key_len,
+                             char *key,
+                             unsigned int val_max,
+                             unsigned int *val_len,
+                             char *val)
+{
+    DECLARE_HYPERCALL;
+    DECLARE_HYPERCALL_BUFFER(xen_hvm_vmport_guest_info_t, arg);
+    int rc;
+
+    if ((key_len < 1) ||
+        (key_len > VMPORT_GUEST_INFO_KEY_MAX) )
+        return -1;
+
+    arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_get_vmport_guest_info;
+    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+    arg->domid = dom;
+    arg->key_length = key_len;
+    arg->value_length = 0;
+    *val_len = 0;
+    memcpy(arg->data, key, key_len);
+    rc = do_xen_hypercall(handle, &hypercall);
+    if (rc == 0) {
+        if (arg->value_length > val_max)
+            arg->value_length = val_max;
+        *val_len = arg->value_length;
+        memcpy(val, &arg->data[key_len], arg->value_length);
+    }
+    xc_hypercall_buffer_free(handle, arg);
+    return rc;
+}
+
+int xc_fetch_vmport_guest_info(xc_interface *handle,
+                               domid_t dom,
+                               unsigned int idx,
+                               unsigned int key_max,
+                               unsigned int *key_len,
+                               char *key,
+                               unsigned int val_max,
+                               unsigned int *val_len,
+                               char *val)
+{
+    DECLARE_HYPERCALL;
+    DECLARE_HYPERCALL_BUFFER(xen_hvm_vmport_guest_info_t, arg);
+    int rc;
+
+    arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_get_vmport_guest_info;
+    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+    arg->domid = dom;
+    arg->key_length = 0;
+    arg->value_length = idx;
+    *key_len = 0;
+    *val_len = 0;
+    rc = do_xen_hypercall(handle, &hypercall);
+    if (rc == 0) {
+        if (arg->key_length > key_max)
+            arg->key_length = key_max;
+        *key_len = arg->key_length;
+        memcpy(key, arg->data, arg->key_length);
+        if (arg->value_length > val_max)
+            arg->value_length = val_max;
+        *val_len = arg->value_length;
+        memcpy(val,
+               &arg->data[arg->key_length],
+               arg->value_length);
+    }
+    xc_hypercall_buffer_free(handle, arg);
+    return rc;
+}
+
 int xc_domain_setdebugging(xc_interface *xch,
                            uint32_t domid,
                            unsigned int enable)
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 6e58ebe..6b22b3b 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -1774,6 +1774,30 @@ void xc_clear_last_error(xc_interface *xch);
 int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value);
 int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value);
 
+int xc_set_vmport_guest_info(xc_interface *handle,
+                             domid_t dom,
+                             unsigned int key_len,
+                             char *key,
+                             unsigned int val_len,
+                             char *val);
+int xc_get_vmport_guest_info(xc_interface *handle,
+                             domid_t dom,
+                             unsigned int key_len,
+                             char *key,
+                             unsigned int val_max,
+                             unsigned int *val_len,
+                             char *val);
+int xc_fetch_vmport_guest_info(xc_interface *handle,
+                               domid_t dom,
+                               unsigned int idx,
+                               unsigned int key_max,
+                               unsigned int *key_len,
+                               char *key,
+                               unsigned int val_max,
+                               unsigned int *val_len,
+                               char *val);
+
+
 /* HVM guest pass-through */
 int xc_assign_device(xc_interface *xch,
                      uint32_t domid,
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index a557272..c6f84fc 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -4662,6 +4662,154 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
         break;
     }
 
+    case HVMOP_get_vmport_guest_info:
+    case HVMOP_set_vmport_guest_info:
+    {
+        struct xen_hvm_vmport_guest_info a;
+        struct domain *d;
+        char *key = NULL;
+        char *value = NULL;
+        struct vmport_state *vs;
+        int idx;
+        vmport_guestinfo_t *add_slots[5];
+        int num_slots = 0, num_free_slots = 0;
+
+        if ( copy_from_guest(&a, arg, 1) )
+            return -EFAULT;
+
+        ASSERT(strlen("guestinfo.") == 10);
+#if VMPORT_MAX_KEY_LEN + 10 != VMPORT_GUEST_INFO_KEY_MAX
+#error Need to adjust VMPORT_MAX_KEY_LEN & VMPORT_GUEST_INFO_KEY_MAX
+#endif
+#if VMPORT_MAX_VAL_LEN != VMPORT_GUEST_INFO_VAL_MAX
+#error Need to adjust VMPORT_MAX_VAL_LEN & VMPORT_GUEST_INFO_VAL_MAX
+#endif
+        if ( a.key_length > strlen("guestinfo.") ) {
+            if ( (unsigned long)a.key_length + (unsigned long)a.value_length > sizeof(a.data) )
+                return -EINVAL;
+            if ( memcmp(a.data, "guestinfo.", strlen("guestinfo.")) == 0 ) {
+                key = &a.data[strlen("guestinfo.")];
+                a.key_length -= strlen("guestinfo.");
+            } else {
+                key = &a.data[0];
+            }
+            value = key + a.key_length;
+        } else if (a.key_length > 0) {
+            if ( (unsigned long)a.key_length + (unsigned long)a.value_length > sizeof(a.data) )
+                return -EINVAL;
+            key = &a.data[0];
+            if ( a.key_length > VMPORT_MAX_KEY_LEN )
+                return -EINVAL;
+            if ( a.value_length > VMPORT_MAX_VAL_LEN )
+                return -EINVAL;
+            value = key + a.key_length;
+        } else if ( (a.key_length == 0) && (op == HVMOP_set_vmport_guest_info) ) {
+            return -EINVAL;
+        }
+        d = rcu_lock_domain_by_any_id(a.domid);
+        if ( d == NULL )
+            return rc;
+
+        rc = -EINVAL;
+        if ( !is_hvm_domain(d) )
+            goto param_fail9;
+
+        rc = xsm_hvm_param(XSM_TARGET, d, op);
+        if ( rc )
+            goto param_fail9;
+
+        vs = d->arch.hvm_domain.vmport_data;
+        if ((a.key_length == 0) && (a.value_length >= vs->used_guestinfo)) {
+            rc = -E2BIG;
+            goto param_fail9;
+        }
+        for (idx = 0; idx < vs->used_guestinfo; idx++) {
+            if (vs->guestinfo[idx] &&
+                (vs->guestinfo[idx]->key_len == 0))
+                num_free_slots++;
+        }
+        if (num_free_slots < 5) {
+            num_slots = 5 - num_free_slots;
+            if (vs->used_guestinfo + num_slots > VMPORT_MAX_NUM_KEY)
+                num_slots = VMPORT_MAX_NUM_KEY - vs->used_guestinfo;
+            for (idx = 0; idx < num_slots; idx++)
+                add_slots[idx] = xzalloc(vmport_guestinfo_t);
+        }
+
+        spin_lock(&d->arch.hvm_domain.vmport_lock);
+
+        for (idx = 0; idx < num_slots; idx++)
+            vs->guestinfo[vs->used_guestinfo + idx] = add_slots[idx];
+        vs->used_guestinfo += num_slots;
+
+        if ( op == HVMOP_set_vmport_guest_info )
+        {
+            int free_idx = -1;
+
+            for (idx = 0; idx < vs->used_guestinfo; idx++) {
+                if (!vs->guestinfo[idx]) {
+                    gdprintk(XENLOG_WARNING, "idx=%d not allocated, but used_guestinfo=%d\n",
+                             idx, vs->used_guestinfo);
+                } else if ((vs->guestinfo[idx]->key_len == a.key_length) &&
+                           (memcmp(key,
+                                   vs->guestinfo[idx]->key_data,
+                                   vs->guestinfo[idx]->key_len) == 0)) {
+                    vs->guestinfo[idx]->val_len = a.value_length;
+                    memcpy(vs->guestinfo[idx]->val_data, value, a.value_length);
+                    break;
+                } else if ((vs->guestinfo[idx]->key_len == 0) &&
+                           (free_idx == -1)) {
+                    free_idx = idx;
+                }
+            }
+            if (idx >= vs->used_guestinfo) {
+                if (free_idx == -1) {
+                    rc = -EBUSY;
+                } else {
+                    vs->guestinfo[free_idx]->key_len = a.key_length;
+                    memcpy(vs->guestinfo[free_idx]->key_data, key, a.key_length);
+                    vs->guestinfo[free_idx]->val_len = a.value_length;
+                    memcpy(vs->guestinfo[free_idx]->val_data, value, a.value_length);
+                }
+            }
+        }
+        else
+        {
+            if (a.key_length == 0) {
+                idx = a.value_length;
+                a.key_length = vs->guestinfo[idx]->key_len;
+                memcpy(a.data, vs->guestinfo[idx]->key_data, a.key_length);
+                a.value_length = vs->guestinfo[idx]->val_len;
+                memcpy(&a.data[a.key_length],
+                       vs->guestinfo[idx]->val_data,
+                       a.value_length);
+                rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
+            } else {
+                for (idx = 0; idx < vs->used_guestinfo; idx++) {
+                    if ((vs->guestinfo[idx]->key_len == a.key_length) &&
+                        (memcmp(key,
+                                vs->guestinfo[idx]->key_data,
+                                vs->guestinfo[idx]->key_len) == 0)) {
+                        a.value_length = vs->guestinfo[idx]->val_len;
+                        memcpy(value,
+                               vs->guestinfo[idx]->val_data,
+                               a.value_length);
+                        rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
+                        break;
+                    }
+                }
+                if (idx >= vs->used_guestinfo) {
+                    rc = -ENOENT;
+                }
+            }
+        }
+        spin_unlock(&d->arch.hvm_domain.vmport_lock);
+
+    param_fail9:
+        rcu_unlock_domain(d);
+        break;
+    }
+
     default:
     {
         gdprintk(XENLOG_DEBUG, "Bad HVM op %ld.\n", op);
diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
index a9aab4b..a530903 100644
--- a/xen/include/public/hvm/hvm_op.h
+++ b/xen/include/public/hvm/hvm_op.h
@@ -272,4 +272,22 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_msi_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+/* Get/set vmport subcommands */
+#define HVMOP_get_vmport_guest_info 17
+#define HVMOP_set_vmport_guest_info 18
+#define VMPORT_GUEST_INFO_KEY_MAX 40
+#define VMPORT_GUEST_INFO_VAL_MAX 128
+struct xen_hvm_vmport_guest_info {
+    /* Domain to be accessed */
+    domid_t   domid;
+    /* key length */
+    uint16_t   key_length;
+    /* value length */
+    uint16_t   value_length;
+    /* key and value data */
+    char      data[VMPORT_GUEST_INFO_KEY_MAX + VMPORT_GUEST_INFO_VAL_MAX];
+};
+typedef struct xen_hvm_vmport_guest_info xen_hvm_vmport_guest_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_vmport_guest_info_t);
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
-- 
1.8.4
next prev parent reply	other threads:[~2013-12-12 19:15 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
2013-12-12 19:15 ` [RFC PATCH 01/10] smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME Don Slutz
2013-12-12 19:35   ` Olaf Hering
2013-12-12 22:07     ` Andrew Cooper
2013-12-13 18:03       ` Don Slutz
2013-12-12 19:15 ` [RFC PATCH 02/10] Add VMware HVM params Don Slutz
2013-12-12 22:32   ` Andrew Cooper
2013-12-13 18:12     ` Don Slutz
2013-12-13 10:52   ` Jan Beulich
2013-12-13 18:13     ` Don Slutz
2013-12-17 20:02   ` Konrad Rzeszutek Wilk
2013-12-19  0:47     ` Don Slutz
2013-12-12 19:15 ` [RFC PATCH 03/10] Add cpuid_vmware_leaves Don Slutz
2013-12-12 22:27   ` Andrew Cooper
2013-12-13 10:55     ` Jan Beulich
2013-12-13 13:38       ` Andrew Cooper
2013-12-13 18:55         ` Don Slutz
2013-12-16  8:13           ` Jan Beulich
2013-12-19  0:51             ` Don Slutz
2013-12-17 16:20     ` Don Slutz
2013-12-12 19:15 ` [RFC PATCH 04/10] tools: Add support for new HVM params Don Slutz
2013-12-12 22:36   ` Andrew Cooper
2013-12-13 23:23     ` Don Slutz
2013-12-12 19:15 ` [RFC PATCH 05/10] vmport: Add VMware provided include files Don Slutz
2013-12-17 20:22   ` Konrad Rzeszutek Wilk
2013-12-19  0:54     ` Don Slutz
2013-12-12 19:15 ` [RFC PATCH 06/10] Add vmport structs Don Slutz
2013-12-12 23:10   ` Andrew Cooper
2013-12-19  1:26     ` Don Slutz
2013-12-12 19:15 ` [RFC PATCH 07/10] Add new vmport code Don Slutz
2013-12-13  0:06   ` Andrew Cooper
2013-12-19  2:22     ` Don Slutz
2013-12-13 10:59   ` Jan Beulich
2013-12-19  2:25     ` Don Slutz
2013-12-17 20:36   ` Konrad Rzeszutek Wilk
2013-12-19  2:29     ` Don Slutz
2013-12-12 19:15 ` [RFC PATCH 08/10] connect vmport up Don Slutz
2013-12-13  0:51   ` Andrew Cooper
2013-12-19  2:53     ` Don Slutz
2013-12-13 15:46   ` Boris Ostrovsky
2013-12-19  3:45     ` Don Slutz
2013-12-17 20:37   ` Konrad Rzeszutek Wilk
2013-12-19  3:46     ` Don Slutz
2013-12-12 19:15 ` [RFC PATCH 09/10] libxl: Add VTPOWER, VTREBOOT and VTPING Don Slutz
2013-12-13  0:58   ` Andrew Cooper
2013-12-17 20:30   ` Konrad Rzeszutek Wilk
2013-12-12 19:15 ` Don Slutz [this message]
2013-12-13  1:08   ` [RFC PATCH 10/10] Add VMware guest info access Andrew Cooper
2013-12-13  5:32   ` Matthew Daley
2013-12-17 20:34   ` Konrad Rzeszutek Wilk
2013-12-17 19:03 ` [RFC PATCH 00/10] Xen VMware tools support Konrad Rzeszutek Wilk
2013-12-19  0:46   ` Don Slutz
2013-12-19  9:50     ` Ian Campbell
2013-12-19 14:08       ` Don Slutz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox
  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):
  git send-email \
    --in-reply-to=1386875718-28166-11-git-send-email-dslutz@terremark.com \
    --to=dslutz@verizon.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=eddie.dong@intel.com \
    --cc=ian.campbell@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=jun.nakajima@intel.com \
    --cc=keir@xen.org \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=suravee.suthikulpanit@amd.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY
  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
  Be sure your reply has a Subject: header at the top and a blank line
  before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).