|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH 07/10] Add new vmport code.
From: Don Slutz <dslutz@xxxxxxxxxxx>
enable vmport_flush call.
Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx>
---
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 = ¤t->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
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |