All of lore.kernel.org
 help / color / mirror / Atom feed
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 07/10] Add new vmport code.
Date: Thu, 12 Dec 2013 14:15:15 -0500	[thread overview]
Message-ID: <1386875718-28166-8-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>

enable vmport_flush call.

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 xen/arch/x86/hvm/Makefile                |   1 +
 xen/arch/x86/hvm/hvm.c                   |   2 -
 xen/arch/x86/hvm/vmport/Makefile         |   1 +
 xen/arch/x86/hvm/vmport/includeCheck.h   |  17 +
 xen/arch/x86/hvm/vmport/vmport.c         | 719 +++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/vmport/xen_vmport_def.h |  36 ++
 xen/include/asm-x86/hvm/trace.h          |   3 +
 7 files changed, 777 insertions(+), 2 deletions(-)
 create mode 100644 xen/arch/x86/hvm/vmport/Makefile
 create mode 100644 xen/arch/x86/hvm/vmport/includeCheck.h
 create mode 100644 xen/arch/x86/hvm/vmport/vmport.c
 create mode 100644 xen/arch/x86/hvm/vmport/xen_vmport_def.h

diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
index eea5555..954a81c 100644
--- a/xen/arch/x86/hvm/Makefile
+++ b/xen/arch/x86/hvm/Makefile
@@ -1,5 +1,6 @@
 subdir-y += svm
 subdir-y += vmx
+subdir-y += vmport
 
 obj-y += asid.o
 obj-y += emulate.o
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index fa5d382..a557272 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -614,9 +614,7 @@ int hvm_domain_initialise(struct domain *d)
              (d->max_pages + (1 << 10) - 1) >> 10,
              (d->max_pages + (1 << 20) - 1) >> 20);
 
-#if 0
     vmport_flush(&d->arch.hvm_domain);
-#endif
 
     if ( is_pvh_domain(d) )
     {
diff --git a/xen/arch/x86/hvm/vmport/Makefile b/xen/arch/x86/hvm/vmport/Makefile
new file mode 100644
index 0000000..2648fae
--- /dev/null
+++ b/xen/arch/x86/hvm/vmport/Makefile
@@ -0,0 +1 @@
+obj-y += vmport.o
diff --git a/xen/arch/x86/hvm/vmport/includeCheck.h b/xen/arch/x86/hvm/vmport/includeCheck.h
new file mode 100644
index 0000000..26e0d59
--- /dev/null
+++ b/xen/arch/x86/hvm/vmport/includeCheck.h
@@ -0,0 +1,17 @@
+/*
+ * includeCheck.h
+ *
+ * Copyright (C) 2012 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file 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. <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Nothing here.  Just to use backdoor_def.h without change.
+ */
diff --git a/xen/arch/x86/hvm/vmport/vmport.c b/xen/arch/x86/hvm/vmport/vmport.c
new file mode 100644
index 0000000..43bdf7b
--- /dev/null
+++ b/xen/arch/x86/hvm/vmport/vmport.c
@@ -0,0 +1,719 @@
+/*
+ * HVM VMPORT emulation
+ *
+ * Copyright (C) 2012 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file 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. <http://www.gnu.org/licenses/>.
+ */
+
+#include "xen_vmport_def.h"
+#include "backdoor_def.h"
+#include "guest_msg_def.h"
+#include "asm-x86/hvm/support.h"
+
+#define LOG_RPC             0x0000001
+#define LOG_RECV_STATUS     0x0000002
+#define LOG_SKIP_SEND       0x0000004
+#define LOG_SEND            0x0000008
+#define LOG_SEND_SIZE_ALL   0x0000010
+#define LOG_SEND_SIZE       0x0000020
+#define LOG_RECV_SIZE_ALL   0x0000040
+#define LOG_RECV_SIZE       0x0000080
+#define LOG_CLOSE           0x0000100
+#define LOG_OPEN            0x0000200
+#define LOG_FLUSH           0x0000400
+#define LOG_TRACE           0x0000800
+#define LOG_PING            0x0001000
+#define LOG_SWEEP           0x0002000
+#define LOG_BUILD           0x0004000
+#define LOG_STATUS          0x0008000
+
+#define LOG_ERROR           0x0010000
+
+#define LOG_INFO_GET        0x0020000
+#define LOG_INFO_SET        0x0040000
+
+#define LOG_GP_UNKNOWN      0x0100000
+#define LOG_GP_NOT_VMWARE   0x0200000
+#define LOG_GP_FAIL_RD_INST 0x0400000
+#define LOG_GP_VMWARE_AFTER 0x0800000
+
+#define LOG_VGP_UNKNOWN     0x1000000
+#define LOG_REALMODE_GP     0x8000000
+
+extern unsigned long get_sec(void);
+
+/* Note: VMPORT_PORT and VMPORT_MAGIC is also defined as BDOOR_PORT
+ * and BDOOR_MAGIC in backdoor_def.h Defined in vmport.h also.
+ */
+
+inline uint16_t getLowBits(uint32_t bits)
+{
+    return bits & 0xffff;
+}
+
+inline uint16_t getHighBits(uint32_t bits)
+{
+    return bits >> 16;
+}
+
+inline uint32_t setHighBits(uint32_t b, uint32_t val)
+{
+    return (val << 16) | getLowBits(b);
+}
+
+static inline long getLogMask(struct hvm_domain *hd)
+{
+    return hd->params[HVM_PARAM_VMPORT_LOGMASK];
+}
+
+static inline char *getStatus(struct hvm_domain *hd)
+{
+    return (char*)&hd->params[HVM_PARAM_VMPORT_STATUS];
+}
+
+void vmport_safe_print(char *prefix, int len, char *msg)
+{
+    unsigned char c;
+    int end = len;
+    int i,k;
+    char out[4*(VMPORT_MAX_SEND_BUF + 1)*3 + 6];
+
+    if (end > (sizeof(out)/3 - 6))
+        end = sizeof(out)/3 - 6;
+    out[0] = '<';
+    k = 1;
+    for (i = 0; i < end; i++) {
+        c = msg[i];
+        if ((c == '^') || (c == '\\') || (c == '>')) {
+            out[k++] = '\\';
+            out[k++] = c;
+        } else if ((c >= ' ') && (c <= '~')) {
+            out[k++] = c;
+        } else if (c < ' ') {
+            out[k++] = '^';
+            out[k++] = c ^ 0x40;
+        } else {
+            snprintf(&out[k], sizeof(out) - k, "\\%02x", c);
+            k += 3;
+        }
+    }
+    out[k++] = '>';
+    if (len > end) {
+        out[k++] = '.';
+        out[k++] = '.';
+        out[k++] = '.';
+    }
+    out[k++] = 0;
+    gdprintk(XENLOG_DEBUG, "%s%d(%d,%d,%ld)%s\n", prefix, end, len, k, sizeof(out), out);
+}
+
+void vmport_send(struct hvm_domain *hd, vmport_channel_t *c, char *msg, int slot)
+{
+    unsigned int cur_recv_len = strlen(msg) + 1;
+    char prefix[30];
+    unsigned int my_bkt = c->recv_write;
+    unsigned int next_bkt = my_bkt + 1;
+    vmport_bucket_t *b;
+
+    if (next_bkt >= VMPORT_MAX_BKTS)
+        next_bkt = 0;
+
+    if (next_bkt == c->recv_read) {
+        if (getLogMask(hd) & LOG_SKIP_SEND) {
+            snprintf(prefix, sizeof(prefix),
+                     "VMware _send skipped %d (%d, %d) ", c->chan_id, my_bkt, c->recv_read);
+            prefix[sizeof(prefix)-1] = 0;
+            vmport_safe_print(prefix, cur_recv_len, msg);
+        }
+        getStatus(hd)[slot] = 200;
+        if (getLogMask(hd) & LOG_STATUS)
+            gdprintk(XENLOG_DEBUG, "VMware %d getStatus[%d]=200\n", c->chan_id, slot);
+        return;
+    }
+
+    c->recv_write = next_bkt;
+    b = &c->recv_bkt[my_bkt];
+    if (getLogMask(hd) & LOG_SEND) {
+        snprintf(prefix, sizeof(prefix),
+                 "VMware _send %d (%d) ", c->chan_id, my_bkt);
+        prefix[sizeof(prefix)-1] = 0;
+        vmport_safe_print(prefix, cur_recv_len, msg);
+    }
+
+    b->recv_len = cur_recv_len;
+    b->recv_slot = slot;
+    b->recv_idx = 0;
+    memset(b->recv_buf, 0, sizeof(b->recv_buf));
+    if (cur_recv_len >= (sizeof(b->recv_buf) - 1)) {
+        if (getLogMask(hd) & LOG_ERROR)
+            gdprintk(XENLOG_DEBUG, "VMware recv_len=%d >= %ld.\n",
+                     cur_recv_len, sizeof(b->recv_buf) - 1);
+        cur_recv_len = sizeof(b->recv_buf) - 1;
+    }
+    memcpy(b->recv_buf, msg, cur_recv_len);
+    getStatus(hd)[b->recv_slot] = 1;
+    if (getLogMask(hd) & LOG_STATUS)
+        gdprintk(XENLOG_DEBUG, "VMware %d,%d getStatus[%d]=1\n",
+                 c->chan_id, c->recv_read, b->recv_slot);
+}
+
+void vmport_ctrl_send(struct hvm_domain *hd, char *msg, int slot)
+{
+    struct vmport_state *vs = hd->vmport_data;
+    int i;
+
+    if (slot < 1 || slot > 7)
+        slot = 7;
+    hd->vmport_data->ping_time = get_sec();
+    spin_lock(&hd->vmport_lock);
+    for (i = 0; i < VMPORT_MAX_CHANS; i++) {
+        if (vs->chans[i].proto_num == 0x4f4c4354) {
+            vmport_send(hd, &vs->chans[i], msg, slot);
+        }
+    }
+    spin_unlock(&hd->vmport_lock);
+}
+
+void vmport_flush(struct hvm_domain *hd)
+{
+    if (getLogMask(hd) & LOG_FLUSH)
+        gdprintk(XENLOG_DEBUG, "VMware flush.\n");
+    spin_lock(&hd->vmport_lock);
+    memset(&hd->vmport_data->chans, 0, sizeof(hd->vmport_data->chans));
+    spin_unlock(&hd->vmport_lock);
+}
+
+void vmport_sweep(struct hvm_domain *hd, unsigned long now_time)
+{
+    struct vmport_state *vs = hd->vmport_data;
+    int i;
+
+    for (i = 0; i < VMPORT_MAX_CHANS; i++) {
+        if (vs->chans[i].proto_num) {
+            vmport_channel_t *c = &vs->chans[i];
+            long delta = now_time - c->active_time;
+
+            if ( delta >= 80 ) {
+                if (getLogMask(hd) & LOG_SWEEP)
+                    gdprintk(XENLOG_DEBUG, "VMware flush %d. delta=%ld\n",
+                             c->chan_id, delta);
+                // Return channel to free pool
+                c->proto_num = 0;
+            }
+        }
+    }
+}
+
+vmport_channel_t *vmport_new_chan(struct vmport_state *vs, unsigned long now_time)
+{
+    int i;
+
+    for (i = 0; i < VMPORT_MAX_CHANS; i++) {
+        if (!vs->chans[i].proto_num) {
+            vmport_channel_t *c = &vs->chans[i];
+
+            c->chan_id = i;
+            c->cookie = vs->open_cookie++;
+            c->active_time = now_time;
+            c->send_len = 0;
+            c->send_idx = 0;
+            c->recv_read = 0;
+            c->recv_write = 0;
+            return c;
+        }
+    }
+    return NULL;
+}
+
+void vmport_process_send_size(struct hvm_domain *hd, vmport_channel_t *c, struct cpu_user_regs *ur)
+{
+    // vmware tools often send a 0 byte request size.
+    c->send_len = ur->ebx;
+    c->send_idx = 0;
+    ur->ecx = setHighBits(ur->ecx, MESSAGE_STATUS_SUCCESS);
+    if ((getLogMask(hd) & LOG_SEND_SIZE_ALL) ||
+        ((getLogMask(hd) & LOG_SEND_SIZE) && (c->send_len)))
+        gdprintk(XENLOG_DEBUG, "VMware SENDSIZE %d is %d.\n",
+                 c->chan_id, c->send_len);
+}
+
+void vmport_process_send_payload(struct hvm_domain *hd, vmport_channel_t *c,
+                                 struct cpu_user_regs *ur, unsigned long now_time)
+{
+    char prefix[30];
+
+    if (c->send_idx < VMPORT_MAX_SEND_BUF) {
+        c->send_buf[c->send_idx] = ur->ebx;
+    }
+    c->send_idx++;
+    ur->ecx = setHighBits(ur->ecx, MESSAGE_STATUS_SUCCESS);
+    if (c->send_idx * 4 >= c->send_len) {
+        if (c->send_idx < VMPORT_MAX_SEND_BUF)
+            ((char*)c->send_buf)[c->send_len] = 0;
+        if (getLogMask(hd) & LOG_RPC) {
+            snprintf(prefix, sizeof(prefix),
+                     "VMware RPC %d (%d) ", c->chan_id, c->recv_read);
+            prefix[sizeof(prefix)-1] = 0;
+            vmport_safe_print(prefix, c->send_len, (char*)c->send_buf);
+        }
+        if (c->proto_num == 0x49435052) {
+/* log toolbox: Version: build-341836 */
+/* SetGuestInfo  4 build-341836 */
+/* info-get guestinfo.ip */
+/* info-set guestinfo.ip joe */
+            char * build = NULL;
+            char * info_key = NULL;
+            char * ret_msg = "1 ";
+            char ret_buffer[2 + VMPORT_MAX_VAL_LEN + 2];
+
+            if (strncmp((char*)c->send_buf, "log toolbox: Version: build-",
+                        strlen("log toolbox: Version: build-")) == 0) {
+                build = (char*)c->send_buf + strlen("log toolbox: Version: build-");
+            } else if (strncmp((char*)c->send_buf, "SetGuestInfo  4 build-",
+                               strlen("SetGuestInfo  4 build-")) == 0) {
+                build = (char*)c->send_buf + strlen("SetGuestInfo  4 build-");
+            } else if (strncmp((char*)c->send_buf, "info-get guestinfo.",
+                               strlen("info-get guestinfo.")) == 0) {
+                int keyLen = c->send_len - strlen("info-get guestinfo.");
+                int idx;
+                struct vmport_state *vs = hd->vmport_data;
+
+                info_key = (char*)c->send_buf + strlen("info-get guestinfo.");
+                if (getLogMask(hd) & LOG_INFO_GET) {
+                    snprintf(prefix, sizeof(prefix),
+                             "VMware info-get key:");
+                    vmport_safe_print(prefix, keyLen, info_key);
+                }
+                if (keyLen <= VMPORT_MAX_KEY_LEN) {
+                    for (idx = 0; idx < vs->used_guestinfo; idx++) {
+                        if ((vs->guestinfo[idx]->key_len == keyLen) &&
+                            (memcmp(info_key,
+                                    vs->guestinfo[idx]->key_data,
+                                    vs->guestinfo[idx]->key_len) == 0)) {
+                            if (getLogMask(hd) & LOG_INFO_GET) {
+                                snprintf(prefix, sizeof(prefix),
+                                         "VMware info-get val:");
+                                vmport_safe_print(prefix,
+                                                  vs->guestinfo[idx]->val_len,
+                                                  vs->guestinfo[idx]->val_data);
+                            }
+                            snprintf(ret_buffer, sizeof(ret_buffer) - 1, "1 %.*s",
+                                     (int)vs->guestinfo[idx]->val_len,
+                                     vs->guestinfo[idx]->val_data);
+                            ret_msg = ret_buffer;
+                            break;
+                        }
+                    }
+                    if (idx >= vs->used_guestinfo) {
+                        ret_msg = "0 No value found";
+                    }
+                } else {
+                    ret_msg = "0 Key is too long";
+                }
+            } else if (strncmp((char*)c->send_buf, "info-set guestinfo.",
+                               strlen("info-set guestinfo.")) == 0) {
+                char * val;
+                int rest_len = c->send_len - strlen("info-set guestinfo.");
+
+                info_key = (char*)c->send_buf + strlen("info-set guestinfo.");
+                val = strstr(info_key, " ");
+                if (val) {
+                    int keyLen = val - info_key;
+                    int valLen = rest_len - keyLen - 1;
+                    int free_idx = -1;
+                    int idx;
+                    struct vmport_state *vs = hd->vmport_data;
+
+                    val++;
+                    if (getLogMask(hd) & LOG_INFO_SET) {
+                        snprintf(prefix, sizeof(prefix),
+                                 "VMware info-set key:");
+                        vmport_safe_print(prefix, keyLen, info_key);
+                        snprintf(prefix, sizeof(prefix),
+                                 "VMware info-set val:");
+                        vmport_safe_print(prefix, valLen, val);
+                    }
+                    if (keyLen <= VMPORT_MAX_KEY_LEN) {
+                        if (valLen <= VMPORT_MAX_VAL_LEN) {
+                            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 == keyLen) &&
+                                           (memcmp(info_key,
+                                                   vs->guestinfo[idx]->key_data,
+                                                   vs->guestinfo[idx]->key_len) == 0)) {
+                                    vs->guestinfo[idx]->val_len = valLen;
+                                    memcpy(vs->guestinfo[idx]->val_data, val, valLen);
+                                    break;
+                                } else if ((vs->guestinfo[idx]->key_len == 0) &&
+                                           (free_idx == -1)) {
+                                    free_idx = idx;
+                                }
+                            }
+                            if (idx >= vs->used_guestinfo) {
+                                if (free_idx == -1) {
+                                    ret_msg = "0 Too many keys";
+                                } else {
+                                    vs->guestinfo[free_idx]->key_len = keyLen;
+                                    memcpy(vs->guestinfo[free_idx]->key_data, info_key, keyLen);
+                                    vs->guestinfo[free_idx]->val_len = valLen;
+                                    memcpy(vs->guestinfo[free_idx]->val_data, val, valLen);
+                                }
+                            }
+                        } else {
+                            ret_msg = "0 Value too long";
+                        }
+                    } else {
+                        ret_msg = "0 Key is too long";
+                    }
+                } else {
+                    if (getLogMask(hd) & LOG_INFO_SET) {
+                        snprintf(prefix, sizeof(prefix),
+                                 "VMware info-set missing val; key:");
+                        vmport_safe_print(prefix, rest_len, info_key);
+                    }
+                    ret_msg = "0 Two and exactly two arguments expected";
+                }
+            }
+
+            vmport_send(hd, c, ret_msg, 5);
+            if (build) {
+                long val = 0;
+                char *p = build;
+
+                while (*p) {
+                    if (*p < '0' || *p > '9')
+                        break;
+                    val = val * 10 + *p - '0';
+                    p++;
+                };
+
+                hd->params[HVM_PARAM_VMPORT_BUILD_NUMBER_VALUE] = val;
+                hd->params[HVM_PARAM_VMPORT_BUILD_NUMBER_TIME] = now_time;
+                if (getLogMask(hd) & LOG_BUILD) {
+                    snprintf(prefix, sizeof(prefix),
+                             "VMware build %ld ", val);
+                    vmport_safe_print(prefix, p - build, build);
+                }
+            }
+        } else {
+            unsigned int my_bkt = c->recv_read - 1;
+            vmport_bucket_t *b;
+            int stat = 100;
+            int slot;
+
+            if (my_bkt >= VMPORT_MAX_BKTS)
+                my_bkt = VMPORT_MAX_BKTS - 1;
+            b = &c->recv_bkt[my_bkt];
+            b->recv_len = 0;
+            slot = b->recv_slot;
+            if (slot < 1 || slot > 7)
+                slot = 7;
+            if ((c->send_len > 2) && ((c->send_buf[0] & 0xffff) == 0x4b4f))
+                stat = 3;
+            if (getLogMask(hd) & LOG_STATUS)
+                gdprintk(XENLOG_DEBUG, "VMware %d,%d(%d) getStatus[%d(%d)]=%d <== %d hex=0x%x\n",
+                         c->chan_id, my_bkt, c->recv_read, slot, b->recv_slot,
+                         getStatus(hd)[slot], stat, c->send_buf[0] & 0xffff);
+            getStatus(hd)[slot] = stat;
+        }
+    }
+}
+
+void vmport_process_recv_size(struct hvm_domain *hd, vmport_channel_t *c, struct cpu_user_regs *ur)
+{
+    vmport_bucket_t *b = &c->recv_bkt[c->recv_read];
+
+    if ((getLogMask(hd) & LOG_RECV_SIZE_ALL) ||
+        ((getLogMask(hd) & LOG_RECV_SIZE) && (b->recv_len)))
+        gdprintk(XENLOG_DEBUG, "VMware RECVSIZE %d is %d.\n",
+                 c->chan_id, b->recv_len);
+
+    if (b->recv_len) {
+        ur->ecx = setHighBits(ur->ecx, MESSAGE_STATUS_DORECV | MESSAGE_STATUS_SUCCESS);
+        ur->edx = setHighBits(ur->edx, MESSAGE_TYPE_SENDSIZE);
+        ur->ebx = b->recv_len;
+    } else {
+        ur->ecx = setHighBits(ur->ecx, MESSAGE_STATUS_SUCCESS);
+    }
+}
+
+void vmport_process_recv_payload(struct hvm_domain *hd, vmport_channel_t *c, struct cpu_user_regs *ur)
+{
+    vmport_bucket_t *b = &c->recv_bkt[c->recv_read];
+
+    if (b->recv_idx < VMPORT_MAX_RECV_BUF) {
+        ur->ebx = b->recv_buf[b->recv_idx++];
+    } else {
+        ur->ebx = 0;
+    }
+    ur->ecx = setHighBits(ur->ecx, MESSAGE_STATUS_SUCCESS);
+    ur->edx = setHighBits(ur->edx, MESSAGE_TYPE_SENDPAYLOAD);
+}
+
+void vmport_process_recv_status(struct hvm_domain *hd, vmport_channel_t *c, struct cpu_user_regs *ur)
+{
+    vmport_bucket_t *b = &c->recv_bkt[c->recv_read];
+    char prefix[30];
+
+    ur->ecx = setHighBits(ur->ecx, MESSAGE_STATUS_SUCCESS);
+    if (getLogMask(hd) & LOG_RECV_STATUS) {
+        snprintf(prefix, sizeof(prefix),
+                 "VMware RECVSTATUS %d (%d) ", c->chan_id, c->recv_read);
+        prefix[sizeof(prefix)-1] = 0;
+        vmport_safe_print(prefix, b->recv_len, (char*)b->recv_buf);
+    }
+    getStatus(hd)[b->recv_slot] = 2;
+    if (getLogMask(hd) & LOG_STATUS)
+        gdprintk(XENLOG_DEBUG, "VMware %d,%d getStatus[%d]=2\n",
+                 c->chan_id, c->recv_read, b->recv_slot);
+    c->recv_read++;
+    if (c->recv_read >= VMPORT_MAX_BKTS)
+        c->recv_read = 0;
+}
+
+void vmport_process_close(struct hvm_domain *hd, vmport_channel_t *c, struct cpu_user_regs *ur)
+{
+    // Return channel to free pool
+    c->proto_num = 0;
+    ur->ecx = setHighBits(ur->ecx, MESSAGE_STATUS_SUCCESS);
+    if (getLogMask(hd) & LOG_CLOSE)
+        gdprintk(XENLOG_DEBUG, "VMware CLOSE %d.\n",
+                 c->chan_id);
+    if (getLogMask(hd) & LOG_STATUS)
+        gdprintk(XENLOG_DEBUG, "VMware %d getStatus[0]=0x%x & ~0x%x=0x%x\n",
+                 c->chan_id, getStatus(hd)[0], 1 << c->chan_id, ~(1 << c->chan_id));
+    getStatus(hd)[0] &= ~(1 << c->chan_id);
+}
+
+void vmport_process_packet(struct hvm_domain *hd, vmport_channel_t *c,
+                           struct cpu_user_regs *ur, int sub_cmd,
+                           unsigned long now_time)
+{
+    c->active_time = now_time;
+    switch (sub_cmd) {
+    case MESSAGE_TYPE_SENDSIZE:
+        vmport_process_send_size(hd, c, ur);
+        break;
+    case MESSAGE_TYPE_SENDPAYLOAD:
+        vmport_process_send_payload(hd, c, ur, now_time);
+        break;
+
+    case MESSAGE_TYPE_RECVSIZE:
+        vmport_process_recv_size(hd, c, ur);
+        break;
+    case MESSAGE_TYPE_RECVPAYLOAD:
+        vmport_process_recv_payload(hd, c, ur);
+        break;
+    case MESSAGE_TYPE_RECVSTATUS:
+        vmport_process_recv_status(hd, c, ur);
+        break;
+
+    case MESSAGE_TYPE_CLOSE:
+        vmport_process_close(hd, c, ur);
+        break;
+
+    default:
+        ur->ecx = 0;
+        break;
+    }
+}
+
+void vmport_rpc(struct hvm_domain *hd, struct cpu_user_regs *ur)
+{
+    int sub_cmd = (ur->ecx >> 16) & 0xffff;
+    vmport_channel_t *c = NULL;
+    uint16_t msg_id;
+    uint32_t msg_cookie;
+    unsigned long now_time = get_sec();
+    long delta = now_time - hd->vmport_data->ping_time;
+
+    if ( delta >= hd->params[HVM_PARAM_VMPORT_RESET_TIME] ) {
+        if (getLogMask(hd) & LOG_PING)
+            gdprintk(XENLOG_DEBUG, "VMware ping. delta=%ld\n",
+                     delta);
+        vmport_ctrl_send(hd, "reset", 7);
+    }
+    spin_lock(&hd->vmport_lock);
+    vmport_sweep(hd, now_time);
+    do {
+        // Check to see if a new open request is happening...
+        if (MESSAGE_TYPE_OPEN == sub_cmd) {
+            c = vmport_new_chan(hd->vmport_data, now_time);
+            if (NULL == c) {
+                if (getLogMask(hd) & LOG_ERROR)
+                    gdprintk(XENLOG_ERR, "VMware failed to find a free channel.\n");
+                break;
+            }
+
+            // Attach the apropriate protocol the the channel
+            c->proto_num = ur->ebx & ~GUESTMSG_FLAG_COOKIE;
+            ur->ecx = setHighBits(ur->ecx, MESSAGE_STATUS_SUCCESS);
+            ur->edx = setHighBits(ur->edx, c->chan_id);
+            ur->edi = getLowBits(c->cookie);
+            ur->esi = getHighBits(c->cookie);
+            if (getLogMask(hd) & LOG_OPEN)
+                gdprintk(XENLOG_DEBUG, "VMware OPEN %d p=%x.\n",
+                         c->chan_id, c->proto_num);
+            if (getLogMask(hd) & LOG_STATUS)
+                gdprintk(XENLOG_DEBUG, "VMware %d getStatus[0]=0x%x | 0x%x\n",
+                         c->chan_id, getStatus(hd)[0], 1 << c->chan_id);
+            getStatus(hd)[0] |= 1 << c->chan_id;
+            if (c->proto_num == 0x4f4c4354) {
+                vmport_send(hd, c, "reset", 6);
+            }
+            break;
+        }
+
+        msg_id = getHighBits(ur->edx);
+        msg_cookie = getLowBits(ur->edi) | (ur->esi << 16);
+        if (msg_id >= VMPORT_MAX_CHANS) {
+            if (getLogMask(hd) & LOG_ERROR)
+                gdprintk(XENLOG_ERR, "VMware chan id err %d >= %d.\n",
+                         msg_id, VMPORT_MAX_CHANS);
+            break;
+        }
+        c = &hd->vmport_data->chans[msg_id];
+        if (!c->proto_num) {
+            if (getLogMask(hd) & LOG_ERROR)
+                gdprintk(XENLOG_ERR, "VMware chan %d not open.\n",
+                         msg_id);
+            break;
+        }
+
+        // We check the cookie here since it's possible that the
+        // connection timed out on us and another channel was opened
+        // if this happens, return error and the um tool will
+        // need to reopen the connection
+        if (msg_cookie != c->cookie) {
+            if (getLogMask(hd) & LOG_ERROR)
+                gdprintk(XENLOG_ERR, "VMware cookie err %x vs %x.\n",
+                         msg_cookie, c->cookie);
+            break;
+        }
+        vmport_process_packet(hd, c, ur, sub_cmd, now_time);
+    } while( 0 );
+
+    if( NULL == c )
+        ur->ecx = setHighBits(ur->ecx, 0);
+
+    spin_unlock(&hd->vmport_lock);
+}
+
+int vmport_ioport(int dir, int size, unsigned long data, struct cpu_user_regs *regs)
+{
+    uint32_t cmd = getLowBits(regs->ecx);
+    uint32_t magic = regs->eax;
+    struct hvm_domain *hd = &current->domain->arch.hvm_domain;
+
+    if ( dir != IOREQ_WRITE )
+        data = 0;
+
+    if (magic == BDOOR_MAGIC) {
+        const uint32_t apicHz = 1000000000L;
+        uint64_t value;
+
+        switch (cmd) {
+        case BDOOR_CMD_GETMHZ:
+            /* ... */
+            regs->ebx = BDOOR_MAGIC;
+            regs->eax = (uint32_t)(current->domain->arch.tsc_khz / 1000);
+            break;
+        case BDOOR_CMD_GETVERSION:
+            /* ... */
+            regs->ebx = BDOOR_MAGIC;
+            /* VERSION_MAGIC */
+            regs->eax = 6;
+            /* Claim we are an ESX. VMX_TYPE_SCALABLE_SERVER */
+            regs->ecx = 2;
+            break;
+        case BDOOR_CMD_GETHWVERSION:
+            /* ... */
+            regs->ebx = BDOOR_MAGIC;
+            /* ?? */
+            regs->eax = 0x4;
+            break;
+        case BDOOR_CMD_GETHZ:
+            value = current->domain->arch.tsc_khz * 1000;
+            /* apic-frequency (bus speed) */
+            regs->ecx = apicHz;
+            /* High part of tsc-frequency */
+            regs->ebx = (uint32_t)(value >> 32);
+            /* Low part of tsc-frequency */
+            regs->eax = (uint32_t)value;
+            break;
+        case BDOOR_CMD_GETTIME:
+            value = get_localtime_us(current->domain);
+            /* hostUsecs */
+            regs->ebx = (uint32_t)(value % 1000000UL);
+            /* hostSecs */
+            regs->eax = (uint32_t)(value / 1000000ULL);
+            /* maxTimeLag */
+            regs->ecx = 0;
+            break;
+        case BDOOR_CMD_GETTIMEFULL:
+            value = get_localtime_us(current->domain);
+            /* ... */
+            regs->eax = BDOOR_MAGIC;
+            /* hostUsecs */
+            regs->ebx = (uint32_t)(value % 1000000UL);
+            /* High part of hostSecs */
+            regs->esi = (uint32_t)((value / 1000000ULL) >> 32);
+            /* Low part of hostSecs */
+            regs->edx = (uint32_t)(value / 1000000ULL);
+            /* maxTimeLag */
+            regs->ecx = 0;
+            break;
+        case BDOOR_CMD_MESSAGE:
+            vmport_rpc(hd, regs);
+            break;
+
+        default:
+            if (getLogMask(hd) & LOG_ERROR)
+                gdprintk(XENLOG_DEBUG, "VMware size=%d dir=%d data=%lx cmd=%d.\n",
+                         size, dir, data, cmd);
+            break;
+        }
+        if (getLogMask(hd) & LOG_TRACE)
+            gdprintk(XENLOG_DEBUG, "VMware ip=%lx cmd=%d ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx\n",
+                     (unsigned long)regs->eip, cmd,
+                     (unsigned long)regs->eax, (unsigned long)regs->ebx,
+                     (unsigned long)regs->ecx, (unsigned long)regs->edx,
+                     (unsigned long)regs->esi, (unsigned long)regs->edi);
+    } else
+        if (getLogMask(hd) & LOG_ERROR)
+            gdprintk(XENLOG_ERR, "Not VMware %x vs %x vs %x; ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx\n",
+                     magic, BDOOR_MAGIC, VMPORT_MAGIC,
+                     (unsigned long)regs->eip,
+                     (unsigned long)regs->eax, (unsigned long)regs->ebx,
+                     (unsigned long)regs->ecx, (unsigned long)regs->edx,
+                     (unsigned long)regs->esi, (unsigned long)regs->edi);
+
+    if (dir == IOREQ_READ)
+        HVMTRACE_ND(IOPORT_READ, 0, 1/*cycles*/, 5, VMPORT_PORT, cmd,
+                    regs->eax, regs->ebx, regs->ecx, 0);
+    else
+        HVMTRACE_ND(IOPORT_WRITE, 0, 1/*cycles*/, 5, VMPORT_PORT, cmd,
+                    regs->eax, regs->ebx, regs->ecx, 0);
+
+    return 1;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/vmport/xen_vmport_def.h b/xen/arch/x86/hvm/vmport/xen_vmport_def.h
new file mode 100644
index 0000000..e87845b
--- /dev/null
+++ b/xen/arch/x86/hvm/vmport/xen_vmport_def.h
@@ -0,0 +1,36 @@
+/*
+ * xen_vmport_def.h: HVM VMPORT emulation
+ *
+ *
+ * Copyright (C) 2012 Verizon Corporation
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License Version 2 (GPLv2)
+ * as published by the Free Software Foundation.
+ *
+ * This file 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. <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XEN_VMPORT_DEF_H__
+#define __XEN_VMPORT_DEF_H__
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/trace.h>
+#include <xen/event.h>
+#include <xen/hypercall.h>
+#include <asm/current.h>
+#include <asm/cpufeature.h>
+#include <asm/processor.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/trace.h>
+#include <asm/hvm/vmport.h>
+
+#endif
diff --git a/xen/include/asm-x86/hvm/trace.h b/xen/include/asm-x86/hvm/trace.h
index 9d7e00b..d5c3a3e 100644
--- a/xen/include/asm-x86/hvm/trace.h
+++ b/xen/include/asm-x86/hvm/trace.h
@@ -52,8 +52,11 @@
 #define DO_TRC_HVM_LMSW64      DEFAULT_HVM_MISC
 #define DO_TRC_HVM_REALMODE_EMULATE DEFAULT_HVM_MISC 
 #define DO_TRC_HVM_TRAP             DEFAULT_HVM_MISC
+#define DO_TRC_HVM_TRAP64           DEFAULT_HVM_MISC
 #define DO_TRC_HVM_TRAP_DEBUG       DEFAULT_HVM_MISC
 #define DO_TRC_HVM_VLAPIC           DEFAULT_HVM_MISC
+#define DO_TRC_HVM_IOPORT_READ      DEFAULT_HVM_IO
+#define DO_TRC_HVM_IOPORT_WRITE     DEFAULT_HVM_IO
 
 
 #define TRC_PAR_LONG(par) ((par)&0xFFFFFFFF),((par)>>32)
-- 
1.8.4

  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 ` Don Slutz [this message]
2013-12-13  0:06   ` [RFC PATCH 07/10] Add new vmport code 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 ` [RFC PATCH 10/10] Add VMware guest info access Don Slutz
2013-12-13  1:08   ` 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-8-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.