All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/10] Xen VMware tools support
@ 2013-12-12 19:15 Don Slutz
  2013-12-12 19:15 ` [RFC PATCH 01/10] smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME Don Slutz
                   ` (10 more replies)
  0 siblings, 11 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

See

http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458

for info on detecting VMware.

Linux does not follow this exactly.  It checks for CPUID 1st.  If
that fails, it checks for SMBIOS containing "VMware" (not VMware- or
VMW).

So this patch set provides:

        SMBIOS -- Add string VMware-
        CPUID -- Add VMware's CPUID (Note: currently HyperV (viridian support) breaks this check.)
        Add the magic VMware port
            Allow VMware tools poweroff and reboot
            Enable access to VMware's guest info
            Provide the VMware tools build number

Don Slutz (10):
  smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME.
  Add VMware HVM params
  Add cpuid_vmware_leaves
  tools: Add support for new HVM params
  vmport: Add VMware provided include files.
  Add vmport structs
  Add new vmport code.
  connect vmport up
  libxl: Add VTPOWER, VTREBOOT and VTPING
  Add VMware guest info access

 tools/firmware/hvmloader/smbios.c        |   2 +-
 tools/libxc/xc_domain.c                  | 112 +++++
 tools/libxc/xc_domain_restore.c          |  27 ++
 tools/libxc/xc_domain_save.c             |  24 ++
 tools/libxc/xenctrl.h                    |  24 ++
 tools/libxc/xg_save_restore.h            |   2 +
 tools/libxl/libxl.c                      |  12 +
 tools/libxl/libxl_create.c               |   4 +-
 tools/libxl/libxl_dom.c                  |   5 +
 tools/libxl/libxl_types.idl              |   5 +
 tools/libxl/xl_cmdimpl.c                 |  10 +
 tools/libxl/xl_cmdtable.c                |   2 +-
 tools/libxl/xl_sxp.c                     |   4 +
 xen/arch/x86/domctl.c                    |  34 ++
 xen/arch/x86/hvm/Makefile                |   1 +
 xen/arch/x86/hvm/hvm.c                   | 209 ++++++++-
 xen/arch/x86/hvm/io.c                    |   4 +
 xen/arch/x86/hvm/svm/svm.c               | 104 +++++
 xen/arch/x86/hvm/svm/vmcb.c              |   1 +
 xen/arch/x86/hvm/vmport/Makefile         |   1 +
 xen/arch/x86/hvm/vmport/backdoor_def.h   | 167 +++++++
 xen/arch/x86/hvm/vmport/guest_msg_def.h  |  87 ++++
 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/arch/x86/hvm/vmx/vmcs.c              |   1 +
 xen/arch/x86/hvm/vmx/vmx.c               | 125 ++++++
 xen/arch/x86/hvm/vmx/vvmx.c              |  13 +
 xen/arch/x86/traps.c                     |  58 ++-
 xen/include/asm-x86/hvm/domain.h         |   4 +
 xen/include/asm-x86/hvm/hvm.h            |   3 +
 xen/include/asm-x86/hvm/trace.h          |   3 +
 xen/include/asm-x86/hvm/vmport.h         |  77 ++++
 xen/include/asm-x86/processor.h          |   2 +
 xen/include/public/domctl.h              |   3 +
 xen/include/public/hvm/hvm_op.h          |  18 +
 xen/include/public/hvm/params.h          |  11 +-
 xen/include/public/trace.h               |   1 +
 38 files changed, 1926 insertions(+), 6 deletions(-)
 create mode 100644 xen/arch/x86/hvm/vmport/Makefile
 create mode 100644 xen/arch/x86/hvm/vmport/backdoor_def.h
 create mode 100644 xen/arch/x86/hvm/vmport/guest_msg_def.h
 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
 create mode 100644 xen/include/asm-x86/hvm/vmport.h

-- 
1.8.4

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [RFC PATCH 01/10] smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME.
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
@ 2013-12-12 19:15 ` Don Slutz
  2013-12-12 19:35   ` Olaf Hering
  2013-12-12 19:15 ` [RFC PATCH 02/10] Add VMware HVM params Don Slutz
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

Some code checks for VMware support by looking for the string
"VMware" in DMI info.  So the string VMwareTools matches.

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 tools/firmware/hvmloader/smbios.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/firmware/hvmloader/smbios.c b/tools/firmware/hvmloader/smbios.c
index 4d3d692..c479272 100644
--- a/tools/firmware/hvmloader/smbios.c
+++ b/tools/firmware/hvmloader/smbios.c
@@ -476,7 +476,7 @@ smbios_type_1_init(void *start, const char *xen_version,
     strcpy((char *)start, s);
     start += strlen(s) + 1;
 
-    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU");
+    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU plus VMware-Tools");
     strcpy((char *)start, s);
     start += strlen(s) + 1;
 
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 02/10] Add VMware HVM params
  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:15 ` Don Slutz
  2013-12-12 22:32   ` Andrew Cooper
                     ` (2 more replies)
  2013-12-12 19:15 ` [RFC PATCH 03/10] Add cpuid_vmware_leaves Don Slutz
                   ` (8 subsequent siblings)
  10 siblings, 3 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 xen/include/public/hvm/params.h | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index 517a184..c571a1e 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -145,6 +145,15 @@
 /* SHUTDOWN_* action in case of a triple fault */
 #define HVM_PARAM_TRIPLE_FAULT_REASON 31
 
-#define HVM_NR_PARAMS          32
+/* Params for VMware */
+#define HVM_PARAM_VMWARE_HW                 32
+#define HVM_PARAM_VMPORT_LOGMASK            33
+#define HVM_PARAM_VMPORT_STATUS             34
+#define HVM_PARAM_VMPORT_BUILD_NUMBER_TIME  35
+#define HVM_PARAM_VMPORT_BUILD_NUMBER_VALUE 36
+#define HVM_PARAM_VMPORT_RESET_TIME         37
+
+#define HVM_NR_PARAMS          38
+
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 03/10] Add cpuid_vmware_leaves
  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:15 ` [RFC PATCH 02/10] Add VMware HVM params Don Slutz
@ 2013-12-12 19:15 ` Don Slutz
  2013-12-12 22:27   ` Andrew Cooper
  2013-12-12 19:15 ` [RFC PATCH 04/10] tools: Add support for new HVM params Don Slutz
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 xen/arch/x86/hvm/hvm.c          |  3 +++
 xen/arch/x86/traps.c            | 58 ++++++++++++++++++++++++++++++++++++++++-
 xen/include/asm-x86/hvm/hvm.h   |  3 +++
 xen/include/asm-x86/processor.h |  2 ++
 4 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 69f7e74..6a7a781 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -2878,6 +2878,9 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     if ( cpuid_viridian_leaves(input, eax, ebx, ecx, edx) )
         return;
 
+    if ( cpuid_vmware_leaves(input, count, eax, ebx, ecx, edx) )
+        return;
+
     if ( cpuid_hypervisor_leaves(input, count, eax, ebx, ecx, edx) )
         return;
 
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 940bc33..71a76df 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -671,14 +671,70 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
     return 0;
 }
 
+int cpuid_vmware_leaves(uint32_t idx, uint32_t sub_idx,
+                        uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+    struct domain *d = current->domain;
+    /* Optionally shift out of the way of Viridian architectural leaves. */
+    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
+    uint32_t limit;
+    const uint32_t apic_khz = 1000000L;
+
+    if ( !is_vmware_domain(d) )
+        return 0;
+
+    idx -= base;
+
+    limit = 0x10;
+
+    if ( idx > limit )
+        return 0;
+
+    switch ( idx )
+    {
+    case 0:
+        *eax = base + limit; /* Largest leaf */
+        *ebx = 0x61774d56; /* "VMwa" */
+        *ecx = 0x4d566572; /* "reVM" */
+        *edx = 0x65726177; /* "ware" */
+        break;
+
+    case 1 ... 0xf:
+        *eax = 0;          /* Reserved */
+        *ebx = 0;          /* Reserved */
+        *ecx = 0;          /* Reserved */
+        *edx = 0;          /* Reserved */
+        break;
+
+    case 0x10:
+        /* (Virtual) TSC frequency in kHz. */
+        *eax =  d->arch.tsc_khz;
+        /* (Virtual) Bus (local apic timer) frequency in kHz. */
+        *ebx = apic_khz;
+        *ecx = 0;          /* Reserved */
+        *edx = 0;          /* Reserved */
+        break;
+
+    default:
+        BUG();
+    }
+
+    return 1;
+}
+
 int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
                uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
 {
     struct domain *d = current->domain;
     /* Optionally shift out of the way of Viridian architectural leaves. */
-    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
+    uint32_t base = 0x40000000;
     uint32_t limit;
 
+    if ( is_viridian_domain(d) )
+        base += 0x100;
+    if ( is_vmware_domain(d) )
+        base += 0x100;
+
     idx -= base;
 
     /*
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index ccca5df..ae3768c 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -332,6 +332,9 @@ static inline unsigned long hvm_get_shadow_gs_base(struct vcpu *v)
 #define is_viridian_domain(_d)                                             \
  (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VIRIDIAN]))
 
+#define is_vmware_domain(_d)                                             \
+ (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VMWARE_HW]))
+
 void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
                                    unsigned int *ecx, unsigned int *edx);
 void hvm_migrate_timers(struct vcpu *v);
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index c120460..6c53e45 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -559,6 +559,8 @@ void int80_direct_trap(void);
 
 extern int hypercall(void);
 
+int cpuid_vmware_leaves( uint32_t idx, uint32_t sub_idx,
+          uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
 int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
           uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
 int rdmsr_hypervisor_regs(uint32_t idx, uint64_t *val);
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 04/10] tools: Add support for new HVM params
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
                   ` (2 preceding siblings ...)
  2013-12-12 19:15 ` [RFC PATCH 03/10] Add cpuid_vmware_leaves Don Slutz
@ 2013-12-12 19:15 ` Don Slutz
  2013-12-12 22:36   ` Andrew Cooper
  2013-12-12 19:15 ` [RFC PATCH 05/10] vmport: Add VMware provided include files Don Slutz
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 tools/libxc/xc_domain_restore.c | 27 +++++++++++++++++++++++++++
 tools/libxc/xc_domain_save.c    | 24 ++++++++++++++++++++++++
 tools/libxc/xg_save_restore.h   |  2 ++
 tools/libxl/libxl_create.c      |  4 +++-
 tools/libxl/libxl_dom.c         |  5 +++++
 tools/libxl/libxl_types.idl     |  2 ++
 tools/libxl/xl_cmdimpl.c        | 10 ++++++++++
 tools/libxl/xl_sxp.c            |  4 ++++
 xen/arch/x86/hvm/hvm.c          |  1 +
 9 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index 80769a7..9bfb608 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -746,6 +746,8 @@ typedef struct {
     uint64_t acpi_ioport_location;
     uint64_t viridian;
     uint64_t vm_generationid_addr;
+    uint64_t vmware_hw;
+    uint64_t vmport_logmask;
 
     struct toolstack_data_t tdata;
 } pagebuf_t;
@@ -930,6 +932,26 @@ static int pagebuf_get_one(xc_interface *xch, struct restore_ctx *ctx,
         }
         return pagebuf_get_one(xch, ctx, buf, fd, dom);
 
+    case XC_SAVE_ID_HVM_VMWARE_HW:
+        /* Skip padding 4 bytes then read the vmware flag. */
+        if ( RDEXACT(fd, &buf->vmware_hw, sizeof(uint32_t)) ||
+             RDEXACT(fd, &buf->vmware_hw, sizeof(uint64_t)) )
+        {
+            PERROR("error read the vmware_hw value");
+            return -1;
+        }
+        return pagebuf_get_one(xch, ctx, buf, fd, dom);
+
+    case XC_SAVE_ID_HVM_VMPORT_LOGMASK:
+        /* Skip padding 4 bytes then read the vmport_logmask flag. */
+        if ( RDEXACT(fd, &buf->vmport_logmask, sizeof(uint32_t)) ||
+             RDEXACT(fd, &buf->vmport_logmask, sizeof(uint64_t)) )
+        {
+            PERROR("error read the vmport_logmask flag");
+            return -1;
+        }
+        return pagebuf_get_one(xch, ctx, buf, fd, dom);
+
     case XC_SAVE_ID_TOOLSTACK:
         {
             if ( RDEXACT(fd, &buf->tdata.len, sizeof(buf->tdata.len)) )
@@ -1755,6 +1777,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
     if (pagebuf.viridian != 0)
         xc_set_hvm_param(xch, dom, HVM_PARAM_VIRIDIAN, 1);
 
+    if (pagebuf.vmware_hw != 0)
+        xc_set_hvm_param(xch, dom, HVM_PARAM_VMWARE_HW, pagebuf.vmport_logmask);
+    if (pagebuf.vmport_logmask != 0)
+        xc_set_hvm_param(xch, dom, HVM_PARAM_VMPORT_LOGMASK, pagebuf.vmport_logmask);
+
     if (pagebuf.acpi_ioport_location == 1) {
         DBGPRINTF("Use new firmware ioport from the checkpoint\n");
         xc_set_hvm_param(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 42c4752..dac7c2c 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -1731,6 +1731,30 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
             PERROR("Error when writing the viridian flag");
             goto out;
         }
+
+        chunk.id = XC_SAVE_ID_HVM_VMWARE_HW;
+        chunk.data = 0;
+        xc_get_hvm_param(xch, dom, HVM_PARAM_VMWARE_HW,
+                         (unsigned long *)&chunk.data);
+
+        if ( (chunk.data != 0) &&
+             wrexact(io_fd, &chunk, sizeof(chunk)) )
+        {
+            PERROR("Error when writing the vmware_hw");
+            goto out;
+        }
+
+        chunk.id = XC_SAVE_ID_HVM_VMPORT_LOGMASK;
+        chunk.data = 0;
+        xc_get_hvm_param(xch, dom, HVM_PARAM_VMPORT_LOGMASK,
+                         (unsigned long *)&chunk.data);
+
+        if ( (chunk.data != 0) &&
+             wrexact(io_fd, &chunk, sizeof(chunk)) )
+        {
+            PERROR("Error when writing the vmport_loglvl");
+            goto out;
+        }
     }
 
     if ( callbacks != NULL && callbacks->toolstack_save != NULL )
diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h
index f859621..69f44de 100644
--- a/tools/libxc/xg_save_restore.h
+++ b/tools/libxc/xg_save_restore.h
@@ -259,6 +259,8 @@
 #define XC_SAVE_ID_HVM_ACCESS_RING_PFN  -16
 #define XC_SAVE_ID_HVM_SHARING_RING_PFN -17
 #define XC_SAVE_ID_TOOLSTACK          -18 /* Optional toolstack specific info */
+#define XC_SAVE_ID_HVM_VMWARE_HW      -19
+#define XC_SAVE_ID_HVM_VMPORT_LOGMASK -20
 
 /*
 ** We process save/restore/migrate in batches of pages; the below
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index e03bb55..8b08bbd 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -388,13 +388,15 @@ int libxl__domain_build(libxl__gc *gc,
         vments[4] = "start_time";
         vments[5] = libxl__sprintf(gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
 
-        localents = libxl__calloc(gc, 7, sizeof(char *));
+        localents = libxl__calloc(gc, 9, sizeof(char *));
         localents[0] = "platform/acpi";
         localents[1] = libxl_defbool_val(info->u.hvm.acpi) ? "1" : "0";
         localents[2] = "platform/acpi_s3";
         localents[3] = libxl_defbool_val(info->u.hvm.acpi_s3) ? "1" : "0";
         localents[4] = "platform/acpi_s4";
         localents[5] = libxl_defbool_val(info->u.hvm.acpi_s4) ? "1" : "0";
+        localents[6] = "platform/vmware_hw";
+        localents[7] = libxl__sprintf(gc, "%d", info->u.hvm.vmware_hw);
 
         break;
     case LIBXL_DOMAIN_TYPE_PV:
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 078cff1..53ab6a6 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -496,6 +496,11 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
     xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
     xc_set_hvm_param(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
 
+    xc_set_hvm_param(handle, domid, HVM_PARAM_VMWARE_HW,
+                     info->u.hvm.vmware_hw);
+    xc_set_hvm_param(handle, domid, HVM_PARAM_VMPORT_LOGMASK,
+                     info->u.hvm.vmport_logmask);
+
     xc_dom_gnttab_hvm_seed(handle, domid, *console_mfn, *store_mfn, console_domid, store_domid);
     return 0;
 }
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 649ce50..71ba64e 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -346,6 +346,8 @@ libxl_domain_build_info = Struct("domain_build_info",[
                                        ("timeoffset",       string),
                                        ("hpet",             libxl_defbool),
                                        ("vpt_align",        libxl_defbool),
+                                       ("vmware_hw",        integer),
+                                       ("vmport_logmask",   integer),
                                        ("timer_mode",       libxl_timer_mode),
                                        ("nested_hvm",       libxl_defbool),
                                        ("smbios_firmware",  string),
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index bd26bcc..013066d 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -987,6 +987,16 @@ static void parse_config_data(const char *config_source,
         xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
         xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
         xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 0);
+        if (!xlu_cfg_get_long(config, "vmware_hw",  &l, 1)) {
+            b_info->u.hvm.vmware_hw = l;
+            if (dom_info->debug)
+                fprintf(stderr, "vmware_hw: 0x%llx\n", (unsigned long long) b_info->u.hvm.vmware_hw);
+        }
+        if (!xlu_cfg_get_long(config, "vmport_logmask", &l, 1)) {
+            b_info->u.hvm.vmport_logmask = l;
+            if (dom_info->debug)
+                fprintf(stderr, "vmport_logmask: 0x%llx\n", (unsigned long long) b_info->u.hvm.vmport_logmask);
+        }
         xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
         xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
 
diff --git a/tools/libxl/xl_sxp.c b/tools/libxl/xl_sxp.c
index a16a025..9010c42 100644
--- a/tools/libxl/xl_sxp.c
+++ b/tools/libxl/xl_sxp.c
@@ -102,6 +102,10 @@ void printf_info_sexp(int domid, libxl_domain_config *d_config)
         printf("\t\t\t(nx %s)\n", libxl_defbool_to_string(b_info->u.hvm.nx));
         printf("\t\t\t(viridian %s)\n",
                libxl_defbool_to_string(b_info->u.hvm.viridian));
+        printf("\t\t\t(vmware_hw %d)\n",
+               b_info->u.hvm.vmware_hw);
+        printf("\t\t\t(vmport_logmask %x)\n",
+               b_info->u.hvm.vmport_logmask);
         printf("\t\t\t(hpet %s)\n",
                libxl_defbool_to_string(b_info->u.hvm.hpet));
         printf("\t\t\t(vpt_align %s)\n",
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 6a7a781..38641c4 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -589,6 +589,7 @@ int hvm_domain_initialise(struct domain *d)
 
     d->arch.hvm_domain.params[HVM_PARAM_HPET_ENABLED] = 1;
     d->arch.hvm_domain.params[HVM_PARAM_TRIPLE_FAULT_REASON] = SHUTDOWN_reboot;
+    d->arch.hvm_domain.params[HVM_PARAM_VMPORT_RESET_TIME] = 15;
 
     vpic_init(d);
 
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 05/10] vmport: Add VMware provided include files.
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
                   ` (3 preceding siblings ...)
  2013-12-12 19:15 ` [RFC PATCH 04/10] tools: Add support for new HVM params Don Slutz
@ 2013-12-12 19:15 ` Don Slutz
  2013-12-17 20:22   ` Konrad Rzeszutek Wilk
  2013-12-12 19:15 ` [RFC PATCH 06/10] Add vmport structs Don Slutz
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

These 2 files: backdoor_def.h and guest_msg_def.h come from:

http://packages.vmware.com/tools/esx/3.5latest/rhel4/SRPMS/index.html
 open-vm-tools-kmod-7.4.8-396269.423167.src.rpm
  open-vm-tools-kmod-7.4.8.tar.gz
   vmhgfs/backdoor_def.h
   vmhgfs/guest_msg_def.h

and are unchanged.

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 xen/arch/x86/hvm/vmport/backdoor_def.h  | 167 ++++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/vmport/guest_msg_def.h |  87 +++++++++++++++++
 2 files changed, 254 insertions(+)
 create mode 100644 xen/arch/x86/hvm/vmport/backdoor_def.h
 create mode 100644 xen/arch/x86/hvm/vmport/guest_msg_def.h

diff --git a/xen/arch/x86/hvm/vmport/backdoor_def.h b/xen/arch/x86/hvm/vmport/backdoor_def.h
new file mode 100644
index 0000000..e76795f
--- /dev/null
+++ b/xen/arch/x86/hvm/vmport/backdoor_def.h
@@ -0,0 +1,167 @@
+/* **********************************************************
+ * Copyright 1998 VMware, Inc.  All rights reserved. 
+ * **********************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/*
+ * backdoor_def.h --
+ *
+ * This contains backdoor defines that can be included from
+ * an assembly language file.
+ */
+
+
+
+#ifndef _BACKDOOR_DEF_H_
+#define _BACKDOOR_DEF_H_
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMKERNEL
+#include "includeCheck.h"
+
+/*
+ * If you want to add a new low-level backdoor call for a guest userland
+ * application, please consider using the GuestRpc mechanism instead. --hpreg
+ */
+
+#define BDOOR_MAGIC 0x564D5868
+
+/* Low-bandwidth backdoor port. --hpreg */
+
+#define BDOOR_PORT 0x5658
+
+#define BDOOR_CMD_GETMHZ      		   1
+/*
+ * BDOOR_CMD_APMFUNCTION is used by:
+ *
+ * o The FrobOS code, which instead should either program the virtual chipset
+ *   (like the new BIOS code does, matthias offered to implement that), or not
+ *   use any VM-specific code (which requires that we correctly implement
+ *   "power off on CLI HLT" for SMP VMs, boris offered to implement that)
+ *
+ * o The old BIOS code, which will soon be jettisoned
+ *
+ *  --hpreg
+ */
+#define BDOOR_CMD_APMFUNCTION 		   2
+#define BDOOR_CMD_GETDISKGEO  		   3
+#define BDOOR_CMD_GETPTRLOCATION	      4
+#define BDOOR_CMD_SETPTRLOCATION	      5
+#define BDOOR_CMD_GETSELLENGTH		   6
+#define BDOOR_CMD_GETNEXTPIECE		   7
+#define BDOOR_CMD_SETSELLENGTH		   8
+#define BDOOR_CMD_SETNEXTPIECE		   9
+#define BDOOR_CMD_GETVERSION		      10
+#define BDOOR_CMD_GETDEVICELISTELEMENT	11
+#define BDOOR_CMD_TOGGLEDEVICE		   12
+#define BDOOR_CMD_GETGUIOPTIONS		   13
+#define BDOOR_CMD_SETGUIOPTIONS		   14
+#define BDOOR_CMD_GETSCREENSIZE		   15
+#define BDOOR_CMD_MONITOR_CONTROL       16
+#define BDOOR_CMD_GETHWVERSION          17
+#define BDOOR_CMD_OSNOTFOUND            18
+#define BDOOR_CMD_GETUUID               19
+#define BDOOR_CMD_GETMEMSIZE            20
+#define BDOOR_CMD_HOSTCOPY              21 /* Devel only */
+/* BDOOR_CMD_GETOS2INTCURSOR, 22, is very old and defunct. Reuse. */
+#define BDOOR_CMD_GETTIME               23 /* Deprecated. Use GETTIMEFULL. */
+#define BDOOR_CMD_STOPCATCHUP           24
+#define BDOOR_CMD_PUTCHR	        25 /* Devel only */
+#define BDOOR_CMD_ENABLE_MSG	        26 /* Devel only */
+#define BDOOR_CMD_GOTO_TCL	        27 /* Devel only */
+#define BDOOR_CMD_INITPCIOPROM		28
+#define BDOOR_CMD_INT13			29
+#define BDOOR_CMD_MESSAGE               30
+#define BDOOR_CMD_RSVD0                 31
+#define BDOOR_CMD_RSVD1                 32
+#define BDOOR_CMD_RSVD2                 33
+#define BDOOR_CMD_ISACPIDISABLED	34
+#define BDOOR_CMD_TOE			35 /* Not in use */
+/* BDOOR_CMD_INITLSIOPROM, 36, was merged with 28. Reuse. */
+#define BDOOR_CMD_PATCH_SMBIOS_STRUCTS  37
+#define BDOOR_CMD_MAPMEM                38 /* Devel only */
+#define BDOOR_CMD_ABSPOINTER_DATA	39
+#define BDOOR_CMD_ABSPOINTER_STATUS	40
+#define BDOOR_CMD_ABSPOINTER_COMMAND	41
+#define BDOOR_CMD_TIMER_SPONGE          42
+#define BDOOR_CMD_PATCH_ACPI_TABLES	43
+/* Catch-all to allow synchronous tests */
+#define BDOOR_CMD_DEVEL_FAKEHARDWARE	44 /* Debug only - needed in beta */
+#define BDOOR_CMD_GETHZ      		45
+#define BDOOR_CMD_GETTIMEFULL           46
+#define BDOOR_CMD_STATELOGGER           47
+#define BDOOR_CMD_CHECKFORCEBIOSSETUP	48
+#define BDOOR_CMD_LAZYTIMEREMULATION    49
+#define BDOOR_CMD_BIOSBBS               50
+#define BDOOR_CMD_MAX                   51
+
+/* 
+ * IMPORTANT NOTE: When modifying the behavior of an existing backdoor command,
+ * you must adhere to the semantics expected by the oldest Tools who use that
+ * command. Specifically, do not alter the way in which the command modifies 
+ * the registers. Otherwise backwards compatibility will suffer.
+ */
+
+/* High-bandwidth backdoor port. --hpreg */
+
+#define BDOORHB_PORT 0x5659
+
+#define BDOORHB_CMD_MESSAGE 0
+#define BDOORHB_CMD_MAX 1
+
+/*
+ * There is another backdoor which allows access to certain TSC-related
+ * values using otherwise illegal PMC indices when the pseudo_perfctr
+ * control flag is set.
+ */
+
+#define BDOOR_PMC_HW_TSC      0x10000
+#define BDOOR_PMC_REAL_NS     0x10001
+#define BDOOR_PMC_APPARENT_NS 0x10002
+
+#define IS_BDOOR_PMC(index)  (((index) | 3) == 0x10003)
+#define BDOOR_CMD(ecx)       ((ecx) & 0xffff)
+
+
+#ifdef VMM
+/*
+ *----------------------------------------------------------------------
+ *
+ * Backdoor_CmdRequiresFullyValidVCPU --
+ *
+ *    A few backdoor commands require the full VCPU to be valid
+ *    (including GDTR, IDTR, TR and LDTR). The rest get read/write
+ *    access to GPRs and read access to Segment registers (selectors).
+ *
+ * Result:
+ *    True iff VECX contains a command that require the full VCPU to
+ *    be valid.
+ *
+ *----------------------------------------------------------------------
+ */
+static INLINE Bool
+Backdoor_CmdRequiresFullyValidVCPU(unsigned cmd)
+{
+   return cmd == BDOOR_CMD_RSVD0 ||
+          cmd == BDOOR_CMD_RSVD1 ||
+          cmd == BDOOR_CMD_RSVD2;
+}
+#endif
+
+#endif
diff --git a/xen/arch/x86/hvm/vmport/guest_msg_def.h b/xen/arch/x86/hvm/vmport/guest_msg_def.h
new file mode 100644
index 0000000..44ae0fa
--- /dev/null
+++ b/xen/arch/x86/hvm/vmport/guest_msg_def.h
@@ -0,0 +1,87 @@
+/* **********************************************************
+ * Copyright 1998 VMware, Inc.  All rights reserved. 
+ * **********************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/*
+ * guest_msg_def.h --
+ *
+ *    Second layer of the internal communication channel between guest
+ *    applications and vmware
+ *
+ */
+
+#ifndef _GUEST_MSG_DEF_H_
+#define _GUEST_MSG_DEF_H_
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#include "includeCheck.h"
+
+
+/* Basic request types */
+typedef enum {
+   MESSAGE_TYPE_OPEN,
+   MESSAGE_TYPE_SENDSIZE,
+   MESSAGE_TYPE_SENDPAYLOAD,
+   MESSAGE_TYPE_RECVSIZE,
+   MESSAGE_TYPE_RECVPAYLOAD,
+   MESSAGE_TYPE_RECVSTATUS,
+   MESSAGE_TYPE_CLOSE,
+} MessageType;
+
+
+/* Reply statuses */
+/*  The basic request succeeded */
+#define MESSAGE_STATUS_SUCCESS  0x0001
+/*  vmware has a message available for its party */
+#define MESSAGE_STATUS_DORECV   0x0002
+/*  The channel has been closed */
+#define MESSAGE_STATUS_CLOSED   0x0004
+/*  vmware removed the message before the party fetched it */
+#define MESSAGE_STATUS_UNSENT   0x0008
+/*  A checkpoint occurred */
+#define MESSAGE_STATUS_CPT      0x0010
+/*  An underlying device is powering off */
+#define MESSAGE_STATUS_POWEROFF 0x0020
+/*  vmware has detected a timeout on the channel */
+#define MESSAGE_STATUS_TIMEOUT  0x0040
+/*  vmware supports high-bandwidth for sending and receiving the payload */
+#define MESSAGE_STATUS_HB       0x0080
+
+/*
+ * This mask defines the status bits that the guest is allowed to set;
+ * we use this to mask out all other bits when receiving the status
+ * from the guest. Otherwise, the guest can manipulate VMX state by
+ * setting status bits that are only supposed to be changed by the
+ * VMX. See bug 45385.
+ */
+#define MESSAGE_STATUS_GUEST_MASK    MESSAGE_STATUS_SUCCESS
+
+/*
+ * Max number of channels.
+ * Unfortunately this has to be public because the monitor part
+ * of the backdoor needs it for its trivial-case optimization. [greg]
+ */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/* Flags to open a channel. --hpreg */
+#define GUESTMSG_FLAG_COOKIE 0x80000000
+#define GUESTMSG_FLAG_ALL GUESTMSG_FLAG_COOKIE
+
+
+#endif /* _GUEST_MSG_DEF_H_ */
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 06/10] Add vmport structs
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
                   ` (4 preceding siblings ...)
  2013-12-12 19:15 ` [RFC PATCH 05/10] vmport: Add VMware provided include files Don Slutz
@ 2013-12-12 19:15 ` Don Slutz
  2013-12-12 23:10   ` Andrew Cooper
  2013-12-12 19:15 ` [RFC PATCH 07/10] Add new vmport code Don Slutz
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 xen/arch/x86/hvm/hvm.c           | 59 +++++++++++++++++++++++++++++-
 xen/include/asm-x86/hvm/domain.h |  4 +++
 xen/include/asm-x86/hvm/vmport.h | 77 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 xen/include/asm-x86/hvm/vmport.h

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 38641c4..fa5d382 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -57,6 +57,7 @@
 #include <asm/hvm/cacheattr.h>
 #include <asm/hvm/trace.h>
 #include <asm/hvm/nestedhvm.h>
+#include <asm/hvm/vmport.h>
 #include <asm/mtrr.h>
 #include <asm/apic.h>
 #include <public/sched.h>
@@ -536,6 +537,7 @@ static int handle_pvh_io(
 int hvm_domain_initialise(struct domain *d)
 {
     int rc;
+    long vmport_mem = 0;
 
     if ( !hvm_enabled )
     {
@@ -562,6 +564,7 @@ int hvm_domain_initialise(struct domain *d)
 
     spin_lock_init(&d->arch.hvm_domain.irq_lock);
     spin_lock_init(&d->arch.hvm_domain.uc_lock);
+    spin_lock_init(&d->arch.hvm_domain.vmport_lock);
 
     INIT_LIST_HEAD(&d->arch.hvm_domain.msixtbl_list);
     spin_lock_init(&d->arch.hvm_domain.msixtbl_list_lock);
@@ -574,11 +577,47 @@ int hvm_domain_initialise(struct domain *d)
 
     d->arch.hvm_domain.params = xzalloc_array(uint64_t, HVM_NR_PARAMS);
     d->arch.hvm_domain.io_handler = xmalloc(struct hvm_io_handler);
+    d->arch.hvm_domain.vmport_data = xzalloc(struct vmport_state);
     rc = -ENOMEM;
-    if ( !d->arch.hvm_domain.params || !d->arch.hvm_domain.io_handler )
+    if ( !d->arch.hvm_domain.params || !d->arch.hvm_domain.io_handler ||
+         !d->arch.hvm_domain.vmport_data )
         goto fail1;
     d->arch.hvm_domain.io_handler->num_slot = 0;
 
+    vmport_mem += sizeof(struct vmport_state);
+    d->arch.hvm_domain.vmport_data->open_cookie = ('C' << 8) + 'S';
+    d->arch.hvm_domain.vmport_data->used_guestinfo = 10;
+
+    for (rc = 0; rc < d->arch.hvm_domain.vmport_data->used_guestinfo; rc++) {
+        d->arch.hvm_domain.vmport_data->guestinfo[rc] = xzalloc(vmport_guestinfo_t);
+        vmport_mem += sizeof(vmport_guestinfo_t);
+    }
+    d->arch.hvm_domain.vmport_data->guestinfo[0]->key_len = 2;
+    memcpy(d->arch.hvm_domain.vmport_data->guestinfo[0]->key_data, "ip", 2);
+
+    gdprintk(XENLOG_DEBUG, "vmport_mem=%ld bytes (%ld KiB, %ld MiB)\n",
+             vmport_mem,
+             (vmport_mem + (1 << 10) - 1) >> 10,
+             (vmport_mem + (1 << 20) - 1) >> 20);
+    vmport_mem += sizeof(uint64_t) * HVM_NR_PARAMS;
+    vmport_mem += sizeof(struct hvm_io_handler);
+    gdprintk(XENLOG_DEBUG, "hvm overhead=%ld bytes (%ld KiB, %ld MiB)\n",
+             vmport_mem,
+             (vmport_mem + (1 << 10) - 1) >> 10,
+             (vmport_mem + (1 << 20) - 1) >> 20);
+    gdprintk(XENLOG_DEBUG, "tot_pages=%d bytes (%d KiB, %d MiB)\n",
+             d->tot_pages,
+             (d->tot_pages + (1 << 10) - 1) >> 10,
+             (d->tot_pages + (1 << 20) - 1) >> 20);
+    gdprintk(XENLOG_DEBUG, "max_pages=%d bytes (%d KiB, %d MiB)\n",
+             d->max_pages,
+             (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) )
     {
         register_portio_handler(d, 0, 0x10003, handle_pvh_io);
@@ -617,6 +656,15 @@ int hvm_domain_initialise(struct domain *d)
     stdvga_deinit(d);
     vioapic_deinit(d);
  fail1:
+    if (d->arch.hvm_domain.vmport_data) {
+        struct vmport_state *vs = d->arch.hvm_domain.vmport_data;
+        int idx;
+
+        for (idx = 0; idx < vs->used_guestinfo; idx++) {
+            xfree(vs->guestinfo[idx]);
+        }
+    }
+    xfree(d->arch.hvm_domain.vmport_data);
     xfree(d->arch.hvm_domain.io_handler);
     xfree(d->arch.hvm_domain.params);
  fail0:
@@ -626,6 +674,15 @@ int hvm_domain_initialise(struct domain *d)
 
 void hvm_domain_relinquish_resources(struct domain *d)
 {
+    if (d->arch.hvm_domain.vmport_data) {
+        struct vmport_state *vs = d->arch.hvm_domain.vmport_data;
+        int idx;
+
+        for (idx = 0; idx < vs->used_guestinfo; idx++) {
+            xfree(vs->guestinfo[idx]);
+        }
+        xfree(d->arch.hvm_domain.vmport_data);
+    }
     xfree(d->arch.hvm_domain.io_handler);
     xfree(d->arch.hvm_domain.params);
 
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index b1e3187..0ca2778 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -62,6 +62,10 @@ struct hvm_domain {
     /* emulated irq to pirq */
     struct radix_tree_root emuirq_pirq;
 
+    /* VMware special port */
+    spinlock_t             vmport_lock;
+    struct  vmport_state  *vmport_data;
+
     uint64_t              *params;
 
     /* Memory ranges with pinned cache attributes. */
diff --git a/xen/include/asm-x86/hvm/vmport.h b/xen/include/asm-x86/hvm/vmport.h
new file mode 100644
index 0000000..180ddac
--- /dev/null
+++ b/xen/include/asm-x86/hvm/vmport.h
@@ -0,0 +1,77 @@
+/*
+ * vmport.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 __ASM_X86_HVM_VMPORT_H__
+#define __ASM_X86_HVM_VMPORT_H__
+
+/* Note: VMPORT_PORT and VMPORT_MAGIC is also defined as BDOOR_PORT
+ * and BDOOR_MAGIC in backdoor_def.h Defined here so that other
+ * parts of XEN can use it.
+ */
+
+#define VMPORT_PORT 0x5658
+#define VMPORT_MAGIC 0x564D5868
+
+#define VMPORT_MAX_KEY_LEN 30
+#define VMPORT_MAX_VAL_LEN 128
+#define VMPORT_MAX_NUM_KEY 128
+
+#define VMPORT_MAX_SEND_BUF ((22 + VMPORT_MAX_KEY_LEN + VMPORT_MAX_VAL_LEN + 3)/4)
+#define VMPORT_MAX_RECV_BUF ((2 + VMPORT_MAX_VAL_LEN + 3)/4)
+#define VMPORT_MAX_CHANS    4
+#define VMPORT_MAX_BKTS     8
+
+
+typedef struct vmport_guestinfo_ {
+    uint8_t key_len;
+    uint8_t val_len;
+    char key_data[VMPORT_MAX_KEY_LEN];
+    char val_data[VMPORT_MAX_VAL_LEN];
+} vmport_guestinfo_t;
+
+typedef struct vmport_bucket_ {
+    uint16_t recv_len;
+    uint16_t recv_idx;
+    uint32_t recv_buf[VMPORT_MAX_RECV_BUF + 1];
+    uint8_t  recv_slot;
+} vmport_bucket_t;
+
+typedef struct vmport_channel_ {
+    unsigned long active_time;
+    uint32_t chan_id;
+    uint32_t cookie;
+    uint32_t proto_num;
+    uint16_t send_len;
+    uint16_t send_idx;
+    uint32_t send_buf[VMPORT_MAX_SEND_BUF + 1];
+    vmport_bucket_t recv_bkt[VMPORT_MAX_BKTS];
+    uint8_t recv_read;
+    uint8_t recv_write;
+} vmport_channel_t;
+
+struct vmport_state {
+    unsigned long ping_time;
+    uint32_t open_cookie;
+    uint32_t used_guestinfo;
+    vmport_channel_t chans[VMPORT_MAX_CHANS];
+    vmport_guestinfo_t *guestinfo[VMPORT_MAX_NUM_KEY];
+};
+
+int vmport_ioport(int dir, int size, unsigned long data, struct cpu_user_regs *regs);
+void vmport_ctrl_send(struct hvm_domain *hd, char *msg, int slot);
+void vmport_flush(struct hvm_domain *hd);
+
+#endif /* __ASM_X86_HVM_VMPORT_H__ */
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 07/10] Add new vmport code.
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
                   ` (5 preceding siblings ...)
  2013-12-12 19:15 ` [RFC PATCH 06/10] Add vmport structs Don Slutz
@ 2013-12-12 19:15 ` Don Slutz
  2013-12-13  0:06   ` Andrew Cooper
                     ` (2 more replies)
  2013-12-12 19:15 ` [RFC PATCH 08/10] connect vmport up Don Slutz
                   ` (3 subsequent siblings)
  10 siblings, 3 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

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

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 08/10] connect vmport up
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
                   ` (6 preceding siblings ...)
  2013-12-12 19:15 ` [RFC PATCH 07/10] Add new vmport code Don Slutz
@ 2013-12-12 19:15 ` Don Slutz
  2013-12-13  0:51   ` Andrew Cooper
                     ` (2 more replies)
  2013-12-12 19:15 ` [RFC PATCH 09/10] libxl: Add VTPOWER, VTREBOOT and VTPING Don Slutz
                   ` (2 subsequent siblings)
  10 siblings, 3 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 xen/arch/x86/hvm/io.c       |   4 ++
 xen/arch/x86/hvm/svm/svm.c  | 104 ++++++++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/svm/vmcb.c |   1 +
 xen/arch/x86/hvm/vmx/vmcs.c |   1 +
 xen/arch/x86/hvm/vmx/vmx.c  | 125 ++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/vmx/vvmx.c |  13 +++++
 xen/include/public/trace.h  |   1 +
 7 files changed, 249 insertions(+)

diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index bf6309d..4bc4716 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -42,6 +42,7 @@
 #include <asm/hvm/vlapic.h>
 #include <asm/hvm/trace.h>
 #include <asm/hvm/emulate.h>
+#include <asm/hvm/vmport.h>
 #include <public/sched.h>
 #include <xen/iocap.h>
 #include <public/hvm/ioreq.h>
@@ -236,6 +237,9 @@ int handle_pio(uint16_t port, unsigned int size, int dir)
     if ( dir == IOREQ_WRITE )
         data = guest_cpu_user_regs()->eax;
 
+    if ( port == VMPORT_PORT )
+        return vmport_ioport(dir, size, data, guest_cpu_user_regs());
+
     rc = hvmemul_do_pio(port, &reps, size, 0, dir, 0, &data);
 
     switch ( rc )
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 406d394..80cf2bf 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -56,6 +56,7 @@
 #include <asm/hvm/svm/nestedsvm.h>
 #include <asm/hvm/nestedhvm.h>
 #include <asm/x86_emulate.h>
+#include <asm/hvm/vmport.h>
 #include <public/sched.h>
 #include <asm/hvm/vpt.h>
 #include <asm/hvm/trace.h>
@@ -1904,6 +1905,105 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
     return;
 }
 
+static void svm_vmexit_gp_intercept(struct cpu_user_regs *regs, struct vcpu *v)
+{
+    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    unsigned long inst_len, bytes_len;
+    int frc;
+    unsigned char bytes[15];
+
+    regs->error_code = vmcb->exitinfo1;
+    if ( !cpu_has_svm_nrips || (vmcb->nextrip <= vmcb->rip) )
+        inst_len = 0;
+    else
+        inst_len = vmcb->nextrip - vmcb->rip;
+    bytes_len = 2 /* inst_len < 15 ? inst_len > 1 ? inst_len : 2 : 15 */;
+    frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
+                                            bytes_len,
+                                            PFEC_page_present);
+
+    if ( hvm_long_mode_enabled(v) )
+        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
+                         regs->error_code,
+                         TRC_PAR_LONG(vmcb->exitinfo2) );
+    else
+        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
+                    regs->error_code, vmcb->exitinfo2 );
+
+    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* LOG_GP_FAIL_RD_INST */)
+        printk("[HVM:%d.%d] <%s> "
+               "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%ld,%d) nip(%d)=%lx(%d,%d(0x%x) 0x%x 0x%x)"
+               "\n",
+               current->domain->domain_id, current->vcpu_id, __func__,
+               (unsigned long)vmcb->exitinfo2,
+               (unsigned long)regs->error_code,
+               (unsigned long)regs->eip, (unsigned int)bytes[0],
+               (unsigned int)bytes[1], bytes_len, inst_len, frc,
+               cpu_has_svm_nrips, (unsigned long)vmcb->nextrip,
+               cpu_has_svm_decode, vmcb->guest_ins_len & 0xf, vmcb->guest_ins_len,
+               vmcb->guest_ins[0], vmcb->guest_ins[1]);
+
+    if ( !frc && bytes[0] == 0xed && (regs->edx & 0xffff) == VMPORT_PORT &&
+         vmcb->exitinfo2 == 0 && regs->error_code == 0 )
+    {
+        /*  in (%dx),%eax */
+        uint32_t magic = regs->eax;
+
+        if ( magic == VMPORT_MAGIC ) {
+            __update_guest_eip(regs, 1);
+            vmport_ioport(IOREQ_READ, 4, 0, regs);
+            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* LOG_GP_VMWARE_AFTER */)
+                printk("[HVM:%d.%d] <%s> "
+                       "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
+                       "\n",
+                       current->domain->domain_id, current->vcpu_id, __func__,
+                       (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);
+            return;
+        } else {
+            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* LOG_GP_NOT_VMWARE */)
+                printk("[HVM:%d.%d] <%s> "
+                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
+                       "\n",
+                       current->domain->domain_id, current->vcpu_id, __func__,
+                       (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);
+            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
+        }
+    } else if (!frc && regs->error_code == 0
+               && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx == 0x10000)
+    {
+        /* "rdpmc 0x10000" */
+        /* Not a very good emulation!  But just not faulting is good enough
+         * to get NetApp booting. */
+        regs->edx = regs->eax = 0;
+
+        __update_guest_eip(regs, inst_len);
+
+        /* Doing the log in this case was too noisy for NetApp, so I moved
+         * it to 'else' */
+    } else {
+        if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x100000 /* LOG_GP_UNKNOWN */) {
+            printk("[HVM:%d.%d] <%s> "
+                   "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
+                   "\n",
+                   current->domain->domain_id, current->vcpu_id, __func__,
+                   (unsigned long)vmcb->exitinfo2, (unsigned long)regs->error_code,
+                   (unsigned long)regs->eip, (unsigned int)bytes[0],
+                   (unsigned int)bytes[1], inst_len, frc,
+                   (unsigned long)regs->eax, (unsigned long)regs->ebx,
+                   (unsigned long)regs->ecx, (unsigned long)regs->edx,
+                   (unsigned long)regs->esi, (unsigned long)regs->edi);
+        }
+        hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
+    }
+}
+
 static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)
 {
     struct hvm_emulate_ctxt ctxt;
@@ -2253,6 +2353,10 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
         break;
     }
 
+    case VMEXIT_EXCEPTION_GP:
+        svm_vmexit_gp_intercept(regs, v);
+        break;
+
     case VMEXIT_EXCEPTION_UD:
         svm_vmexit_ud_intercept(regs);
         break;
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
index 21292bb..791c045 100644
--- a/xen/arch/x86/hvm/svm/vmcb.c
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -193,6 +193,7 @@ static int construct_vmcb(struct vcpu *v)
 
     vmcb->_exception_intercepts =
         HVM_TRAP_MASK
+        | (1U << TRAP_gp_fault)
         | (1U << TRAP_no_device);
 
     if ( paging_mode_hap(v->domain) )
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 44f33cb..21cde2f 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -1074,6 +1074,7 @@ static int construct_vmcs(struct vcpu *v)
 
     v->arch.hvm_vmx.exception_bitmap = HVM_TRAP_MASK
               | (paging_mode_hap(d) ? 0 : (1U << TRAP_page_fault))
+              | (1U << TRAP_gp_fault)
               | (1U << TRAP_no_device);
     vmx_update_exception_bitmap(v);
 
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index dfff628..248900d 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -44,6 +44,7 @@
 #include <asm/hvm/support.h>
 #include <asm/hvm/vmx/vmx.h>
 #include <asm/hvm/vmx/vmcs.h>
+#include <asm/hvm/vmport.h>
 #include <public/sched.h>
 #include <public/hvm/ioreq.h>
 #include <asm/hvm/vpic.h>
@@ -1211,6 +1212,7 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
                 v->arch.hvm_vmx.exception_bitmap = HVM_TRAP_MASK
                           | (paging_mode_hap(v->domain) ?
                              0 : (1U << TRAP_page_fault))
+                          | (1U << TRAP_gp_fault)
                           | (1U << TRAP_no_device);
                 vmx_update_exception_bitmap(v);
                 vmx_update_debug_state(v);
@@ -2454,6 +2456,113 @@ static void vmx_idtv_reinject(unsigned long idtv_info)
     }
 }
 
+void do_gp_fault(struct cpu_user_regs *regs, struct vcpu *v)
+{
+    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
+    unsigned long exit_qualification;
+    unsigned long inst_len;
+    unsigned long ecode;
+
+    __vmread(EXIT_QUALIFICATION, &exit_qualification);
+    __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
+    __vmread(VM_EXIT_INTR_ERROR_CODE, &ecode);
+    regs->error_code = ecode;
+    if ( hvm_long_mode_enabled(v) )
+        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
+                         regs->error_code,
+                         TRC_PAR_LONG(exit_qualification) );
+    else
+        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
+                    regs->error_code, exit_qualification );
+
+    if ( inst_len == 1 && (regs->edx & 0xffff) == VMPORT_PORT &&
+         exit_qualification == 0 && regs->error_code == 0 ) {
+        uint32_t magic = regs->eax;
+
+        if ( magic == VMPORT_MAGIC ) {
+            unsigned char bytes[1];
+            int frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
+                                                        1, PFEC_page_present);
+            if (!frc && bytes[0] == 0xed) { /*  in (%dx),%eax */
+                update_guest_eip();
+                vmport_ioport(IOREQ_READ, 4, 0, regs);
+                if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* LOG_GP_VMWARE_AFTER */)
+                    printk("[HVM:%d.%d] <%s> "
+                           "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
+                           "\n",
+                           current->domain->domain_id, current->vcpu_id, __func__,
+                           (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);
+                return;
+            } else {
+                if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* LOG_GP_FAIL_RD_INST */)
+                    printk("[HVM:%d.%d] <%s> "
+                           "gp: VMware? ip=%lx=>0x%x(%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
+                           "\n",
+                           current->domain->domain_id, current->vcpu_id, __func__,
+                           (unsigned long)regs->eip, bytes[0], frc,
+                           (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 (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* LOG_GP_NOT_VMWARE */)
+                printk("[HVM:%d.%d] <%s> "
+                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
+                       "\n",
+                       current->domain->domain_id, current->vcpu_id, __func__,
+                       (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);
+            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
+        }
+    } else {
+        unsigned char bytes[15];
+        int frc;
+
+        /*
+         * We can conditionalize this call on inst_len == 2 if we decide to
+         * remove the following printk.
+         */
+        frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
+                                                inst_len < 15 ? inst_len : 15,
+                                                PFEC_page_present);
+
+        /* Emulate "rdpmc 0x10000" */
+        if (!frc && inst_len == 2 && regs->error_code == 0
+            && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx == 0x10000)
+        {
+            /* Not a very good emulation!  But just not faulting is good enough
+             * to get NetApp booting. */
+            regs->edx = regs->eax = 0;
+
+            update_guest_eip();
+
+            /* Doing the log in this case was too noisy for NetApp, so I moved
+             * it to 'else' */
+        } else {
+            /* We should probably turn this log off by default in production in
+             * case somebody decides to do a lot of #GPs. */
+            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x100000 /* LOG_GP_UNKNOWN */) {
+                printk("[HVM:%d.%d] <%s> "
+                       "gp: eq=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
+                       "\n",
+                       current->domain->domain_id, current->vcpu_id, __func__,
+                       (unsigned long)exit_qualification, (unsigned long)regs->error_code,
+                       (unsigned long)regs->eip, (unsigned int)bytes[0],
+                       (unsigned int)bytes[1], inst_len, frc,
+                       (unsigned long)regs->eax, (unsigned long)regs->ebx,
+                       (unsigned long)regs->ecx, (unsigned long)regs->edx,
+                       (unsigned long)regs->esi, (unsigned long)regs->edi);
+            }
+            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
+        }
+    }
+}
+
 static int vmx_handle_apic_write(void)
 {
     unsigned long exit_qualification;
@@ -2562,6 +2671,19 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
                  && vector != TRAP_nmi 
                  && vector != TRAP_machine_check ) 
             {
+                if (vector == TRAP_gp_fault ) {
+                    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
+
+                    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x8000000 /* LOG_REALMODE_GP */)
+                        printk("[HVM:%d.%d] <%s> "
+                               "realmode gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
+                               "\n",
+                               current->domain->domain_id, current->vcpu_id, __func__,
+                               (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);
+                }
                 perfc_incr(realmode_exits);
                 v->arch.hvm_vmx.vmx_emulate = 1;
                 HVMTRACE_0D(REALMODE_EMULATE);
@@ -2677,6 +2799,9 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
             HVMTRACE_1D(TRAP, vector);
             vmx_fpu_dirty_intercept();
             break;
+        case TRAP_gp_fault:
+            do_gp_fault(regs, v);
+            break;
         case TRAP_page_fault:
             __vmread(EXIT_QUALIFICATION, &exit_qualification);
             __vmread(VM_EXIT_INTR_ERROR_CODE, &ecode);
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 0daad79..fcd03dd 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -2166,6 +2166,19 @@ int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs,
             if ( v->fpu_dirtied )
                 nvcpu->nv_vmexit_pending = 1;
         }
+        else if ( vector == TRAP_gp_fault )
+        {
+            struct cpu_user_regs *ur = guest_cpu_user_regs();
+            struct hvm_domain *hd = &v->domain->arch.hvm_domain;
+
+            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x1000000 /* LOG_VGP_UNKNOWN */)
+                gdprintk(XENLOG_ERR, "Unexpected gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx\n",
+                         (unsigned long)ur->eip,
+                         (unsigned long)ur->eax, (unsigned long)ur->ebx,
+                         (unsigned long)ur->ecx, (unsigned long)ur->edx,
+                         (unsigned long)ur->esi, (unsigned long)ur->edi);
+                nvcpu->nv_vmexit_pending = 1;
+        }
         else if ( (intr_info & valid_mask) == valid_mask )
         {
             exec_bitmap =__get_vvmcs(nvcpu->nv_vvmcx, EXCEPTION_BITMAP);
diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h
index e2f60a6..32489f0 100644
--- a/xen/include/public/trace.h
+++ b/xen/include/public/trace.h
@@ -223,6 +223,7 @@
 #define TRC_HVM_NPF             (TRC_HVM_HANDLER + 0x21)
 #define TRC_HVM_REALMODE_EMULATE (TRC_HVM_HANDLER + 0x22)
 #define TRC_HVM_TRAP             (TRC_HVM_HANDLER + 0x23)
+#define TRC_HVM_TRAP64           (TRC_HVM_HANDLER + TRC_64_FLAG + 0x23)
 #define TRC_HVM_TRAP_DEBUG       (TRC_HVM_HANDLER + 0x24)
 #define TRC_HVM_VLAPIC           (TRC_HVM_HANDLER + 0x25)
 
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 09/10] libxl: Add VTPOWER, VTREBOOT and VTPING
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
                   ` (7 preceding siblings ...)
  2013-12-12 19:15 ` [RFC PATCH 08/10] connect vmport up Don Slutz
@ 2013-12-12 19:15 ` 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-17 19:03 ` [RFC PATCH 00/10] Xen VMware tools support Konrad Rzeszutek Wilk
  10 siblings, 2 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

From: Don Slutz <dslutz@verizon.com>

Signed-off-by: Don Slutz <dslutz@verizon.com>
---
 tools/libxl/libxl.c         | 12 ++++++++++++
 tools/libxl/libxl_types.idl |  3 +++
 tools/libxl/xl_cmdtable.c   |  2 +-
 xen/arch/x86/domctl.c       | 34 ++++++++++++++++++++++++++++++++++
 xen/include/public/domctl.h |  3 +++
 5 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index fd8b988..1ec8484 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -5057,6 +5057,18 @@ int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid,
         rc = xc_domain_send_trigger(ctx->xch, domid,
                                     XEN_DOMCTL_SENDTRIGGER_SLEEP, vcpuid);
         break;
+    case LIBXL_TRIGGER_VTPOWER:
+        rc = xc_domain_send_trigger(ctx->xch, domid,
+                                    XEN_DOMCTL_SENDTRIGGER_VTPOWER, vcpuid);
+        break;
+    case LIBXL_TRIGGER_VTREBOOT:
+        rc = xc_domain_send_trigger(ctx->xch, domid,
+                                    XEN_DOMCTL_SENDTRIGGER_VTREBOOT, vcpuid);
+        break;
+    case LIBXL_TRIGGER_VTPING:
+        rc = xc_domain_send_trigger(ctx->xch, domid,
+                                    XEN_DOMCTL_SENDTRIGGER_VTPING, vcpuid);
+        break;
     case LIBXL_TRIGGER_NMI:
         rc = xc_domain_send_trigger(ctx->xch, domid,
                                     XEN_DOMCTL_SENDTRIGGER_NMI, vcpuid);
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 71ba64e..80a8ee8 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -105,6 +105,9 @@ libxl_trigger = Enumeration("trigger", [
     (4, "INIT"),
     (5, "RESET"),
     (6, "S3RESUME"),
+    (7, "VTPOWER"),
+    (8, "VTREBOOT"),
+    (9, "VTPING"),
     ])
 
 libxl_tsc_mode = Enumeration("tsc_mode", [
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index ebe0220..98db8ae 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -290,7 +290,7 @@ struct cmd_spec cmd_table[] = {
     { "trigger",
       &main_trigger, 0, 1,
       "Send a trigger to a domain",
-      "<Domain> <nmi|reset|init|power|sleep|s3resume> [<VCPU>]",
+      "<Domain> <nmi|reset|init|power|sleep|s3resume|vtpower|vtreboot|vtping> [<VCPU>]",
     },
     { "sysrq",
       &main_sysrq, 0, 1,
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index ef6c140..8b77ce2 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -23,6 +23,7 @@
 #include <xen/paging.h>
 #include <asm/irq.h>
 #include <asm/hvm/hvm.h>
+#include <asm/hvm/vmport.h>
 #include <asm/hvm/support.h>
 #include <asm/hvm/cacheattr.h>
 #include <asm/processor.h>
@@ -577,6 +578,39 @@ long arch_do_domctl(
         }
         break;
 
+        case XEN_DOMCTL_SENDTRIGGER_VTPOWER:
+        {
+            ret = -EINVAL;
+            if ( is_hvm_domain(d) )
+            {
+                ret = 0;
+                vmport_ctrl_send(&d->arch.hvm_domain, "OS_Halt", 1);
+            }
+        }
+        break;
+
+        case XEN_DOMCTL_SENDTRIGGER_VTREBOOT:
+        {
+            ret = -EINVAL;
+            if ( is_hvm_domain(d) )
+            {
+                ret = 0;
+                vmport_ctrl_send(&d->arch.hvm_domain, "OS_Reboot", 2);
+            }
+        }
+        break;
+
+        case XEN_DOMCTL_SENDTRIGGER_VTPING:
+        {
+            ret = -EINVAL;
+            if ( is_hvm_domain(d) )
+            {
+                ret = 0;
+                vmport_ctrl_send(&d->arch.hvm_domain, "ping", 3);
+            }
+        }
+        break;
+
         default:
             ret = -ENOSYS;
         }
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 01a3652..d71d57c 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -454,6 +454,9 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t);
 #define XEN_DOMCTL_SENDTRIGGER_INIT   2
 #define XEN_DOMCTL_SENDTRIGGER_POWER  3
 #define XEN_DOMCTL_SENDTRIGGER_SLEEP  4
+#define XEN_DOMCTL_SENDTRIGGER_VTPOWER  5
+#define XEN_DOMCTL_SENDTRIGGER_VTREBOOT 6
+#define XEN_DOMCTL_SENDTRIGGER_VTPING   7
 struct xen_domctl_sendtrigger {
     uint32_t  trigger;  /* IN */
     uint32_t  vcpu;     /* IN */
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC PATCH 10/10] Add VMware guest info access
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
                   ` (8 preceding siblings ...)
  2013-12-12 19:15 ` [RFC PATCH 09/10] libxl: Add VTPOWER, VTREBOOT and VTPING Don Slutz
@ 2013-12-12 19:15 ` Don Slutz
  2013-12-13  1:08   ` Andrew Cooper
                     ` (2 more replies)
  2013-12-17 19:03 ` [RFC PATCH 00/10] Xen VMware tools support Konrad Rzeszutek Wilk
  10 siblings, 3 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-12 19:15 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Don Slutz, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

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

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 01/10] smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME.
  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
  0 siblings, 1 reply; 54+ messages in thread
From: Olaf Hering @ 2013-12-12 19:35 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Thu, Dec 12, Don Slutz wrote:

> -    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU");
> +    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU plus VMware-Tools");

This will break other code which checks for the current string.
(/sys/class/dmi/id/product_name)

Olaf

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 01/10] smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME.
  2013-12-12 19:35   ` Olaf Hering
@ 2013-12-12 22:07     ` Andrew Cooper
  2013-12-13 18:03       ` Don Slutz
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Cooper @ 2013-12-12 22:07 UTC (permalink / raw)
  To: Don Slutz
  Cc: Olaf Hering, Keir Fraser, Ian Campbell, Stefano Stabellini,
	Ian Jackson, Eddie Dong, xen-devel, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/12/2013 19:35, Olaf Hering wrote:
> On Thu, Dec 12, Don Slutz wrote:
>
>> -    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU");
>> +    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU plus VMware-Tools");
> This will break other code which checks for the current string.
> (/sys/class/dmi/id/product_name)
>
> Olaf

Furthermore, the whole point of this is so the toolstack can write the
xenstore key

/local/domain/$DOMID/bios-strings/system-product-name

with a custom value which will be written into the SMBios table.

The toolstack itself should have a big "pretend to be vmware" flag for a
domain.

~Andrew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 03/10] Add cpuid_vmware_leaves
  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-17 16:20     ` Don Slutz
  0 siblings, 2 replies; 54+ messages in thread
From: Andrew Cooper @ 2013-12-12 22:27 UTC (permalink / raw)
  To: Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/2013 19:15, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
>
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  xen/arch/x86/hvm/hvm.c          |  3 +++
>  xen/arch/x86/traps.c            | 58 ++++++++++++++++++++++++++++++++++++++++-
>  xen/include/asm-x86/hvm/hvm.h   |  3 +++
>  xen/include/asm-x86/processor.h |  2 ++
>  4 files changed, 65 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 69f7e74..6a7a781 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -2878,6 +2878,9 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
>      if ( cpuid_viridian_leaves(input, eax, ebx, ecx, edx) )
>          return;
>  
> +    if ( cpuid_vmware_leaves(input, count, eax, ebx, ecx, edx) )
> +        return;
> +
>      if ( cpuid_hypervisor_leaves(input, count, eax, ebx, ecx, edx) )
>          return;
>  
> diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
> index 940bc33..71a76df 100644
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -671,14 +671,70 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
>      return 0;
>  }
>  
> +int cpuid_vmware_leaves(uint32_t idx, uint32_t sub_idx,
> +                        uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
> +{
> +    struct domain *d = current->domain;
> +    /* Optionally shift out of the way of Viridian architectural leaves. */
> +    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
> +    uint32_t limit;
> +    const uint32_t apic_khz = 1000000L;

Please use the proper constant for this.

> +
> +    if ( !is_vmware_domain(d) )
> +        return 0;
> +
> +    idx -= base;
> +
> +    limit = 0x10;
> +
> +    if ( idx > limit )
> +        return 0;

This `limit` is pointless and the BUG() below is dead code (which
Coverity will complain about).

Please see 839b966e3f587bbb1a0d954230fb3904330dccb6 and follow its
style, rather than propagating this bad style (which admittedly you have
gotten from following cpuid_hypervisor_leaves() )

> +
> +    switch ( idx )
> +    {
> +    case 0:
> +        *eax = base + limit; /* Largest leaf */
> +        *ebx = 0x61774d56; /* "VMwa" */
> +        *ecx = 0x4d566572; /* "reVM" */
> +        *edx = 0x65726177; /* "ware" */
> +        break;
> +
> +    case 1 ... 0xf:
> +        *eax = 0;          /* Reserved */
> +        *ebx = 0;          /* Reserved */
> +        *ecx = 0;          /* Reserved */
> +        *edx = 0;          /* Reserved */
> +        break;
> +
> +    case 0x10:
> +        /* (Virtual) TSC frequency in kHz. */
> +        *eax =  d->arch.tsc_khz;
> +        /* (Virtual) Bus (local apic timer) frequency in kHz. */
> +        *ebx = apic_khz;
> +        *ecx = 0;          /* Reserved */
> +        *edx = 0;          /* Reserved */
> +        break;
> +
> +    default:
> +        BUG();
> +    }
> +
> +    return 1;
> +}
> +
>  int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
>                 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
>  {
>      struct domain *d = current->domain;
>      /* Optionally shift out of the way of Viridian architectural leaves. */
> -    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
> +    uint32_t base = 0x40000000;
>      uint32_t limit;
>  
> +    if ( is_viridian_domain(d) )
> +        base += 0x100;
> +    if ( is_vmware_domain(d) )
> +        base += 0x100;
> +

These bases need a far more scalable solution, especially as the result
of each of these clauses can be changed at runtime with a cunning
hvm_param_set hypercall.

I think that both "is pretending to be HyperV" and "is pretending to be
VMware" need to be domain creation flags which are strictly static for
the lifetime of the domain.

~Andrew

>      idx -= base;
>  
>      /*
> diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
> index ccca5df..ae3768c 100644
> --- a/xen/include/asm-x86/hvm/hvm.h
> +++ b/xen/include/asm-x86/hvm/hvm.h
> @@ -332,6 +332,9 @@ static inline unsigned long hvm_get_shadow_gs_base(struct vcpu *v)
>  #define is_viridian_domain(_d)                                             \
>   (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VIRIDIAN]))
>  
> +#define is_vmware_domain(_d)                                             \
> + (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VMWARE_HW]))
> +
>  void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
>                                     unsigned int *ecx, unsigned int *edx);
>  void hvm_migrate_timers(struct vcpu *v);
> diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
> index c120460..6c53e45 100644
> --- a/xen/include/asm-x86/processor.h
> +++ b/xen/include/asm-x86/processor.h
> @@ -559,6 +559,8 @@ void int80_direct_trap(void);
>  
>  extern int hypercall(void);
>  
> +int cpuid_vmware_leaves( uint32_t idx, uint32_t sub_idx,
> +          uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
>  int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
>            uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
>  int rdmsr_hypervisor_regs(uint32_t idx, uint64_t *val);

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 02/10] Add VMware HVM params
  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-17 20:02   ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 54+ messages in thread
From: Andrew Cooper @ 2013-12-12 22:32 UTC (permalink / raw)
  To: Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/2013 19:15, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
>
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  xen/include/public/hvm/params.h | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
> index 517a184..c571a1e 100644
> --- a/xen/include/public/hvm/params.h
> +++ b/xen/include/public/hvm/params.h
> @@ -145,6 +145,15 @@
>  /* SHUTDOWN_* action in case of a triple fault */
>  #define HVM_PARAM_TRIPLE_FAULT_REASON 31
>  
> -#define HVM_NR_PARAMS          32
> +/* Params for VMware */
> +#define HVM_PARAM_VMWARE_HW                 32
> +#define HVM_PARAM_VMPORT_LOGMASK            33
> +#define HVM_PARAM_VMPORT_STATUS             34
> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_TIME  35
> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_VALUE 36
> +#define HVM_PARAM_VMPORT_RESET_TIME         37
> +
> +#define HVM_NR_PARAMS          38
> +
>  
>  #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */

STATUS at the very least sounds like it should be read-only from domains?

You might want/need some extra logic in do_hvm_op().

~Andrew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 04/10] tools: Add support for new HVM params
  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
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Cooper @ 2013-12-12 22:36 UTC (permalink / raw)
  To: Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/2013 19:15, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
>
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  tools/libxc/xc_domain_restore.c | 27 +++++++++++++++++++++++++++
>  tools/libxc/xc_domain_save.c    | 24 ++++++++++++++++++++++++
>  tools/libxc/xg_save_restore.h   |  2 ++
>  tools/libxl/libxl_create.c      |  4 +++-
>  tools/libxl/libxl_dom.c         |  5 +++++
>  tools/libxl/libxl_types.idl     |  2 ++
>  tools/libxl/xl_cmdimpl.c        | 10 ++++++++++
>  tools/libxl/xl_sxp.c            |  4 ++++
>  xen/arch/x86/hvm/hvm.c          |  1 +
>  9 files changed, 78 insertions(+), 1 deletion(-)
>
> diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
> index 80769a7..9bfb608 100644
> --- a/tools/libxc/xc_domain_restore.c
> +++ b/tools/libxc/xc_domain_restore.c
> @@ -746,6 +746,8 @@ typedef struct {
>      uint64_t acpi_ioport_location;
>      uint64_t viridian;
>      uint64_t vm_generationid_addr;
> +    uint64_t vmware_hw;
> +    uint64_t vmport_logmask;
>  
>      struct toolstack_data_t tdata;
>  } pagebuf_t;
> @@ -930,6 +932,26 @@ static int pagebuf_get_one(xc_interface *xch, struct restore_ctx *ctx,
>          }
>          return pagebuf_get_one(xch, ctx, buf, fd, dom);
>  
> +    case XC_SAVE_ID_HVM_VMWARE_HW:
> +        /* Skip padding 4 bytes then read the vmware flag. */
> +        if ( RDEXACT(fd, &buf->vmware_hw, sizeof(uint32_t)) ||
> +             RDEXACT(fd, &buf->vmware_hw, sizeof(uint64_t)) )
> +        {
> +            PERROR("error read the vmware_hw value");
> +            return -1;
> +        }
> +        return pagebuf_get_one(xch, ctx, buf, fd, dom);
> +
> +    case XC_SAVE_ID_HVM_VMPORT_LOGMASK:
> +        /* Skip padding 4 bytes then read the vmport_logmask flag. */
> +        if ( RDEXACT(fd, &buf->vmport_logmask, sizeof(uint32_t)) ||
> +             RDEXACT(fd, &buf->vmport_logmask, sizeof(uint64_t)) )
> +        {
> +            PERROR("error read the vmport_logmask flag");
> +            return -1;
> +        }
> +        return pagebuf_get_one(xch, ctx, buf, fd, dom);
> +
>      case XC_SAVE_ID_TOOLSTACK:
>          {
>              if ( RDEXACT(fd, &buf->tdata.len, sizeof(buf->tdata.len)) )
> @@ -1755,6 +1777,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
>      if (pagebuf.viridian != 0)
>          xc_set_hvm_param(xch, dom, HVM_PARAM_VIRIDIAN, 1);
>  
> +    if (pagebuf.vmware_hw != 0)
> +        xc_set_hvm_param(xch, dom, HVM_PARAM_VMWARE_HW, pagebuf.vmport_logmask);
> +    if (pagebuf.vmport_logmask != 0)
> +        xc_set_hvm_param(xch, dom, HVM_PARAM_VMPORT_LOGMASK, pagebuf.vmport_logmask);
> +
>      if (pagebuf.acpi_ioport_location == 1) {
>          DBGPRINTF("Use new firmware ioport from the checkpoint\n");
>          xc_set_hvm_param(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
> diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
> index 42c4752..dac7c2c 100644
> --- a/tools/libxc/xc_domain_save.c
> +++ b/tools/libxc/xc_domain_save.c
> @@ -1731,6 +1731,30 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
>              PERROR("Error when writing the viridian flag");
>              goto out;
>          }
> +
> +        chunk.id = XC_SAVE_ID_HVM_VMWARE_HW;
> +        chunk.data = 0;
> +        xc_get_hvm_param(xch, dom, HVM_PARAM_VMWARE_HW,
> +                         (unsigned long *)&chunk.data);
> +
> +        if ( (chunk.data != 0) &&
> +             wrexact(io_fd, &chunk, sizeof(chunk)) )
> +        {
> +            PERROR("Error when writing the vmware_hw");
> +            goto out;
> +        }
> +
> +        chunk.id = XC_SAVE_ID_HVM_VMPORT_LOGMASK;
> +        chunk.data = 0;
> +        xc_get_hvm_param(xch, dom, HVM_PARAM_VMPORT_LOGMASK,
> +                         (unsigned long *)&chunk.data);
> +
> +        if ( (chunk.data != 0) &&
> +             wrexact(io_fd, &chunk, sizeof(chunk)) )
> +        {
> +            PERROR("Error when writing the vmport_loglvl");
> +            goto out;
> +        }
>      }
>  
>      if ( callbacks != NULL && callbacks->toolstack_save != NULL )
> diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h
> index f859621..69f44de 100644
> --- a/tools/libxc/xg_save_restore.h
> +++ b/tools/libxc/xg_save_restore.h
> @@ -259,6 +259,8 @@
>  #define XC_SAVE_ID_HVM_ACCESS_RING_PFN  -16
>  #define XC_SAVE_ID_HVM_SHARING_RING_PFN -17
>  #define XC_SAVE_ID_TOOLSTACK          -18 /* Optional toolstack specific info */
> +#define XC_SAVE_ID_HVM_VMWARE_HW      -19
> +#define XC_SAVE_ID_HVM_VMPORT_LOGMASK -20
>  
>  /*
>  ** We process save/restore/migrate in batches of pages; the below
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index e03bb55..8b08bbd 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -388,13 +388,15 @@ int libxl__domain_build(libxl__gc *gc,
>          vments[4] = "start_time";
>          vments[5] = libxl__sprintf(gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
>  
> -        localents = libxl__calloc(gc, 7, sizeof(char *));
> +        localents = libxl__calloc(gc, 9, sizeof(char *));
>          localents[0] = "platform/acpi";
>          localents[1] = libxl_defbool_val(info->u.hvm.acpi) ? "1" : "0";
>          localents[2] = "platform/acpi_s3";
>          localents[3] = libxl_defbool_val(info->u.hvm.acpi_s3) ? "1" : "0";
>          localents[4] = "platform/acpi_s4";
>          localents[5] = libxl_defbool_val(info->u.hvm.acpi_s4) ? "1" : "0";
> +        localents[6] = "platform/vmware_hw";
> +        localents[7] = libxl__sprintf(gc, "%d", info->u.hvm.vmware_hw);
>  
>          break;
>      case LIBXL_DOMAIN_TYPE_PV:
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index 078cff1..53ab6a6 100644
> --- a/tools/libxl/libxl_dom.c
> +++ b/tools/libxl/libxl_dom.c
> @@ -496,6 +496,11 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
>      xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
>      xc_set_hvm_param(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
>  
> +    xc_set_hvm_param(handle, domid, HVM_PARAM_VMWARE_HW,
> +                     info->u.hvm.vmware_hw);
> +    xc_set_hvm_param(handle, domid, HVM_PARAM_VMPORT_LOGMASK,
> +                     info->u.hvm.vmport_logmask);
> +
>      xc_dom_gnttab_hvm_seed(handle, domid, *console_mfn, *store_mfn, console_domid, store_domid);
>      return 0;
>  }
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 649ce50..71ba64e 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -346,6 +346,8 @@ libxl_domain_build_info = Struct("domain_build_info",[
>                                         ("timeoffset",       string),
>                                         ("hpet",             libxl_defbool),
>                                         ("vpt_align",        libxl_defbool),
> +                                       ("vmware_hw",        integer),
> +                                       ("vmport_logmask",   integer),

"integer" in the IDL is 24 bit is it not? I would suggest uint64 to
match the param width.

>                                         ("timer_mode",       libxl_timer_mode),
>                                         ("nested_hvm",       libxl_defbool),
>                                         ("smbios_firmware",  string),
> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
> index bd26bcc..013066d 100644
> --- a/tools/libxl/xl_cmdimpl.c
> +++ b/tools/libxl/xl_cmdimpl.c
> @@ -987,6 +987,16 @@ static void parse_config_data(const char *config_source,
>          xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
>          xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
>          xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 0);
> +        if (!xlu_cfg_get_long(config, "vmware_hw",  &l, 1)) {
> +            b_info->u.hvm.vmware_hw = l;
> +            if (dom_info->debug)
> +                fprintf(stderr, "vmware_hw: 0x%llx\n", (unsigned long long) b_info->u.hvm.vmware_hw);

PRIx64 and no cast please.

> +        }
> +        if (!xlu_cfg_get_long(config, "vmport_logmask", &l, 1)) {
> +            b_info->u.hvm.vmport_logmask = l;
> +            if (dom_info->debug)
> +                fprintf(stderr, "vmport_logmask: 0x%llx\n", (unsigned long long) b_info->u.hvm.vmport_logmask);
> +        }
>          xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
>          xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
>  
> diff --git a/tools/libxl/xl_sxp.c b/tools/libxl/xl_sxp.c
> index a16a025..9010c42 100644
> --- a/tools/libxl/xl_sxp.c
> +++ b/tools/libxl/xl_sxp.c

The sxp is strictly for xm compatibility.  New features should not
extend it.

> @@ -102,6 +102,10 @@ void printf_info_sexp(int domid, libxl_domain_config *d_config)
>          printf("\t\t\t(nx %s)\n", libxl_defbool_to_string(b_info->u.hvm.nx));
>          printf("\t\t\t(viridian %s)\n",
>                 libxl_defbool_to_string(b_info->u.hvm.viridian));
> +        printf("\t\t\t(vmware_hw %d)\n",
> +               b_info->u.hvm.vmware_hw);
> +        printf("\t\t\t(vmport_logmask %x)\n",
> +               b_info->u.hvm.vmport_logmask);
>          printf("\t\t\t(hpet %s)\n",
>                 libxl_defbool_to_string(b_info->u.hvm.hpet));
>          printf("\t\t\t(vpt_align %s)\n",
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 6a7a781..38641c4 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -589,6 +589,7 @@ int hvm_domain_initialise(struct domain *d)
>  
>      d->arch.hvm_domain.params[HVM_PARAM_HPET_ENABLED] = 1;
>      d->arch.hvm_domain.params[HVM_PARAM_TRIPLE_FAULT_REASON] = SHUTDOWN_reboot;
> +    d->arch.hvm_domain.params[HVM_PARAM_VMPORT_RESET_TIME] = 15;
>  
>      vpic_init(d);
>  

This should probably be part of the patch which introduced the params.

~Andrew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 06/10] Add vmport structs
  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
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Cooper @ 2013-12-12 23:10 UTC (permalink / raw)
  To: Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/2013 19:15, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
>
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  xen/arch/x86/hvm/hvm.c           | 59 +++++++++++++++++++++++++++++-
>  xen/include/asm-x86/hvm/domain.h |  4 +++
>  xen/include/asm-x86/hvm/vmport.h | 77 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 139 insertions(+), 1 deletion(-)
>  create mode 100644 xen/include/asm-x86/hvm/vmport.h
>
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 38641c4..fa5d382 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -57,6 +57,7 @@
>  #include <asm/hvm/cacheattr.h>
>  #include <asm/hvm/trace.h>
>  #include <asm/hvm/nestedhvm.h>
> +#include <asm/hvm/vmport.h>
>  #include <asm/mtrr.h>
>  #include <asm/apic.h>
>  #include <public/sched.h>
> @@ -536,6 +537,7 @@ static int handle_pvh_io(
>  int hvm_domain_initialise(struct domain *d)
>  {
>      int rc;
> +    long vmport_mem = 0;
>  
>      if ( !hvm_enabled )
>      {
> @@ -562,6 +564,7 @@ int hvm_domain_initialise(struct domain *d)
>  
>      spin_lock_init(&d->arch.hvm_domain.irq_lock);
>      spin_lock_init(&d->arch.hvm_domain.uc_lock);
> +    spin_lock_init(&d->arch.hvm_domain.vmport_lock);
>  
>      INIT_LIST_HEAD(&d->arch.hvm_domain.msixtbl_list);
>      spin_lock_init(&d->arch.hvm_domain.msixtbl_list_lock);
> @@ -574,11 +577,47 @@ int hvm_domain_initialise(struct domain *d)
>  
>      d->arch.hvm_domain.params = xzalloc_array(uint64_t, HVM_NR_PARAMS);
>      d->arch.hvm_domain.io_handler = xmalloc(struct hvm_io_handler);
> +    d->arch.hvm_domain.vmport_data = xzalloc(struct vmport_state);
>      rc = -ENOMEM;
> -    if ( !d->arch.hvm_domain.params || !d->arch.hvm_domain.io_handler )
> +    if ( !d->arch.hvm_domain.params || !d->arch.hvm_domain.io_handler ||
> +         !d->arch.hvm_domain.vmport_data )
>          goto fail1;
>      d->arch.hvm_domain.io_handler->num_slot = 0;
>  
> +    vmport_mem += sizeof(struct vmport_state);
> +    d->arch.hvm_domain.vmport_data->open_cookie = ('C' << 8) + 'S';

This is one place where multicharacter constants would really help. 
However, I suspect a change to add -Wno-multichar to the build might not
go down too well.

> +    d->arch.hvm_domain.vmport_data->used_guestinfo = 10;
> +
> +    for (rc = 0; rc < d->arch.hvm_domain.vmport_data->used_guestinfo; rc++) {

Xen style - space inside brackets and braces lined up.

> +        d->arch.hvm_domain.vmport_data->guestinfo[rc] = xzalloc(vmport_guestinfo_t);

xzalloc_array() of used_guestinfo entries, and needs to be checked for
an allocation failure.

> +        vmport_mem += sizeof(vmport_guestinfo_t);
> +    }
> +    d->arch.hvm_domain.vmport_data->guestinfo[0]->key_len = 2;
> +    memcpy(d->arch.hvm_domain.vmport_data->guestinfo[0]->key_data, "ip", 2);
> +
> +    gdprintk(XENLOG_DEBUG, "vmport_mem=%ld bytes (%ld KiB, %ld MiB)\n",
> +             vmport_mem,
> +             (vmport_mem + (1 << 10) - 1) >> 10,
> +             (vmport_mem + (1 << 20) - 1) >> 20);
> +    vmport_mem += sizeof(uint64_t) * HVM_NR_PARAMS;
> +    vmport_mem += sizeof(struct hvm_io_handler);
> +    gdprintk(XENLOG_DEBUG, "hvm overhead=%ld bytes (%ld KiB, %ld MiB)\n",
> +             vmport_mem,
> +             (vmport_mem + (1 << 10) - 1) >> 10,
> +             (vmport_mem + (1 << 20) - 1) >> 20);
> +    gdprintk(XENLOG_DEBUG, "tot_pages=%d bytes (%d KiB, %d MiB)\n",
> +             d->tot_pages,
> +             (d->tot_pages + (1 << 10) - 1) >> 10,
> +             (d->tot_pages + (1 << 20) - 1) >> 20);
> +    gdprintk(XENLOG_DEBUG, "max_pages=%d bytes (%d KiB, %d MiB)\n",
> +             d->max_pages,
> +             (d->max_pages + (1 << 10) - 1) >> 10,
> +             (d->max_pages + (1 << 20) - 1) >> 20);

These two gdprintk()s do not appear to be related to the content of this
patch.

> +
> +#if 0
> +    vmport_flush(&d->arch.hvm_domain);
> +#endif

Is this stray debugging?

> +
>      if ( is_pvh_domain(d) )
>      {
>          register_portio_handler(d, 0, 0x10003, handle_pvh_io);
> @@ -617,6 +656,15 @@ int hvm_domain_initialise(struct domain *d)
>      stdvga_deinit(d);
>      vioapic_deinit(d);
>   fail1:
> +    if (d->arch.hvm_domain.vmport_data) {
> +        struct vmport_state *vs = d->arch.hvm_domain.vmport_data;
> +        int idx;
> +
> +        for (idx = 0; idx < vs->used_guestinfo; idx++) {
> +            xfree(vs->guestinfo[idx]);
> +        }
> +    }
> +    xfree(d->arch.hvm_domain.vmport_data);
>      xfree(d->arch.hvm_domain.io_handler);
>      xfree(d->arch.hvm_domain.params);
>   fail0:
> @@ -626,6 +674,15 @@ int hvm_domain_initialise(struct domain *d)
>  
>  void hvm_domain_relinquish_resources(struct domain *d)
>  {
> +    if (d->arch.hvm_domain.vmport_data) {
> +        struct vmport_state *vs = d->arch.hvm_domain.vmport_data;
> +        int idx;
> +
> +        for (idx = 0; idx < vs->used_guestinfo; idx++) {
> +            xfree(vs->guestinfo[idx]);
> +        }
> +        xfree(d->arch.hvm_domain.vmport_data);
> +    }
>      xfree(d->arch.hvm_domain.io_handler);
>      xfree(d->arch.hvm_domain.params);
>  
> diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
> index b1e3187..0ca2778 100644
> --- a/xen/include/asm-x86/hvm/domain.h
> +++ b/xen/include/asm-x86/hvm/domain.h
> @@ -62,6 +62,10 @@ struct hvm_domain {
>      /* emulated irq to pirq */
>      struct radix_tree_root emuirq_pirq;
>  
> +    /* VMware special port */
> +    spinlock_t             vmport_lock;
> +    struct  vmport_state  *vmport_data;
> +

Stray space between struct and vmport.

>      uint64_t              *params;
>  
>      /* Memory ranges with pinned cache attributes. */
> diff --git a/xen/include/asm-x86/hvm/vmport.h b/xen/include/asm-x86/hvm/vmport.h
> new file mode 100644
> index 0000000..180ddac
> --- /dev/null
> +++ b/xen/include/asm-x86/hvm/vmport.h
> @@ -0,0 +1,77 @@
> +/*
> + * vmport.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 __ASM_X86_HVM_VMPORT_H__
> +#define __ASM_X86_HVM_VMPORT_H__
> +
> +/* Note: VMPORT_PORT and VMPORT_MAGIC is also defined as BDOOR_PORT
> + * and BDOOR_MAGIC in backdoor_def.h Defined here so that other
> + * parts of XEN can use it.
> + */
> +
> +#define VMPORT_PORT 0x5658
> +#define VMPORT_MAGIC 0x564D5868

You should include backdoor_def.h rather than having the same constant
defined twice in the codebase.

> +
> +#define VMPORT_MAX_KEY_LEN 30
> +#define VMPORT_MAX_VAL_LEN 128
> +#define VMPORT_MAX_NUM_KEY 128
> +
> +#define VMPORT_MAX_SEND_BUF ((22 + VMPORT_MAX_KEY_LEN + VMPORT_MAX_VAL_LEN + 3)/4)
> +#define VMPORT_MAX_RECV_BUF ((2 + VMPORT_MAX_VAL_LEN + 3)/4)
> +#define VMPORT_MAX_CHANS    4
> +#define VMPORT_MAX_BKTS     8
> +
> +
> +typedef struct vmport_guestinfo_ {

Why the trailing underscores in the non-typedef'd name?

> +    uint8_t key_len;
> +    uint8_t val_len;
> +    char key_data[VMPORT_MAX_KEY_LEN];
> +    char val_data[VMPORT_MAX_VAL_LEN];
> +} vmport_guestinfo_t;
> +
> +typedef struct vmport_bucket_ {
> +    uint16_t recv_len;
> +    uint16_t recv_idx;
> +    uint32_t recv_buf[VMPORT_MAX_RECV_BUF + 1];
> +    uint8_t  recv_slot;
> +} vmport_bucket_t;
> +
> +typedef struct vmport_channel_ {
> +    unsigned long active_time;
> +    uint32_t chan_id;
> +    uint32_t cookie;
> +    uint32_t proto_num;
> +    uint16_t send_len;
> +    uint16_t send_idx;
> +    uint32_t send_buf[VMPORT_MAX_SEND_BUF + 1];
> +    vmport_bucket_t recv_bkt[VMPORT_MAX_BKTS];
> +    uint8_t recv_read;
> +    uint8_t recv_write;
> +} vmport_channel_t;
> +
> +struct vmport_state {
> +    unsigned long ping_time;
> +    uint32_t open_cookie;
> +    uint32_t used_guestinfo;
> +    vmport_channel_t chans[VMPORT_MAX_CHANS];
> +    vmport_guestinfo_t *guestinfo[VMPORT_MAX_NUM_KEY];
> +};
> +
> +int vmport_ioport(int dir, int size, unsigned long data, struct cpu_user_regs *regs);
> +void vmport_ctrl_send(struct hvm_domain *hd, char *msg, int slot);
> +void vmport_flush(struct hvm_domain *hd);

These declarations need to be in the same patch as defines them.

~Andrew

> +
> +#endif /* __ASM_X86_HVM_VMPORT_H__ */

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 07/10] Add new vmport code.
  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-17 20:36   ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 54+ messages in thread
From: Andrew Cooper @ 2013-12-13  0:06 UTC (permalink / raw)
  To: Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/2013 19:15, Don Slutz wrote:
> 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.

What do you mean by this?

> + */
> 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"

#include <asm/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);

Please include the appropriate header files.

> +
> +/* 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);
> +}

What is the point of these functions being separated out?

setHighBits only seems to be used with regs->ecx (which is actually a
64bit value not a 32bit value) to set a status value.

Why not set_status(cpu_user_regs *, uint16_t val) ?

> +
> +static inline long getLogMask(struct hvm_domain *hd)
> +{
> +    return hd->params[HVM_PARAM_VMPORT_LOGMASK];

A param is unsigned long, not long...

> +}
> +
> +static inline char *getStatus(struct hvm_domain *hd)
> +{
> +    return (char*)&hd->params[HVM_PARAM_VMPORT_STATUS];

... And most certainly not a string.

> +}
> +
> +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);

the correct format for any sizeof is %zu or %zx depending on decimal/hex.

> +}
> +
> +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;

This (and every use of getStatus() below) most certainly needs to
guarentee that slot is strictly in the bound 0 to 7, and writing the
integer 200 to a char is undefined I believe.

> +        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 ";

I cant remember offhand whether Xen is compiled with or without
read-only strings,

> +            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;

Again this hard coded constant.

> +        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:
> + */

Frankly, this while file is quite nasty.  There is a huge amount of
pointer arithmetic and array indexing with guest data, which doesn't
appear at a glance to have sufficient validation.

The vast majority of the ints should be unsigned as they are used as
indices.  All the times should probably be s_time_t's

The idiom

if ( getLogMask(hd) & LOG_$SOMETHING )
    gdprintk(XENLOG_$SOMETHING, ...);

Can probably be moved into a single macro, which will simply the reading
of the code quite a bit.

Is there a spec for what this code is trying to accomplish?  Some of the
comments suggest that it has been reverse engineered?

I think I have counted 4 coding styles in there.  Given the Xen block on
the bottom, can it settle on a single style.

> 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>

What is the point of this header file?

> +
> +#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

There are already traps for io ports, which I believe are part of the
generic vmexit traps.

~Andrew

>  
>  
>  #define TRC_PAR_LONG(par) ((par)&0xFFFFFFFF),((par)>>32)

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 08/10] connect vmport up
  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-17 20:37   ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 54+ messages in thread
From: Andrew Cooper @ 2013-12-13  0:51 UTC (permalink / raw)
  To: Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/2013 19:15, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
>
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  xen/arch/x86/hvm/io.c       |   4 ++
>  xen/arch/x86/hvm/svm/svm.c  | 104 ++++++++++++++++++++++++++++++++++++
>  xen/arch/x86/hvm/svm/vmcb.c |   1 +
>  xen/arch/x86/hvm/vmx/vmcs.c |   1 +
>  xen/arch/x86/hvm/vmx/vmx.c  | 125 ++++++++++++++++++++++++++++++++++++++++++++
>  xen/arch/x86/hvm/vmx/vvmx.c |  13 +++++
>  xen/include/public/trace.h  |   1 +
>  7 files changed, 249 insertions(+)
>
> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
> index bf6309d..4bc4716 100644
> --- a/xen/arch/x86/hvm/io.c
> +++ b/xen/arch/x86/hvm/io.c
> @@ -42,6 +42,7 @@
>  #include <asm/hvm/vlapic.h>
>  #include <asm/hvm/trace.h>
>  #include <asm/hvm/emulate.h>
> +#include <asm/hvm/vmport.h>
>  #include <public/sched.h>
>  #include <xen/iocap.h>
>  #include <public/hvm/ioreq.h>
> @@ -236,6 +237,9 @@ int handle_pio(uint16_t port, unsigned int size, int dir)
>      if ( dir == IOREQ_WRITE )
>          data = guest_cpu_user_regs()->eax;
>  
> +    if ( port == VMPORT_PORT )
> +        return vmport_ioport(dir, size, data, guest_cpu_user_regs());
> +

Use register_portio_handler(), which is the already-existing
infrastructure for intercepting ports.

>      rc = hvmemul_do_pio(port, &reps, size, 0, dir, 0, &data);
>  
>      switch ( rc )
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index 406d394..80cf2bf 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -56,6 +56,7 @@
>  #include <asm/hvm/svm/nestedsvm.h>
>  #include <asm/hvm/nestedhvm.h>
>  #include <asm/x86_emulate.h>
> +#include <asm/hvm/vmport.h>
>  #include <public/sched.h>
>  #include <asm/hvm/vpt.h>
>  #include <asm/hvm/trace.h>
> @@ -1904,6 +1905,105 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
>      return;
>  }
>  
> +static void svm_vmexit_gp_intercept(struct cpu_user_regs *regs, struct vcpu *v)
> +{
> +    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
> +    unsigned long inst_len, bytes_len;
> +    int frc;
> +    unsigned char bytes[15];
> +
> +    regs->error_code = vmcb->exitinfo1;
> +    if ( !cpu_has_svm_nrips || (vmcb->nextrip <= vmcb->rip) )
> +        inst_len = 0;
> +    else
> +        inst_len = vmcb->nextrip - vmcb->rip;
> +    bytes_len = 2 /* inst_len < 15 ? inst_len > 1 ? inst_len : 2 : 15 */;
> +    frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
> +                                            bytes_len,
> +                                            PFEC_page_present);
> +
> +    if ( hvm_long_mode_enabled(v) )
> +        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
> +                         regs->error_code,
> +                         TRC_PAR_LONG(vmcb->exitinfo2) );
> +    else
> +        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
> +                    regs->error_code, vmcb->exitinfo2 );
> +
> +    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* LOG_GP_FAIL_RD_INST */)
> +        printk("[HVM:%d.%d] <%s> "
> +               "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%ld,%d) nip(%d)=%lx(%d,%d(0x%x) 0x%x 0x%x)"
> +               "\n",
> +               current->domain->domain_id, current->vcpu_id, __func__,
> +               (unsigned long)vmcb->exitinfo2,
> +               (unsigned long)regs->error_code,
> +               (unsigned long)regs->eip, (unsigned int)bytes[0],
> +               (unsigned int)bytes[1], bytes_len, inst_len, frc,
> +               cpu_has_svm_nrips, (unsigned long)vmcb->nextrip,
> +               cpu_has_svm_decode, vmcb->guest_ins_len & 0xf, vmcb->guest_ins_len,
> +               vmcb->guest_ins[0], vmcb->guest_ins[1]);
> +
> +    if ( !frc && bytes[0] == 0xed && (regs->edx & 0xffff) == VMPORT_PORT &&
> +         vmcb->exitinfo2 == 0 && regs->error_code == 0 )
> +    {
> +        /*  in (%dx),%eax */
> +        uint32_t magic = regs->eax;
> +
> +        if ( magic == VMPORT_MAGIC ) {
> +            __update_guest_eip(regs, 1);
> +            vmport_ioport(IOREQ_READ, 4, 0, regs);

This appears to be intercepting an L2 guest doing vmport magic IO to the
L1 hypervisor.

Is this sane/sensible/wise?

> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* LOG_GP_VMWARE_AFTER */)
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (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);
> +            return;
> +        } else {
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* LOG_GP_NOT_VMWARE */)
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (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);
> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +        }
> +    } else if (!frc && regs->error_code == 0
> +               && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx == 0x10000)
> +    {
> +        /* "rdpmc 0x10000" */
> +        /* Not a very good emulation!  But just not faulting is good enough
> +         * to get NetApp booting. */
> +        regs->edx = regs->eax = 0;

This doesn't look like it is logically part of "connecting vmport up"

~Andrew

> +
> +        __update_guest_eip(regs, inst_len);
> +
> +        /* Doing the log in this case was too noisy for NetApp, so I moved
> +         * it to 'else' */
> +    } else {
> +        if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x100000 /* LOG_GP_UNKNOWN */) {
> +            printk("[HVM:%d.%d] <%s> "
> +                   "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                   "\n",
> +                   current->domain->domain_id, current->vcpu_id, __func__,
> +                   (unsigned long)vmcb->exitinfo2, (unsigned long)regs->error_code,
> +                   (unsigned long)regs->eip, (unsigned int)bytes[0],
> +                   (unsigned int)bytes[1], inst_len, frc,
> +                   (unsigned long)regs->eax, (unsigned long)regs->ebx,
> +                   (unsigned long)regs->ecx, (unsigned long)regs->edx,
> +                   (unsigned long)regs->esi, (unsigned long)regs->edi);
> +        }
> +        hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +    }
> +}
> +
>  static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)
>  {
>      struct hvm_emulate_ctxt ctxt;
> @@ -2253,6 +2353,10 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
>          break;
>      }
>  
> +    case VMEXIT_EXCEPTION_GP:
> +        svm_vmexit_gp_intercept(regs, v);
> +        break;
> +
>      case VMEXIT_EXCEPTION_UD:
>          svm_vmexit_ud_intercept(regs);
>          break;
> diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
> index 21292bb..791c045 100644
> --- a/xen/arch/x86/hvm/svm/vmcb.c
> +++ b/xen/arch/x86/hvm/svm/vmcb.c
> @@ -193,6 +193,7 @@ static int construct_vmcb(struct vcpu *v)
>  
>      vmcb->_exception_intercepts =
>          HVM_TRAP_MASK
> +        | (1U << TRAP_gp_fault)
>          | (1U << TRAP_no_device);
>  
>      if ( paging_mode_hap(v->domain) )
> diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
> index 44f33cb..21cde2f 100644
> --- a/xen/arch/x86/hvm/vmx/vmcs.c
> +++ b/xen/arch/x86/hvm/vmx/vmcs.c
> @@ -1074,6 +1074,7 @@ static int construct_vmcs(struct vcpu *v)
>  
>      v->arch.hvm_vmx.exception_bitmap = HVM_TRAP_MASK
>                | (paging_mode_hap(d) ? 0 : (1U << TRAP_page_fault))
> +              | (1U << TRAP_gp_fault)
>                | (1U << TRAP_no_device);
>      vmx_update_exception_bitmap(v);
>  
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index dfff628..248900d 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -44,6 +44,7 @@
>  #include <asm/hvm/support.h>
>  #include <asm/hvm/vmx/vmx.h>
>  #include <asm/hvm/vmx/vmcs.h>
> +#include <asm/hvm/vmport.h>
>  #include <public/sched.h>
>  #include <public/hvm/ioreq.h>
>  #include <asm/hvm/vpic.h>
> @@ -1211,6 +1212,7 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
>                  v->arch.hvm_vmx.exception_bitmap = HVM_TRAP_MASK
>                            | (paging_mode_hap(v->domain) ?
>                               0 : (1U << TRAP_page_fault))
> +                          | (1U << TRAP_gp_fault)
>                            | (1U << TRAP_no_device);
>                  vmx_update_exception_bitmap(v);
>                  vmx_update_debug_state(v);
> @@ -2454,6 +2456,113 @@ static void vmx_idtv_reinject(unsigned long idtv_info)
>      }
>  }
>  
> +void do_gp_fault(struct cpu_user_regs *regs, struct vcpu *v)
> +{
> +    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +    unsigned long exit_qualification;
> +    unsigned long inst_len;
> +    unsigned long ecode;
> +
> +    __vmread(EXIT_QUALIFICATION, &exit_qualification);
> +    __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
> +    __vmread(VM_EXIT_INTR_ERROR_CODE, &ecode);
> +    regs->error_code = ecode;
> +    if ( hvm_long_mode_enabled(v) )
> +        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
> +                         regs->error_code,
> +                         TRC_PAR_LONG(exit_qualification) );
> +    else
> +        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
> +                    regs->error_code, exit_qualification );
> +
> +    if ( inst_len == 1 && (regs->edx & 0xffff) == VMPORT_PORT &&
> +         exit_qualification == 0 && regs->error_code == 0 ) {
> +        uint32_t magic = regs->eax;
> +
> +        if ( magic == VMPORT_MAGIC ) {
> +            unsigned char bytes[1];
> +            int frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
> +                                                        1, PFEC_page_present);
> +            if (!frc && bytes[0] == 0xed) { /*  in (%dx),%eax */
> +                update_guest_eip();
> +                vmport_ioport(IOREQ_READ, 4, 0, regs);
> +                if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* LOG_GP_VMWARE_AFTER */)
> +                    printk("[HVM:%d.%d] <%s> "
> +                           "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                           "\n",
> +                           current->domain->domain_id, current->vcpu_id, __func__,
> +                           (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);
> +                return;
> +            } else {
> +                if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* LOG_GP_FAIL_RD_INST */)
> +                    printk("[HVM:%d.%d] <%s> "
> +                           "gp: VMware? ip=%lx=>0x%x(%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                           "\n",
> +                           current->domain->domain_id, current->vcpu_id, __func__,
> +                           (unsigned long)regs->eip, bytes[0], frc,
> +                           (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 (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* LOG_GP_NOT_VMWARE */)
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (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);
> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +        }
> +    } else {
> +        unsigned char bytes[15];
> +        int frc;
> +
> +        /*
> +         * We can conditionalize this call on inst_len == 2 if we decide to
> +         * remove the following printk.
> +         */
> +        frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
> +                                                inst_len < 15 ? inst_len : 15,
> +                                                PFEC_page_present);
> +
> +        /* Emulate "rdpmc 0x10000" */
> +        if (!frc && inst_len == 2 && regs->error_code == 0
> +            && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx == 0x10000)
> +        {
> +            /* Not a very good emulation!  But just not faulting is good enough
> +             * to get NetApp booting. */
> +            regs->edx = regs->eax = 0;
> +
> +            update_guest_eip();
> +
> +            /* Doing the log in this case was too noisy for NetApp, so I moved
> +             * it to 'else' */
> +        } else {
> +            /* We should probably turn this log off by default in production in
> +             * case somebody decides to do a lot of #GPs. */
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x100000 /* LOG_GP_UNKNOWN */) {
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: eq=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (unsigned long)exit_qualification, (unsigned long)regs->error_code,
> +                       (unsigned long)regs->eip, (unsigned int)bytes[0],
> +                       (unsigned int)bytes[1], inst_len, frc,
> +                       (unsigned long)regs->eax, (unsigned long)regs->ebx,
> +                       (unsigned long)regs->ecx, (unsigned long)regs->edx,
> +                       (unsigned long)regs->esi, (unsigned long)regs->edi);
> +            }
> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +        }
> +    }
> +}
> +
>  static int vmx_handle_apic_write(void)
>  {
>      unsigned long exit_qualification;
> @@ -2562,6 +2671,19 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
>                   && vector != TRAP_nmi 
>                   && vector != TRAP_machine_check ) 
>              {
> +                if (vector == TRAP_gp_fault ) {
> +                    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +
> +                    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x8000000 /* LOG_REALMODE_GP */)
> +                        printk("[HVM:%d.%d] <%s> "
> +                               "realmode gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                               "\n",
> +                               current->domain->domain_id, current->vcpu_id, __func__,
> +                               (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);
> +                }
>                  perfc_incr(realmode_exits);
>                  v->arch.hvm_vmx.vmx_emulate = 1;
>                  HVMTRACE_0D(REALMODE_EMULATE);
> @@ -2677,6 +2799,9 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
>              HVMTRACE_1D(TRAP, vector);
>              vmx_fpu_dirty_intercept();
>              break;
> +        case TRAP_gp_fault:
> +            do_gp_fault(regs, v);
> +            break;
>          case TRAP_page_fault:
>              __vmread(EXIT_QUALIFICATION, &exit_qualification);
>              __vmread(VM_EXIT_INTR_ERROR_CODE, &ecode);
> diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
> index 0daad79..fcd03dd 100644
> --- a/xen/arch/x86/hvm/vmx/vvmx.c
> +++ b/xen/arch/x86/hvm/vmx/vvmx.c
> @@ -2166,6 +2166,19 @@ int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs,
>              if ( v->fpu_dirtied )
>                  nvcpu->nv_vmexit_pending = 1;
>          }
> +        else if ( vector == TRAP_gp_fault )
> +        {
> +            struct cpu_user_regs *ur = guest_cpu_user_regs();
> +            struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x1000000 /* LOG_VGP_UNKNOWN */)
> +                gdprintk(XENLOG_ERR, "Unexpected gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx\n",
> +                         (unsigned long)ur->eip,
> +                         (unsigned long)ur->eax, (unsigned long)ur->ebx,
> +                         (unsigned long)ur->ecx, (unsigned long)ur->edx,
> +                         (unsigned long)ur->esi, (unsigned long)ur->edi);
> +                nvcpu->nv_vmexit_pending = 1;
> +        }
>          else if ( (intr_info & valid_mask) == valid_mask )
>          {
>              exec_bitmap =__get_vvmcs(nvcpu->nv_vvmcx, EXCEPTION_BITMAP);
> diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h
> index e2f60a6..32489f0 100644
> --- a/xen/include/public/trace.h
> +++ b/xen/include/public/trace.h
> @@ -223,6 +223,7 @@
>  #define TRC_HVM_NPF             (TRC_HVM_HANDLER + 0x21)
>  #define TRC_HVM_REALMODE_EMULATE (TRC_HVM_HANDLER + 0x22)
>  #define TRC_HVM_TRAP             (TRC_HVM_HANDLER + 0x23)
> +#define TRC_HVM_TRAP64           (TRC_HVM_HANDLER + TRC_64_FLAG + 0x23)

Haven't you already defined this in a previous patch?

>  #define TRC_HVM_TRAP_DEBUG       (TRC_HVM_HANDLER + 0x24)
>  #define TRC_HVM_VLAPIC           (TRC_HVM_HANDLER + 0x25)
>  

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 09/10] libxl: Add VTPOWER, VTREBOOT and VTPING
  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
  1 sibling, 0 replies; 54+ messages in thread
From: Andrew Cooper @ 2013-12-13  0:58 UTC (permalink / raw)
  To: Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/2013 19:15, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
>
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  tools/libxl/libxl.c         | 12 ++++++++++++
>  tools/libxl/libxl_types.idl |  3 +++
>  tools/libxl/xl_cmdtable.c   |  2 +-
>  xen/arch/x86/domctl.c       | 34 ++++++++++++++++++++++++++++++++++
>  xen/include/public/domctl.h |  3 +++
>  5 files changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> index fd8b988..1ec8484 100644
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -5057,6 +5057,18 @@ int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid,
>          rc = xc_domain_send_trigger(ctx->xch, domid,
>                                      XEN_DOMCTL_SENDTRIGGER_SLEEP, vcpuid);
>          break;
> +    case LIBXL_TRIGGER_VTPOWER:
> +        rc = xc_domain_send_trigger(ctx->xch, domid,
> +                                    XEN_DOMCTL_SENDTRIGGER_VTPOWER, vcpuid);
> +        break;
> +    case LIBXL_TRIGGER_VTREBOOT:
> +        rc = xc_domain_send_trigger(ctx->xch, domid,
> +                                    XEN_DOMCTL_SENDTRIGGER_VTREBOOT, vcpuid);
> +        break;
> +    case LIBXL_TRIGGER_VTPING:
> +        rc = xc_domain_send_trigger(ctx->xch, domid,
> +                                    XEN_DOMCTL_SENDTRIGGER_VTPING, vcpuid);
> +        break;
>      case LIBXL_TRIGGER_NMI:
>          rc = xc_domain_send_trigger(ctx->xch, domid,
>                                      XEN_DOMCTL_SENDTRIGGER_NMI, vcpuid);
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 71ba64e..80a8ee8 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -105,6 +105,9 @@ libxl_trigger = Enumeration("trigger", [
>      (4, "INIT"),
>      (5, "RESET"),
>      (6, "S3RESUME"),
> +    (7, "VTPOWER"),
> +    (8, "VTREBOOT"),
> +    (9, "VTPING"),
>      ])
>  
>  libxl_tsc_mode = Enumeration("tsc_mode", [
> diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
> index ebe0220..98db8ae 100644
> --- a/tools/libxl/xl_cmdtable.c
> +++ b/tools/libxl/xl_cmdtable.c
> @@ -290,7 +290,7 @@ struct cmd_spec cmd_table[] = {
>      { "trigger",
>        &main_trigger, 0, 1,
>        "Send a trigger to a domain",
> -      "<Domain> <nmi|reset|init|power|sleep|s3resume> [<VCPU>]",
> +      "<Domain> <nmi|reset|init|power|sleep|s3resume|vtpower|vtreboot|vtping> [<VCPU>]",
>      },
>      { "sysrq",
>        &main_sysrq, 0, 1,
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index ef6c140..8b77ce2 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -23,6 +23,7 @@
>  #include <xen/paging.h>
>  #include <asm/irq.h>
>  #include <asm/hvm/hvm.h>
> +#include <asm/hvm/vmport.h>
>  #include <asm/hvm/support.h>
>  #include <asm/hvm/cacheattr.h>
>  #include <asm/processor.h>
> @@ -577,6 +578,39 @@ long arch_do_domctl(
>          }
>          break;
>  
> +        case XEN_DOMCTL_SENDTRIGGER_VTPOWER:
> +        {
> +            ret = -EINVAL;
> +            if ( is_hvm_domain(d) )

Surely "is_vmware_domain(d)" is the appropriate check here?

> +            {
> +                ret = 0;
> +                vmport_ctrl_send(&d->arch.hvm_domain, "OS_Halt", 1);
> +            }
> +        }
> +        break;
> +
> +        case XEN_DOMCTL_SENDTRIGGER_VTREBOOT:
> +        {
> +            ret = -EINVAL;
> +            if ( is_hvm_domain(d) )
> +            {
> +                ret = 0;
> +                vmport_ctrl_send(&d->arch.hvm_domain, "OS_Reboot", 2);
> +            }
> +        }
> +        break;
> +
> +        case XEN_DOMCTL_SENDTRIGGER_VTPING:
> +        {
> +            ret = -EINVAL;
> +            if ( is_hvm_domain(d) )
> +            {
> +                ret = 0;
> +                vmport_ctrl_send(&d->arch.hvm_domain, "ping", 3);

POWER and REBOOT I can understand, but what is the expected actions from
PING ?

~Andrew

> +            }
> +        }
> +        break;
> +
>          default:
>              ret = -ENOSYS;
>          }
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index 01a3652..d71d57c 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -454,6 +454,9 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t);
>  #define XEN_DOMCTL_SENDTRIGGER_INIT   2
>  #define XEN_DOMCTL_SENDTRIGGER_POWER  3
>  #define XEN_DOMCTL_SENDTRIGGER_SLEEP  4
> +#define XEN_DOMCTL_SENDTRIGGER_VTPOWER  5
> +#define XEN_DOMCTL_SENDTRIGGER_VTREBOOT 6
> +#define XEN_DOMCTL_SENDTRIGGER_VTPING   7
>  struct xen_domctl_sendtrigger {
>      uint32_t  trigger;  /* IN */
>      uint32_t  vcpu;     /* IN */

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 10/10] Add VMware guest info access
  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
  2 siblings, 0 replies; 54+ messages in thread
From: Andrew Cooper @ 2013-12-13  1:08 UTC (permalink / raw)
  To: Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/2013 19:15, Don Slutz wrote:
> 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);

Debugging code?

> +#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.") ) {

Xen braces style.

> +            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;

This break will skip the spin_unlock() on the vmport_lock, as will most
of the others by the looks of the code.

> +                } 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

These probably want to be domctl hypercalls not HVMOPs

> +#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];

This wants to be a GUEST_HANDLE

~Andrew

> +};
> +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__ */

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 10/10] Add VMware guest info access
  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
  2 siblings, 0 replies; 54+ messages in thread
From: Matthew Daley @ 2013-12-13  5:32 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Fri, Dec 13, 2013 at 8:15 AM, Don Slutz <dslutz@verizon.com> wrote:
> 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

I don't think I quite understand the need for the
VMPORT_MAX_{KEY,VAL}_LEN macros as well as the
VMPORT_GUEST_INFO_{KEY,VAL}_MAX ones. IIUC VMPORT_MAX_{KEY,VAL}_LEN is
used for sizing the guestinfo data buffer on the Xen side, but
VMPORT_GUEST_INFO_{KEY,VAL}_MAX is used for the public subop hypercall
interface.

Is there a need for the "guestinfo." key prefix chopping? This is
being done in this new hypercall subop implemented by Xen, so
shouldn't there be no existing callers expecting this behaviour,
allowing it to be dropped?

> +        if ( a.key_length > strlen("guestinfo.") ) {
> +            if ( (unsigned long)a.key_length + (unsigned long)a.value_length > sizeof(a.data) )

Are the casts necessary? It looks like you're trying to avoid
overflow, but {key,value}_length are uint16's, which will be
automatically promoted to ints.

> +                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;

You don't check these two maximum lengths in the a.key_length >
strlen("guestinfo.") case, where one could still provide a large key
and tiny value.

> +            value = key + a.key_length;
> +        } else if ( (a.key_length == 0) && (op == HVMOP_set_vmport_guest_info) ) {

I wouldn't bother checking for a.key_length == 0 explicitly here, it's
implied at this point. In addition, the check on op should be a
whitelist (op != ...), not a blacklist (op == ...).

> +            return -EINVAL;
> +        }

Perhaps these three cases can be shuffled around a bit. By making the
a.key_length > strlen("guestinfo.") check also include the memcmp(),
the two cases then become "key *is* prefixed with guestinfo." and "key
is not prefixed with guestinfo." instead of the current setup, which
has "key *could* be prefixed with guestinfo." and "key is not prefixed
with guestinfo.". This allows factoring out the "is not prefixed with
guestinfo." part into a single case. Before all this, the common
length checks can be done. Something like this:

if ( (op != HVMOP_get_vmport_guest_info && !a.key_length) ||
        a.key_length > VMPORT_MAX_KEY_LEN ||
        a.value_length > VMPORT_MAX_VAL_LEN )
        return -EINVAL;

key = a.data;
if ( a.key_length > strlen("guestinfo.") &&
        memcmp(a.data, "guestinfo.", strlen("guestinfo.") == 0 ) {
        key += strlen("guestinfo.");
        a.key_length -= strlen("guestinfo.");
}

value = key + a.key_length;

> +        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);
> +        }

Is it really worth the extra complexity to maintain allocated but
unused guestinfos? Can't they just be allocated on demand and freed
when unneeded? Speaking of which, is there a way to delete (and not
just empty out) a guestinfo? If not, would it be a good thing to have?

> +
> +        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) {

The use of key_length being 0 in a "get" operation confused me here
(for example, I thought this was open to bad indexing if value_length
was out-of-range, but I see that you check it back up where you return
E2BIG).

Really, there are three subops being added here; one set and two gets
(looking up by key or index). Hence I think it might be a good idea to
explicitly define a third subop, say
HVMOP_get_by_idx_vmport_guest_info. You could then use a union for the
{get,set} subops which have differing arguments to the new get_by_idx
subop.

> +                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
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 02/10] Add VMware HVM params
  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 10:52   ` Jan Beulich
  2013-12-13 18:13     ` Don Slutz
  2013-12-17 20:02   ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 54+ messages in thread
From: Jan Beulich @ 2013-12-13 10:52 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Jun Nakajima, xen-devel, Boris Ostrovsky,
	Suravee Suthikulpanit

>>> On 12.12.13 at 20:15, Don Slutz <dslutz@verizon.com> wrote:
> --- a/xen/include/public/hvm/params.h
> +++ b/xen/include/public/hvm/params.h
> @@ -145,6 +145,15 @@
>  /* SHUTDOWN_* action in case of a triple fault */
>  #define HVM_PARAM_TRIPLE_FAULT_REASON 31
>  
> -#define HVM_NR_PARAMS          32
> +/* Params for VMware */
> +#define HVM_PARAM_VMWARE_HW                 32
> +#define HVM_PARAM_VMPORT_LOGMASK            33
> +#define HVM_PARAM_VMPORT_STATUS             34
> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_TIME  35
> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_VALUE 36
> +#define HVM_PARAM_VMPORT_RESET_TIME         37
> +
> +#define HVM_NR_PARAMS          38
> +
>  
>  #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */

Both for reviewing purposes and from a consistency pov this
should be in a single patch together with the hypervisor side
implementation.

Jan

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 03/10] Add cpuid_vmware_leaves
  2013-12-12 22:27   ` Andrew Cooper
@ 2013-12-13 10:55     ` Jan Beulich
  2013-12-13 13:38       ` Andrew Cooper
  2013-12-17 16:20     ` Don Slutz
  1 sibling, 1 reply; 54+ messages in thread
From: Jan Beulich @ 2013-12-13 10:55 UTC (permalink / raw)
  To: Andrew Cooper, Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Jun Nakajima, xen-devel, Boris Ostrovsky,
	Suravee Suthikulpanit

>>> On 12.12.13 at 23:27, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
> On 12/12/2013 19:15, Don Slutz wrote:
>>  int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
>>                 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
>>  {
>>      struct domain *d = current->domain;
>>      /* Optionally shift out of the way of Viridian architectural leaves. */
>> -    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
>> +    uint32_t base = 0x40000000;
>>      uint32_t limit;
>>  
>> +    if ( is_viridian_domain(d) )
>> +        base += 0x100;
>> +    if ( is_vmware_domain(d) )
>> +        base += 0x100;
>> +
> 
> These bases need a far more scalable solution, especially as the result
> of each of these clauses can be changed at runtime with a cunning
> hvm_param_set hypercall.
> 
> I think that both "is pretending to be HyperV" and "is pretending to be
> VMware" need to be domain creation flags which are strictly static for
> the lifetime of the domain.

And it seems highly questionable to me whether having both at the
same time makes much sense.

Plus the new function doesn't belong in xen/arch/x86/traps.c ...

Jan

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 07/10] Add new vmport code.
  2013-12-12 19:15 ` [RFC PATCH 07/10] Add new vmport code Don Slutz
  2013-12-13  0:06   ` Andrew Cooper
@ 2013-12-13 10:59   ` Jan Beulich
  2013-12-19  2:25     ` Don Slutz
  2013-12-17 20:36   ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 54+ messages in thread
From: Jan Beulich @ 2013-12-13 10:59 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Jun Nakajima, xen-devel, Boris Ostrovsky,
	Suravee Suthikulpanit

>>> On 12.12.13 at 20:15, Don Slutz <dslutz@verizon.com> wrote:
> From: Don Slutz <dslutz@verizon.com>
> 
> enable vmport_flush call.
> 
> Signed-off-by: Don Slutz <dslutz@verizon.com>

Again - please be more verbose.

And clean up the coding style before submitting.

Jan

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 03/10] Add cpuid_vmware_leaves
  2013-12-13 10:55     ` Jan Beulich
@ 2013-12-13 13:38       ` Andrew Cooper
  2013-12-13 18:55         ` Don Slutz
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Cooper @ 2013-12-13 13:38 UTC (permalink / raw)
  To: Jan Beulich, Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Jun Nakajima, xen-devel, Boris Ostrovsky,
	Suravee Suthikulpanit

On 13/12/2013 10:55, Jan Beulich wrote:
>>>> On 12.12.13 at 23:27, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>> On 12/12/2013 19:15, Don Slutz wrote:
>>>  int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
>>>                 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
>>>  {
>>>      struct domain *d = current->domain;
>>>      /* Optionally shift out of the way of Viridian architectural leaves. */
>>> -    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
>>> +    uint32_t base = 0x40000000;
>>>      uint32_t limit;
>>>  
>>> +    if ( is_viridian_domain(d) )
>>> +        base += 0x100;
>>> +    if ( is_vmware_domain(d) )
>>> +        base += 0x100;
>>> +
>> These bases need a far more scalable solution, especially as the result
>> of each of these clauses can be changed at runtime with a cunning
>> hvm_param_set hypercall.
>>
>> I think that both "is pretending to be HyperV" and "is pretending to be
>> VMware" need to be domain creation flags which are strictly static for
>> the lifetime of the domain.
> And it seems highly questionable to me whether having both at the
> same time makes much sense.
>
> Plus the new function doesn't belong in xen/arch/x86/traps.c ...
>
> Jan
>

I would certainly agree on the sentiment of it not making much sense.

However, as Xen needs viridian to run windows, I would be astounded if
vmware VMs didn't have viridian as well, in which case it is probably
quite likely that a vmware windows vm with vmware tools would expect to
find viridian and vmware extensions.

~Andrew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 08/10] connect vmport up
  2013-12-12 19:15 ` [RFC PATCH 08/10] connect vmport up Don Slutz
  2013-12-13  0:51   ` Andrew Cooper
@ 2013-12-13 15:46   ` Boris Ostrovsky
  2013-12-19  3:45     ` Don Slutz
  2013-12-17 20:37   ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 54+ messages in thread
From: Boris Ostrovsky @ 2013-12-13 15:46 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, xen-devel, Jan Beulich, Jun Nakajima,
	Suravee Suthikulpanit

On 12/12/2013 02:15 PM, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
>
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>   xen/arch/x86/hvm/io.c       |   4 ++
>   xen/arch/x86/hvm/svm/svm.c  | 104 ++++++++++++++++++++++++++++++++++++
>   xen/arch/x86/hvm/svm/vmcb.c |   1 +
>   xen/arch/x86/hvm/vmx/vmcs.c |   1 +
>   xen/arch/x86/hvm/vmx/vmx.c  | 125 ++++++++++++++++++++++++++++++++++++++++++++
>   xen/arch/x86/hvm/vmx/vvmx.c |  13 +++++
>   xen/include/public/trace.h  |   1 +
>   7 files changed, 249 insertions(+)
>
> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
> index bf6309d..4bc4716 100644
> --- a/xen/arch/x86/hvm/io.c
> +++ b/xen/arch/x86/hvm/io.c
> @@ -42,6 +42,7 @@
>   #include <asm/hvm/vlapic.h>
>   #include <asm/hvm/trace.h>
>   #include <asm/hvm/emulate.h>
> +#include <asm/hvm/vmport.h>
>   #include <public/sched.h>
>   #include <xen/iocap.h>
>   #include <public/hvm/ioreq.h>
> @@ -236,6 +237,9 @@ int handle_pio(uint16_t port, unsigned int size, int dir)
>       if ( dir == IOREQ_WRITE )
>           data = guest_cpu_user_regs()->eax;
>   
> +    if ( port == VMPORT_PORT )
> +        return vmport_ioport(dir, size, data, guest_cpu_user_regs());
> +
>       rc = hvmemul_do_pio(port, &reps, size, 0, dir, 0, &data);
>   
>       switch ( rc )
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index 406d394..80cf2bf 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -56,6 +56,7 @@
>   #include <asm/hvm/svm/nestedsvm.h>
>   #include <asm/hvm/nestedhvm.h>
>   #include <asm/x86_emulate.h>
> +#include <asm/hvm/vmport.h>
>   #include <public/sched.h>
>   #include <asm/hvm/vpt.h>
>   #include <asm/hvm/trace.h>
> @@ -1904,6 +1905,105 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
>       return;
>   }
>   
> +static void svm_vmexit_gp_intercept(struct cpu_user_regs *regs, struct vcpu *v)
> +{
> +    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
> +    unsigned long inst_len, bytes_len;
> +    int frc;
> +    unsigned char bytes[15];
> +
> +    regs->error_code = vmcb->exitinfo1;
> +    if ( !cpu_has_svm_nrips || (vmcb->nextrip <= vmcb->rip) )
> +        inst_len = 0;
> +    else
> +        inst_len = vmcb->nextrip - vmcb->rip;

You can use svm_nextrip_insn_length(), with some adjustments to NDEBUG 
case there.

> +    bytes_len = 2 /* inst_len < 15 ? inst_len > 1 ? inst_len : 2 : 15 */;

Saying this in words would be preferable --- I am not sure I understand 
why it's 2. Do you only expect specific instructions here? Or are you 
only interested in the first two bytes of the opcode?

> +    frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
> +                                            bytes_len,
> +                                            PFEC_page_present);
> +
> +    if ( hvm_long_mode_enabled(v) )
> +        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
> +                         regs->error_code,
> +                         TRC_PAR_LONG(vmcb->exitinfo2) );
> +    else
> +        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
> +                    regs->error_code, vmcb->exitinfo2 );
> +
> +    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* LOG_GP_FAIL_RD_INST */)
> +        printk("[HVM:%d.%d] <%s> "
> +               "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%ld,%d) nip(%d)=%lx(%d,%d(0x%x) 0x%x 0x%x)"
> +               "\n",
> +               current->domain->domain_id, current->vcpu_id, __func__,
> +               (unsigned long)vmcb->exitinfo2,
> +               (unsigned long)regs->error_code,
> +               (unsigned long)regs->eip, (unsigned int)bytes[0],
> +               (unsigned int)bytes[1], bytes_len, inst_len, frc,
> +               cpu_has_svm_nrips, (unsigned long)vmcb->nextrip,
> +               cpu_has_svm_decode, vmcb->guest_ins_len & 0xf, vmcb->guest_ins_len,
> +               vmcb->guest_ins[0], vmcb->guest_ins[1]);
> +
> +    if ( !frc && bytes[0] == 0xed && (regs->edx & 0xffff) == VMPORT_PORT &&
> +         vmcb->exitinfo2 == 0 && regs->error_code == 0 )
> +    {
> +        /*  in (%dx),%eax */
> +        uint32_t magic = regs->eax;
> +
> +        if ( magic == VMPORT_MAGIC ) {
> +            __update_guest_eip(regs, 1);
> +            vmport_ioport(IOREQ_READ, 4, 0, regs);
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* LOG_GP_VMWARE_AFTER */)
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (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);
> +            return;
> +        } else {
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* LOG_GP_NOT_VMWARE */)
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (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);
> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +        }
> +    } else if (!frc && regs->error_code == 0
> +               && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx == 0x10000)
> +    {
> +        /* "rdpmc 0x10000" */
> +        /* Not a very good emulation!  But just not faulting is good enough
> +         * to get NetApp booting. */
> +        regs->edx = regs->eax = 0;
> +
> +        __update_guest_eip(regs, inst_len);

What if inst_len is zero? (e.g. if NRIP is not supported?)


-boris

> +
> +        /* Doing the log in this case was too noisy for NetApp, so I moved
> +         * it to 'else' */
> +    } else {
> +        if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x100000 /* LOG_GP_UNKNOWN */) {
> +            printk("[HVM:%d.%d] <%s> "
> +                   "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                   "\n",
> +                   current->domain->domain_id, current->vcpu_id, __func__,
> +                   (unsigned long)vmcb->exitinfo2, (unsigned long)regs->error_code,
> +                   (unsigned long)regs->eip, (unsigned int)bytes[0],
> +                   (unsigned int)bytes[1], inst_len, frc,
> +                   (unsigned long)regs->eax, (unsigned long)regs->ebx,
> +                   (unsigned long)regs->ecx, (unsigned long)regs->edx,
> +                   (unsigned long)regs->esi, (unsigned long)regs->edi);
> +        }
> +        hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +    }
> +}
> +
>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 01/10] smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME.
  2013-12-12 22:07     ` Andrew Cooper
@ 2013-12-13 18:03       ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-13 18:03 UTC (permalink / raw)
  To: Andrew Cooper, Don Slutz
  Cc: Olaf Hering, Keir Fraser, Ian Campbell, Stefano Stabellini,
	Ian Jackson, Eddie Dong, xen-devel, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/12/13 17:07, Andrew Cooper wrote:
> On 12/12/2013 19:35, Olaf Hering wrote:
>> On Thu, Dec 12, Don Slutz wrote:
>>
>>> -    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU");
>>> +    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU plus VMware-Tools");
>> This will break other code which checks for the current string.
>> (/sys/class/dmi/id/product_name)
>>
>> Olaf
That is true, however since this is a xenstore_read, this is the default value.  I do not know of any code that checks for just "HVM domU", and it would break on any system that uses xenstore to change this to something else.
> Furthermore, the whole point of this is so the toolstack can write the
> xenstore key
>
> /local/domain/$DOMID/bios-strings/system-product-name
>
> with a custom value which will be written into the SMBios table.
True.  The default tool stack (xl) does not change this, and so I was looking into a simple way to let xl users enable this.  I can add a xenstore_read of "platform/vmware_hw", "0" (set in patch #4) to make it conditional.  This is some what optional in that VMware's stated way of using this is only after CPUID fails.
> The toolstack itself should have a big "pretend to be vmware" flag for a
> domain.
And Verizon's does and so we do not need this change.  Maybe I should have just added this to some documentation.

    -Don Slutz
> ~Andrew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 02/10] Add VMware HVM params
  2013-12-12 22:32   ` Andrew Cooper
@ 2013-12-13 18:12     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-13 18:12 UTC (permalink / raw)
  To: Andrew Cooper, Don Slutz, xen-devel
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Eddie Dong,
	Ian Jackson, Jan Beulich, Jun Nakajima, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/12/13 17:32, Andrew Cooper wrote:
> On 12/12/2013 19:15, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> Signed-off-by: Don Slutz <dslutz@verizon.com>
>> ---
>>   xen/include/public/hvm/params.h | 11 ++++++++++-
>>   1 file changed, 10 insertions(+), 1 deletion(-)
>>
>> diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
>> index 517a184..c571a1e 100644
>> --- a/xen/include/public/hvm/params.h
>> +++ b/xen/include/public/hvm/params.h
>> @@ -145,6 +145,15 @@
>>   /* SHUTDOWN_* action in case of a triple fault */
>>   #define HVM_PARAM_TRIPLE_FAULT_REASON 31
>>   
>> -#define HVM_NR_PARAMS          32
>> +/* Params for VMware */
>> +#define HVM_PARAM_VMWARE_HW                 32
>> +#define HVM_PARAM_VMPORT_LOGMASK            33
>> +#define HVM_PARAM_VMPORT_STATUS             34
>> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_TIME  35
>> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_VALUE 36
>> +#define HVM_PARAM_VMPORT_RESET_TIME         37
>> +
>> +#define HVM_NR_PARAMS          38
>> +
>>   
>>   #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
> STATUS at the very least sounds like it should be read-only from domains?
It does not need to be.  It is only written to, never read by the code.  So far I have only used it as a check (debugging help) while doing manual testing, and a simple program that just outputs the hex value was what I used.  At this point, it and the code to modify it could be removed.
    -Don
>
> You might want/need some extra logic in do_hvm_op().
>
> ~Andrew
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 02/10] Add VMware HVM params
  2013-12-13 10:52   ` Jan Beulich
@ 2013-12-13 18:13     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-13 18:13 UTC (permalink / raw)
  To: Jan Beulich, Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Jun Nakajima, xen-devel, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/13/13 05:52, Jan Beulich wrote:
>>>> On 12.12.13 at 20:15, Don Slutz <dslutz@verizon.com> wrote:
>> --- a/xen/include/public/hvm/params.h
>> +++ b/xen/include/public/hvm/params.h
>> @@ -145,6 +145,15 @@
>>   /* SHUTDOWN_* action in case of a triple fault */
>>   #define HVM_PARAM_TRIPLE_FAULT_REASON 31
>>   
>> -#define HVM_NR_PARAMS          32
>> +/* Params for VMware */
>> +#define HVM_PARAM_VMWARE_HW                 32
>> +#define HVM_PARAM_VMPORT_LOGMASK            33
>> +#define HVM_PARAM_VMPORT_STATUS             34
>> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_TIME  35
>> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_VALUE 36
>> +#define HVM_PARAM_VMPORT_RESET_TIME         37
>> +
>> +#define HVM_NR_PARAMS          38
>> +
>>   
>>   #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
> Both for reviewing purposes and from a consistency pov this
> should be in a single patch together with the hypervisor side
> implementation.
Thanks, I will move it there.  Still learning the "split a change into set of patches".
    -Don Slutz
> Jan
>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 03/10] Add cpuid_vmware_leaves
  2013-12-13 13:38       ` Andrew Cooper
@ 2013-12-13 18:55         ` Don Slutz
  2013-12-16  8:13           ` Jan Beulich
  0 siblings, 1 reply; 54+ messages in thread
From: Don Slutz @ 2013-12-13 18:55 UTC (permalink / raw)
  To: Andrew Cooper, Jan Beulich, Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Jun Nakajima, xen-devel, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/13/13 08:38, Andrew Cooper wrote:
> On 13/12/2013 10:55, Jan Beulich wrote:
>>>>> On 12.12.13 at 23:27, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>>> On 12/12/2013 19:15, Don Slutz wrote:
>>>>   int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
>>>>                  uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
>>>>   {
>>>>       struct domain *d = current->domain;
>>>>       /* Optionally shift out of the way of Viridian architectural leaves. */
>>>> -    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
>>>> +    uint32_t base = 0x40000000;
>>>>       uint32_t limit;
>>>>   
>>>> +    if ( is_viridian_domain(d) )
>>>> +        base += 0x100;
>>>> +    if ( is_vmware_domain(d) )
>>>> +        base += 0x100;
>>>> +
As a related question: Should I reply to each e-mail, or is the reply at the thread place (like here) ok?
>>> These bases need a far more scalable solution, especially as the result
>>> of each of these clauses can be changed at runtime with a cunning
>>> hvm_param_set hypercall.
I see.  Did not think about HVM_PARAM_VIRIDIAN changing and the effect it has on all the related code.  I just saw what was there for viridian and tried to add vmware support the same way.  I will look into a patch that will make the bases more scalable, not run time changeable.  I see that right now you can get the code to do strange (and maybe bad) things by changing HVM_PARAM_VIRIDIAN.  So this patch (or patches) would make is_viridian_domain() an unchangable result.  Same for is_vmware_domain() when I add it.
>>> I think that both "is pretending to be HyperV" and "is pretending to be
>>> VMware" need to be domain creation flags which are strictly static for
>>> the lifetime of the domain.
I agree with this.
>> And it seems highly questionable to me whether having both at the
>> same time makes much sense.
>>
>> Plus the new function doesn't belong in xen/arch/x86/traps.c ...
I read this as "Change to some sort of data structure to get the answer instead of a function".  This is because I do not see how to return the correct data from a function if it is not in xen/arch/x86/traps.c (like cpuid_hypervisor_leaves is) or called from there, which I would see as more confusing.
>> Jan
>>
> I would certainly agree on the sentiment of it not making much sense.
>
> However, as Xen needs viridian to run windows, I would be astounded if
> vmware VMs didn't have viridian as well, in which case it is probably
> quite likely that a vmware windows vm with vmware tools would expect to
> find viridian and vmware extensions.
I also find it strange, but could not see a reason not to try and support it.  This could be related to VMware stating that using CPUID is not 100% the way to find out you are running on VMware.

    -Don Slutz
> ~Andrew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 04/10] tools: Add support for new HVM params
  2013-12-12 22:36   ` Andrew Cooper
@ 2013-12-13 23:23     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-13 23:23 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, xen-devel, Jan Beulich,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/12/13 17:36, Andrew Cooper wrote:
> On 12/12/2013 19:15, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
[snip]
>>
>> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
>> index 649ce50..71ba64e 100644
>> --- a/tools/libxl/libxl_types.idl
>> +++ b/tools/libxl/libxl_types.idl
>> @@ -346,6 +346,8 @@ libxl_domain_build_info = Struct("domain_build_info",[
>>                                          ("timeoffset",       string),
>>                                          ("hpet",             libxl_defbool),
>>                                          ("vpt_align",        libxl_defbool),
>> +                                       ("vmware_hw",        integer),
>> +                                       ("vmport_logmask",   integer),
> "integer" in the IDL is 24 bit is it not? I would suggest uint64 to
> match the param width.
>
Will do.
>>                                          ("timer_mode",       libxl_timer_mode),
>>                                          ("nested_hvm",       libxl_defbool),
>>                                          ("smbios_firmware",  string),
>> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
>> index bd26bcc..013066d 100644
>> --- a/tools/libxl/xl_cmdimpl.c
>> +++ b/tools/libxl/xl_cmdimpl.c
>> @@ -987,6 +987,16 @@ static void parse_config_data(const char *config_source,
>>           xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
>>           xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
>>           xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 0);
>> +        if (!xlu_cfg_get_long(config, "vmware_hw",  &l, 1)) {
>> +            b_info->u.hvm.vmware_hw = l;
>> +            if (dom_info->debug)
>> +                fprintf(stderr, "vmware_hw: 0x%llx\n", (unsigned long long) b_info->u.hvm.vmware_hw);
> PRIx64 and no cast please.
Also will do.
>> +        }
>> +        if (!xlu_cfg_get_long(config, "vmport_logmask", &l, 1)) {
>> +            b_info->u.hvm.vmport_logmask = l;
>> +            if (dom_info->debug)
>> +                fprintf(stderr, "vmport_logmask: 0x%llx\n", (unsigned long long) b_info->u.hvm.vmport_logmask);
>> +        }
>>           xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
>>           xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
>>   
>> diff --git a/tools/libxl/xl_sxp.c b/tools/libxl/xl_sxp.c
>> index a16a025..9010c42 100644
>> --- a/tools/libxl/xl_sxp.c
>> +++ b/tools/libxl/xl_sxp.c
> The sxp is strictly for xm compatibility.  New features should not
> extend it.
Ok, will drop this file change.
>> @@ -102,6 +102,10 @@ void printf_info_sexp(int domid, libxl_domain_config *d_config)
>>           printf("\t\t\t(nx %s)\n", libxl_defbool_to_string(b_info->u.hvm.nx));
>>           printf("\t\t\t(viridian %s)\n",
>>                  libxl_defbool_to_string(b_info->u.hvm.viridian));
>> +        printf("\t\t\t(vmware_hw %d)\n",
>> +               b_info->u.hvm.vmware_hw);
>> +        printf("\t\t\t(vmport_logmask %x)\n",
>> +               b_info->u.hvm.vmport_logmask);
>>           printf("\t\t\t(hpet %s)\n",
>>                  libxl_defbool_to_string(b_info->u.hvm.hpet));
>>           printf("\t\t\t(vpt_align %s)\n",
>> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
>> index 6a7a781..38641c4 100644
>> --- a/xen/arch/x86/hvm/hvm.c
>> +++ b/xen/arch/x86/hvm/hvm.c
>> @@ -589,6 +589,7 @@ int hvm_domain_initialise(struct domain *d)
>>   
>>       d->arch.hvm_domain.params[HVM_PARAM_HPET_ENABLED] = 1;
>>       d->arch.hvm_domain.params[HVM_PARAM_TRIPLE_FAULT_REASON] = SHUTDOWN_reboot;
>> +    d->arch.hvm_domain.params[HVM_PARAM_VMPORT_RESET_TIME] = 15;
>>   
>>       vpic_init(d);
>>   
> This should probably be part of the patch which introduced the params.
>
> ~Andrew
Yes, patch #2 and #4 will be combined.
    -Don Slutz

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 03/10] Add cpuid_vmware_leaves
  2013-12-13 18:55         ` Don Slutz
@ 2013-12-16  8:13           ` Jan Beulich
  2013-12-19  0:51             ` Don Slutz
  0 siblings, 1 reply; 54+ messages in thread
From: Jan Beulich @ 2013-12-16  8:13 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, StefanoStabellini, Jun Nakajima,
	Andrew Cooper, Eddie Dong, Suravee Suthikulpanit, xen-devel,
	Boris Ostrovsky, Ian Jackson

>>> On 13.12.13 at 19:55, Don Slutz <dslutz@verizon.com> wrote:
> On 12/13/13 08:38, Andrew Cooper wrote:
>> On 13/12/2013 10:55, Jan Beulich wrote:
>>>>>> On 12.12.13 at 23:27, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>>>> On 12/12/2013 19:15, Don Slutz wrote:
>>>>> +    if ( is_viridian_domain(d) )
>>>>> +        base += 0x100;
>>>>> +    if ( is_vmware_domain(d) )
>>>>> +        base += 0x100;
>>>>> +
> As a related question: Should I reply to each e-mail, or is the reply at the 
> thread place (like here) ok?

Generally per-mail answers are preferred, as that makes the context
more obvious. Occasionally you'll find that overall effect is better if
you reply to multiple levels of contexts at once.

But please, for legibility's sake, include blank lines between quoted
text and your responses.

>>> And it seems highly questionable to me whether having both at the
>>> same time makes much sense.
>>>
>>> Plus the new function doesn't belong in xen/arch/x86/traps.c ...
> I read this as "Change to some sort of data structure to get the answer 
> instead of a function".  This is because I do not see how to return the 
> correct data from a function if it is not in xen/arch/x86/traps.c (like 
> cpuid_hypervisor_leaves is) or called from there, which I would see as more 
> confusing.

Just like cpuid_viridian_leaves() lives in xen/arch/x86/hvm/viridian.c,
your new function should live in e.g. xen/arch/x86/hvm/vmware.c.

Jan

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 03/10] Add cpuid_vmware_leaves
  2013-12-12 22:27   ` Andrew Cooper
  2013-12-13 10:55     ` Jan Beulich
@ 2013-12-17 16:20     ` Don Slutz
  1 sibling, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-17 16:20 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, xen-devel, Jan Beulich,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/12/13 17:27, Andrew Cooper wrote:
> On 12/12/2013 19:15, Don Slutz wrote:
>> From: Don Slutz<dslutz@verizon.com>
>>
>> Signed-off-by: Don Slutz<dslutz@verizon.com>
>> ---
>>   xen/arch/x86/hvm/hvm.c          |  3 +++
>>   xen/arch/x86/traps.c            | 58 ++++++++++++++++++++++++++++++++++++++++-
>>   xen/include/asm-x86/hvm/hvm.h   |  3 +++
>>   xen/include/asm-x86/processor.h |  2 ++
>>   4 files changed, 65 insertions(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
>> index 69f7e74..6a7a781 100644
>> --- a/xen/arch/x86/hvm/hvm.c
>> +++ b/xen/arch/x86/hvm/hvm.c
>> @@ -2878,6 +2878,9 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
>>       if ( cpuid_viridian_leaves(input, eax, ebx, ecx, edx) )
>>           return;
>>   
>> +    if ( cpuid_vmware_leaves(input, count, eax, ebx, ecx, edx) )
>> +        return;
>> +
>>       if ( cpuid_hypervisor_leaves(input, count, eax, ebx, ecx, edx) )
>>           return;
>>   
>> diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
>> index 940bc33..71a76df 100644
>> --- a/xen/arch/x86/traps.c
>> +++ b/xen/arch/x86/traps.c
>> @@ -671,14 +671,70 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
>>       return 0;
>>   }
>>   
>> +int cpuid_vmware_leaves(uint32_t idx, uint32_t sub_idx,
>> +                        uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
>> +{
>> +    struct domain *d = current->domain;
>> +    /* Optionally shift out of the way of Viridian architectural leaves. */
>> +    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
>> +    uint32_t limit;
>> +    const uint32_t apic_khz = 1000000L;
> Please use the proper constant for this.

Is this SYSTEM_TIME_HZ / 1000 ?  Or is not a constant.  All my old testing on amazon showed it to be a constant (but that is an much older xen; most likely did not use virtual apic hardware, but used qemu).  I just checked and the hardware I am testing on has:

(XEN) calibrating APIC timer ...
(XEN) ..... CPU clock speed is 2400.0122 MHz.
(XEN) ..... host bus clock speed is 100.0003 MHz.
(XEN) ..... bus_scale = 0x6669

So it may be safer to pass on the detected host bus clock speed.

>> +
>> +    if ( !is_vmware_domain(d) )
>> +        return 0;
>> +
>> +    idx -= base;
>> +
>> +    limit = 0x10;
>> +
>> +    if ( idx > limit )
>> +        return 0;
> This `limit` is pointless and the BUG() below is dead code (which
> Coverity will complain about).
>
> Please see 839b966e3f587bbb1a0d954230fb3904330dccb6 and follow its
> style, rather than propagating this bad style (which admittedly you have
> gotten from following cpuid_hypervisor_leaves() )
Will do.
>> +
>> +    switch ( idx )
>> +    {
>> +    case 0:
>> +        *eax = base + limit; /* Largest leaf */
>> +        *ebx = 0x61774d56; /* "VMwa" */
>> +        *ecx = 0x4d566572; /* "reVM" */
>> +        *edx = 0x65726177; /* "ware" */
>> +        break;
>> +
>> +    case 1 ... 0xf:
>> +        *eax = 0;          /* Reserved */
>> +        *ebx = 0;          /* Reserved */
>> +        *ecx = 0;          /* Reserved */
>> +        *edx = 0;          /* Reserved */
>> +        break;
>> +
>> +    case 0x10:
>> +        /* (Virtual) TSC frequency in kHz. */
>> +        *eax =  d->arch.tsc_khz;
>> +        /* (Virtual) Bus (local apic timer) frequency in kHz. */
>> +        *ebx = apic_khz;
>> +        *ecx = 0;          /* Reserved */
>> +        *edx = 0;          /* Reserved */
>> +        break;
>> +
>> +    default:
>> +        BUG();
>> +    }
>> +
>> +    return 1;
>> +}
>> +
>>   int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
>>                  uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
>>   {
>>       struct domain *d = current->domain;
>>       /* Optionally shift out of the way of Viridian architectural leaves. */
>> -    uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
>> +    uint32_t base = 0x40000000;
>>       uint32_t limit;
>>   
>> +    if ( is_viridian_domain(d) )
>> +        base += 0x100;
>> +    if ( is_vmware_domain(d) )
>> +        base += 0x100;
>> +
> These bases need a far more scalable solution, especially as the result
> of each of these clauses can be changed at runtime with a cunning
> hvm_param_set hypercall.
Will work on a redesign for these bases.
    -Don Slutz
> I think that both "is pretending to be HyperV" and "is pretending to be
> VMware" need to be domain creation flags which are strictly static for
> the lifetime of the domain.
>
> ~Andrew
>
>>       idx -= base;
>>   
>>       /*
>> diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
>> index ccca5df..ae3768c 100644
>> --- a/xen/include/asm-x86/hvm/hvm.h
>> +++ b/xen/include/asm-x86/hvm/hvm.h
>> @@ -332,6 +332,9 @@ static inline unsigned long hvm_get_shadow_gs_base(struct vcpu *v)
>>   #define is_viridian_domain(_d)                                             \
>>    (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VIRIDIAN]))
>>   
>> +#define is_vmware_domain(_d)                                             \
>> + (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VMWARE_HW]))
>> +
>>   void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
>>                                      unsigned int *ecx, unsigned int *edx);
>>   void hvm_migrate_timers(struct vcpu *v);
>> diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
>> index c120460..6c53e45 100644
>> --- a/xen/include/asm-x86/processor.h
>> +++ b/xen/include/asm-x86/processor.h
>> @@ -559,6 +559,8 @@ void int80_direct_trap(void);
>>   
>>   extern int hypercall(void);
>>   
>> +int cpuid_vmware_leaves( uint32_t idx, uint32_t sub_idx,
>> +          uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
>>   int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
>>             uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
>>   int rdmsr_hypervisor_regs(uint32_t idx, uint64_t *val);

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 00/10] Xen VMware tools support
  2013-12-12 19:15 [RFC PATCH 00/10] Xen VMware tools support Don Slutz
                   ` (9 preceding siblings ...)
  2013-12-12 19:15 ` [RFC PATCH 10/10] Add VMware guest info access Don Slutz
@ 2013-12-17 19:03 ` Konrad Rzeszutek Wilk
  2013-12-19  0:46   ` Don Slutz
  10 siblings, 1 reply; 54+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-12-17 19:03 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Thu, Dec 12, 2013 at 02:15:08PM -0500, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
> 
> See
> 
> http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458

Can you say how this benefits Xen to detect this and take
advantage of it? Or is this Xen emulating VMWare so to a guest
it looks like its running under VMWare?

Thank you.
> 
> for info on detecting VMware.
> 
> Linux does not follow this exactly.  It checks for CPUID 1st.  If
> that fails, it checks for SMBIOS containing "VMware" (not VMware- or
> VMW).
> 
> So this patch set provides:
> 
>         SMBIOS -- Add string VMware-
>         CPUID -- Add VMware's CPUID (Note: currently HyperV (viridian support) breaks this check.)
>         Add the magic VMware port
>             Allow VMware tools poweroff and reboot
>             Enable access to VMware's guest info
>             Provide the VMware tools build number
> 
> Don Slutz (10):
>   smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME.
>   Add VMware HVM params
>   Add cpuid_vmware_leaves
>   tools: Add support for new HVM params
>   vmport: Add VMware provided include files.
>   Add vmport structs
>   Add new vmport code.
>   connect vmport up
>   libxl: Add VTPOWER, VTREBOOT and VTPING
>   Add VMware guest info access
> 
>  tools/firmware/hvmloader/smbios.c        |   2 +-
>  tools/libxc/xc_domain.c                  | 112 +++++
>  tools/libxc/xc_domain_restore.c          |  27 ++
>  tools/libxc/xc_domain_save.c             |  24 ++
>  tools/libxc/xenctrl.h                    |  24 ++
>  tools/libxc/xg_save_restore.h            |   2 +
>  tools/libxl/libxl.c                      |  12 +
>  tools/libxl/libxl_create.c               |   4 +-
>  tools/libxl/libxl_dom.c                  |   5 +
>  tools/libxl/libxl_types.idl              |   5 +
>  tools/libxl/xl_cmdimpl.c                 |  10 +
>  tools/libxl/xl_cmdtable.c                |   2 +-
>  tools/libxl/xl_sxp.c                     |   4 +
>  xen/arch/x86/domctl.c                    |  34 ++
>  xen/arch/x86/hvm/Makefile                |   1 +
>  xen/arch/x86/hvm/hvm.c                   | 209 ++++++++-
>  xen/arch/x86/hvm/io.c                    |   4 +
>  xen/arch/x86/hvm/svm/svm.c               | 104 +++++
>  xen/arch/x86/hvm/svm/vmcb.c              |   1 +
>  xen/arch/x86/hvm/vmport/Makefile         |   1 +
>  xen/arch/x86/hvm/vmport/backdoor_def.h   | 167 +++++++
>  xen/arch/x86/hvm/vmport/guest_msg_def.h  |  87 ++++
>  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/arch/x86/hvm/vmx/vmcs.c              |   1 +
>  xen/arch/x86/hvm/vmx/vmx.c               | 125 ++++++
>  xen/arch/x86/hvm/vmx/vvmx.c              |  13 +
>  xen/arch/x86/traps.c                     |  58 ++-
>  xen/include/asm-x86/hvm/domain.h         |   4 +
>  xen/include/asm-x86/hvm/hvm.h            |   3 +
>  xen/include/asm-x86/hvm/trace.h          |   3 +
>  xen/include/asm-x86/hvm/vmport.h         |  77 ++++
>  xen/include/asm-x86/processor.h          |   2 +
>  xen/include/public/domctl.h              |   3 +
>  xen/include/public/hvm/hvm_op.h          |  18 +
>  xen/include/public/hvm/params.h          |  11 +-
>  xen/include/public/trace.h               |   1 +
>  38 files changed, 1926 insertions(+), 6 deletions(-)
>  create mode 100644 xen/arch/x86/hvm/vmport/Makefile
>  create mode 100644 xen/arch/x86/hvm/vmport/backdoor_def.h
>  create mode 100644 xen/arch/x86/hvm/vmport/guest_msg_def.h
>  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
>  create mode 100644 xen/include/asm-x86/hvm/vmport.h
> 
> -- 
> 1.8.4
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 02/10] Add VMware HVM params
  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 10:52   ` Jan Beulich
@ 2013-12-17 20:02   ` Konrad Rzeszutek Wilk
  2013-12-19  0:47     ` Don Slutz
  2 siblings, 1 reply; 54+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-12-17 20:02 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Thu, Dec 12, 2013 at 02:15:10PM -0500, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
> 
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  xen/include/public/hvm/params.h | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
> index 517a184..c571a1e 100644
> --- a/xen/include/public/hvm/params.h
> +++ b/xen/include/public/hvm/params.h
> @@ -145,6 +145,15 @@
>  /* SHUTDOWN_* action in case of a triple fault */
>  #define HVM_PARAM_TRIPLE_FAULT_REASON 31
>  
> -#define HVM_NR_PARAMS          32
> +/* Params for VMware */
> +#define HVM_PARAM_VMWARE_HW                 32
> +#define HVM_PARAM_VMPORT_LOGMASK            33
> +#define HVM_PARAM_VMPORT_STATUS             34
> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_TIME  35
> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_VALUE 36
> +#define HVM_PARAM_VMPORT_RESET_TIME         37

Could these values be passed via XenBus?

> +
> +#define HVM_NR_PARAMS          38
> +
>  
>  #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
> -- 
> 1.8.4
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 05/10] vmport: Add VMware provided include files.
  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
  0 siblings, 1 reply; 54+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-12-17 20:22 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Thu, Dec 12, 2013 at 02:15:13PM -0500, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
> 
> These 2 files: backdoor_def.h and guest_msg_def.h come from:
> 
> http://packages.vmware.com/tools/esx/3.5latest/rhel4/SRPMS/index.html
>  open-vm-tools-kmod-7.4.8-396269.423167.src.rpm
>   open-vm-tools-kmod-7.4.8.tar.gz
>    vmhgfs/backdoor_def.h
>    vmhgfs/guest_msg_def.h
> 
> and are unchanged.
> 
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  xen/arch/x86/hvm/vmport/backdoor_def.h  | 167 ++++++++++++++++++++++++++++++++
>  xen/arch/x86/hvm/vmport/guest_msg_def.h |  87 +++++++++++++++++
>  2 files changed, 254 insertions(+)
>  create mode 100644 xen/arch/x86/hvm/vmport/backdoor_def.h
>  create mode 100644 xen/arch/x86/hvm/vmport/guest_msg_def.h
> 
> diff --git a/xen/arch/x86/hvm/vmport/backdoor_def.h b/xen/arch/x86/hvm/vmport/backdoor_def.h
> new file mode 100644
> index 0000000..e76795f
> --- /dev/null
> +++ b/xen/arch/x86/hvm/vmport/backdoor_def.h
> @@ -0,0 +1,167 @@
> +/* **********************************************************
> + * Copyright 1998 VMware, Inc.  All rights reserved. 
> + * **********************************************************
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation version 2 and no later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

Please don't include the address. It should be:

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +/*
> + * backdoor_def.h --
> + *
> + * This contains backdoor defines that can be included from
> + * an assembly language file.
> + */
> +
> +
> +
> +#ifndef _BACKDOOR_DEF_H_
> +#define _BACKDOOR_DEF_H_
> +
> +#define INCLUDE_ALLOW_MODULE
> +#define INCLUDE_ALLOW_USERLEVEL
> +#define INCLUDE_ALLOW_VMMEXT
> +#define INCLUDE_ALLOW_VMCORE
> +#define INCLUDE_ALLOW_VMKERNEL
> +#include "includeCheck.h"
> +
> +/*
> + * If you want to add a new low-level backdoor call for a guest userland
> + * application, please consider using the GuestRpc mechanism instead. --hpreg
> + */
> +
> +#define BDOOR_MAGIC 0x564D5868
> +
> +/* Low-bandwidth backdoor port. --hpreg */
> +
> +#define BDOOR_PORT 0x5658
> +
> +#define BDOOR_CMD_GETMHZ      		   1
> +/*
> + * BDOOR_CMD_APMFUNCTION is used by:
> + *
> + * o The FrobOS code, which instead should either program the virtual chipset
> + *   (like the new BIOS code does, matthias offered to implement that), or not
> + *   use any VM-specific code (which requires that we correctly implement
> + *   "power off on CLI HLT" for SMP VMs, boris offered to implement that)
> + *
> + * o The old BIOS code, which will soon be jettisoned
> + *
> + *  --hpreg
> + */
> +#define BDOOR_CMD_APMFUNCTION 		   2
> +#define BDOOR_CMD_GETDISKGEO  		   3
> +#define BDOOR_CMD_GETPTRLOCATION	      4
> +#define BDOOR_CMD_SETPTRLOCATION	      5
> +#define BDOOR_CMD_GETSELLENGTH		   6
> +#define BDOOR_CMD_GETNEXTPIECE		   7
> +#define BDOOR_CMD_SETSELLENGTH		   8
> +#define BDOOR_CMD_SETNEXTPIECE		   9
> +#define BDOOR_CMD_GETVERSION		      10
> +#define BDOOR_CMD_GETDEVICELISTELEMENT	11
> +#define BDOOR_CMD_TOGGLEDEVICE		   12
> +#define BDOOR_CMD_GETGUIOPTIONS		   13
> +#define BDOOR_CMD_SETGUIOPTIONS		   14
> +#define BDOOR_CMD_GETSCREENSIZE		   15
> +#define BDOOR_CMD_MONITOR_CONTROL       16
> +#define BDOOR_CMD_GETHWVERSION          17
> +#define BDOOR_CMD_OSNOTFOUND            18
> +#define BDOOR_CMD_GETUUID               19
> +#define BDOOR_CMD_GETMEMSIZE            20
> +#define BDOOR_CMD_HOSTCOPY              21 /* Devel only */
> +/* BDOOR_CMD_GETOS2INTCURSOR, 22, is very old and defunct. Reuse. */
> +#define BDOOR_CMD_GETTIME               23 /* Deprecated. Use GETTIMEFULL. */
> +#define BDOOR_CMD_STOPCATCHUP           24
> +#define BDOOR_CMD_PUTCHR	        25 /* Devel only */
> +#define BDOOR_CMD_ENABLE_MSG	        26 /* Devel only */
> +#define BDOOR_CMD_GOTO_TCL	        27 /* Devel only */
> +#define BDOOR_CMD_INITPCIOPROM		28
> +#define BDOOR_CMD_INT13			29
> +#define BDOOR_CMD_MESSAGE               30
> +#define BDOOR_CMD_RSVD0                 31
> +#define BDOOR_CMD_RSVD1                 32
> +#define BDOOR_CMD_RSVD2                 33
> +#define BDOOR_CMD_ISACPIDISABLED	34
> +#define BDOOR_CMD_TOE			35 /* Not in use */
> +/* BDOOR_CMD_INITLSIOPROM, 36, was merged with 28. Reuse. */
> +#define BDOOR_CMD_PATCH_SMBIOS_STRUCTS  37
> +#define BDOOR_CMD_MAPMEM                38 /* Devel only */
> +#define BDOOR_CMD_ABSPOINTER_DATA	39
> +#define BDOOR_CMD_ABSPOINTER_STATUS	40
> +#define BDOOR_CMD_ABSPOINTER_COMMAND	41
> +#define BDOOR_CMD_TIMER_SPONGE          42
> +#define BDOOR_CMD_PATCH_ACPI_TABLES	43
> +/* Catch-all to allow synchronous tests */
> +#define BDOOR_CMD_DEVEL_FAKEHARDWARE	44 /* Debug only - needed in beta */
> +#define BDOOR_CMD_GETHZ      		45
> +#define BDOOR_CMD_GETTIMEFULL           46
> +#define BDOOR_CMD_STATELOGGER           47
> +#define BDOOR_CMD_CHECKFORCEBIOSSETUP	48
> +#define BDOOR_CMD_LAZYTIMEREMULATION    49
> +#define BDOOR_CMD_BIOSBBS               50
> +#define BDOOR_CMD_MAX                   51
> +
> +/* 
> + * IMPORTANT NOTE: When modifying the behavior of an existing backdoor command,
> + * you must adhere to the semantics expected by the oldest Tools who use that
> + * command. Specifically, do not alter the way in which the command modifies 
> + * the registers. Otherwise backwards compatibility will suffer.
> + */
> +
> +/* High-bandwidth backdoor port. --hpreg */
> +
> +#define BDOORHB_PORT 0x5659
> +
> +#define BDOORHB_CMD_MESSAGE 0
> +#define BDOORHB_CMD_MAX 1
> +
> +/*
> + * There is another backdoor which allows access to certain TSC-related
> + * values using otherwise illegal PMC indices when the pseudo_perfctr
> + * control flag is set.
> + */
> +
> +#define BDOOR_PMC_HW_TSC      0x10000
> +#define BDOOR_PMC_REAL_NS     0x10001
> +#define BDOOR_PMC_APPARENT_NS 0x10002
> +
> +#define IS_BDOOR_PMC(index)  (((index) | 3) == 0x10003)
> +#define BDOOR_CMD(ecx)       ((ecx) & 0xffff)
> +
> +
> +#ifdef VMM
> +/*
> + *----------------------------------------------------------------------
> + *
> + * Backdoor_CmdRequiresFullyValidVCPU --
> + *
> + *    A few backdoor commands require the full VCPU to be valid
> + *    (including GDTR, IDTR, TR and LDTR). The rest get read/write
> + *    access to GPRs and read access to Segment registers (selectors).
> + *
> + * Result:
> + *    True iff VECX contains a command that require the full VCPU to
> + *    be valid.
> + *
> + *----------------------------------------------------------------------
> + */
> +static INLINE Bool
> +Backdoor_CmdRequiresFullyValidVCPU(unsigned cmd)
> +{
> +   return cmd == BDOOR_CMD_RSVD0 ||
> +          cmd == BDOOR_CMD_RSVD1 ||
> +          cmd == BDOOR_CMD_RSVD2;
> +}
> +#endif
> +
> +#endif
> diff --git a/xen/arch/x86/hvm/vmport/guest_msg_def.h b/xen/arch/x86/hvm/vmport/guest_msg_def.h
> new file mode 100644
> index 0000000..44ae0fa
> --- /dev/null
> +++ b/xen/arch/x86/hvm/vmport/guest_msg_def.h
> @@ -0,0 +1,87 @@
> +/* **********************************************************
> + * Copyright 1998 VMware, Inc.  All rights reserved. 
> + * **********************************************************
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation version 2 and no later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

Ditto:

 You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +/*
> + * guest_msg_def.h --
> + *
> + *    Second layer of the internal communication channel between guest
> + *    applications and vmware
> + *
> + */
> +
> +#ifndef _GUEST_MSG_DEF_H_
> +#define _GUEST_MSG_DEF_H_
> +
> +#define INCLUDE_ALLOW_MODULE
> +#define INCLUDE_ALLOW_USERLEVEL
> +#define INCLUDE_ALLOW_VMMEXT
> +#include "includeCheck.h"
> +
> +
> +/* Basic request types */
> +typedef enum {
> +   MESSAGE_TYPE_OPEN,
> +   MESSAGE_TYPE_SENDSIZE,
> +   MESSAGE_TYPE_SENDPAYLOAD,
> +   MESSAGE_TYPE_RECVSIZE,
> +   MESSAGE_TYPE_RECVPAYLOAD,
> +   MESSAGE_TYPE_RECVSTATUS,
> +   MESSAGE_TYPE_CLOSE,
> +} MessageType;
> +
> +
> +/* Reply statuses */
> +/*  The basic request succeeded */
> +#define MESSAGE_STATUS_SUCCESS  0x0001
> +/*  vmware has a message available for its party */
> +#define MESSAGE_STATUS_DORECV   0x0002
> +/*  The channel has been closed */
> +#define MESSAGE_STATUS_CLOSED   0x0004
> +/*  vmware removed the message before the party fetched it */
> +#define MESSAGE_STATUS_UNSENT   0x0008
> +/*  A checkpoint occurred */
> +#define MESSAGE_STATUS_CPT      0x0010
> +/*  An underlying device is powering off */
> +#define MESSAGE_STATUS_POWEROFF 0x0020
> +/*  vmware has detected a timeout on the channel */
> +#define MESSAGE_STATUS_TIMEOUT  0x0040
> +/*  vmware supports high-bandwidth for sending and receiving the payload */
> +#define MESSAGE_STATUS_HB       0x0080
> +
> +/*
> + * This mask defines the status bits that the guest is allowed to set;
> + * we use this to mask out all other bits when receiving the status
> + * from the guest. Otherwise, the guest can manipulate VMX state by
> + * setting status bits that are only supposed to be changed by the
> + * VMX. See bug 45385.
> + */
> +#define MESSAGE_STATUS_GUEST_MASK    MESSAGE_STATUS_SUCCESS
> +
> +/*
> + * Max number of channels.
> + * Unfortunately this has to be public because the monitor part
> + * of the backdoor needs it for its trivial-case optimization. [greg]
> + */
> +#define GUESTMSG_MAX_CHANNEL 8
> +
> +/* Flags to open a channel. --hpreg */
> +#define GUESTMSG_FLAG_COOKIE 0x80000000
> +#define GUESTMSG_FLAG_ALL GUESTMSG_FLAG_COOKIE
> +
> +
> +#endif /* _GUEST_MSG_DEF_H_ */
> -- 
> 1.8.4
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 09/10] libxl: Add VTPOWER, VTREBOOT and VTPING
  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
  1 sibling, 0 replies; 54+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-12-17 20:30 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Thu, Dec 12, 2013 at 02:15:17PM -0500, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
> 
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  tools/libxl/libxl.c         | 12 ++++++++++++
>  tools/libxl/libxl_types.idl |  3 +++
>  tools/libxl/xl_cmdtable.c   |  2 +-
>  xen/arch/x86/domctl.c       | 34 ++++++++++++++++++++++++++++++++++
>  xen/include/public/domctl.h |  3 +++
>  5 files changed, 53 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> index fd8b988..1ec8484 100644
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -5057,6 +5057,18 @@ int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid,
>          rc = xc_domain_send_trigger(ctx->xch, domid,
>                                      XEN_DOMCTL_SENDTRIGGER_SLEEP, vcpuid);
>          break;
> +    case LIBXL_TRIGGER_VTPOWER:
> +        rc = xc_domain_send_trigger(ctx->xch, domid,
> +                                    XEN_DOMCTL_SENDTRIGGER_VTPOWER, vcpuid);
> +        break;
> +    case LIBXL_TRIGGER_VTREBOOT:
> +        rc = xc_domain_send_trigger(ctx->xch, domid,
> +                                    XEN_DOMCTL_SENDTRIGGER_VTREBOOT, vcpuid);
> +        break;

Why not use the reboot/power and switch over to the VmWare ones when
detecting the guest as running VMWare? 


> +    case LIBXL_TRIGGER_VTPING:
> +        rc = xc_domain_send_trigger(ctx->xch, domid,
> +                                    XEN_DOMCTL_SENDTRIGGER_VTPING, vcpuid);
> +        break;
>      case LIBXL_TRIGGER_NMI:
>          rc = xc_domain_send_trigger(ctx->xch, domid,
>                                      XEN_DOMCTL_SENDTRIGGER_NMI, vcpuid);
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 71ba64e..80a8ee8 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -105,6 +105,9 @@ libxl_trigger = Enumeration("trigger", [
>      (4, "INIT"),
>      (5, "RESET"),
>      (6, "S3RESUME"),
> +    (7, "VTPOWER"),
> +    (8, "VTREBOOT"),
> +    (9, "VTPING"),
>      ])
>  
>  libxl_tsc_mode = Enumeration("tsc_mode", [
> diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
> index ebe0220..98db8ae 100644
> --- a/tools/libxl/xl_cmdtable.c
> +++ b/tools/libxl/xl_cmdtable.c
> @@ -290,7 +290,7 @@ struct cmd_spec cmd_table[] = {
>      { "trigger",
>        &main_trigger, 0, 1,
>        "Send a trigger to a domain",
> -      "<Domain> <nmi|reset|init|power|sleep|s3resume> [<VCPU>]",
> +      "<Domain> <nmi|reset|init|power|sleep|s3resume|vtpower|vtreboot|vtping> [<VCPU>]",
>      },
>      { "sysrq",
>        &main_sysrq, 0, 1,
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index ef6c140..8b77ce2 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -23,6 +23,7 @@
>  #include <xen/paging.h>
>  #include <asm/irq.h>
>  #include <asm/hvm/hvm.h>
> +#include <asm/hvm/vmport.h>
>  #include <asm/hvm/support.h>
>  #include <asm/hvm/cacheattr.h>
>  #include <asm/processor.h>
> @@ -577,6 +578,39 @@ long arch_do_domctl(
>          }
>          break;
>  
> +        case XEN_DOMCTL_SENDTRIGGER_VTPOWER:
> +        {
> +            ret = -EINVAL;
> +            if ( is_hvm_domain(d) )
> +            {
> +                ret = 0;
> +                vmport_ctrl_send(&d->arch.hvm_domain, "OS_Halt", 1);
> +            }
> +        }
> +        break;
> +
> +        case XEN_DOMCTL_SENDTRIGGER_VTREBOOT:
> +        {
> +            ret = -EINVAL;
> +            if ( is_hvm_domain(d) )
> +            {
> +                ret = 0;
> +                vmport_ctrl_send(&d->arch.hvm_domain, "OS_Reboot", 2);
> +            }
> +        }
> +        break;
> +
> +        case XEN_DOMCTL_SENDTRIGGER_VTPING:
> +        {
> +            ret = -EINVAL;
> +            if ( is_hvm_domain(d) )
> +            {
> +                ret = 0;
> +                vmport_ctrl_send(&d->arch.hvm_domain, "ping", 3);
> +            }
> +        }
> +        break;
> +
>          default:
>              ret = -ENOSYS;
>          }
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index 01a3652..d71d57c 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -454,6 +454,9 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t);
>  #define XEN_DOMCTL_SENDTRIGGER_INIT   2
>  #define XEN_DOMCTL_SENDTRIGGER_POWER  3
>  #define XEN_DOMCTL_SENDTRIGGER_SLEEP  4
> +#define XEN_DOMCTL_SENDTRIGGER_VTPOWER  5
> +#define XEN_DOMCTL_SENDTRIGGER_VTREBOOT 6
> +#define XEN_DOMCTL_SENDTRIGGER_VTPING   7
>  struct xen_domctl_sendtrigger {
>      uint32_t  trigger;  /* IN */
>      uint32_t  vcpu;     /* IN */
> -- 
> 1.8.4
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 10/10] Add VMware guest info access
  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
  2 siblings, 0 replies; 54+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-12-17 20:34 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Thu, Dec 12, 2013 at 02:15:18PM -0500, Don Slutz wrote:
> 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));

Why not use the bounce buffer? That would save you some of this alloc
and free.

> +    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);

So what if key_len and val_len are greater than what you
allocated?

> +    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);

Ditto. key_len could be bigger than what you allocated.

> +    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);

I am failing to understand why you are using a hypercall to store/get
values when they could be stored/retrieved using a XenBus?

If we want a key-value store system it might be better to implement one
that is generic for everybody. But if we do that - then why not
do it using XenBus?


> +
>  #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
> -- 
> 1.8.4
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 07/10] Add new vmport code.
  2013-12-12 19:15 ` [RFC PATCH 07/10] Add new vmport code Don Slutz
  2013-12-13  0:06   ` Andrew Cooper
  2013-12-13 10:59   ` Jan Beulich
@ 2013-12-17 20:36   ` Konrad Rzeszutek Wilk
  2013-12-19  2:29     ` Don Slutz
  2 siblings, 1 reply; 54+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-12-17 20:36 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Thu, Dec 12, 2013 at 02:15:15PM -0500, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>
> 
> enable vmport_flush call.

I think this patch needs a bigger description of what it does!

> 
> 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
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 08/10] connect vmport up
  2013-12-12 19:15 ` [RFC PATCH 08/10] connect vmport up Don Slutz
  2013-12-13  0:51   ` Andrew Cooper
  2013-12-13 15:46   ` Boris Ostrovsky
@ 2013-12-17 20:37   ` Konrad Rzeszutek Wilk
  2013-12-19  3:46     ` Don Slutz
  2 siblings, 1 reply; 54+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-12-17 20:37 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Thu, Dec 12, 2013 at 02:15:16PM -0500, Don Slutz wrote:
> From: Don Slutz <dslutz@verizon.com>

Please add a description of what this does.

> 
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
>  xen/arch/x86/hvm/io.c       |   4 ++
>  xen/arch/x86/hvm/svm/svm.c  | 104 ++++++++++++++++++++++++++++++++++++
>  xen/arch/x86/hvm/svm/vmcb.c |   1 +
>  xen/arch/x86/hvm/vmx/vmcs.c |   1 +
>  xen/arch/x86/hvm/vmx/vmx.c  | 125 ++++++++++++++++++++++++++++++++++++++++++++
>  xen/arch/x86/hvm/vmx/vvmx.c |  13 +++++
>  xen/include/public/trace.h  |   1 +
>  7 files changed, 249 insertions(+)
> 
> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
> index bf6309d..4bc4716 100644
> --- a/xen/arch/x86/hvm/io.c
> +++ b/xen/arch/x86/hvm/io.c
> @@ -42,6 +42,7 @@
>  #include <asm/hvm/vlapic.h>
>  #include <asm/hvm/trace.h>
>  #include <asm/hvm/emulate.h>
> +#include <asm/hvm/vmport.h>
>  #include <public/sched.h>
>  #include <xen/iocap.h>
>  #include <public/hvm/ioreq.h>
> @@ -236,6 +237,9 @@ int handle_pio(uint16_t port, unsigned int size, int dir)
>      if ( dir == IOREQ_WRITE )
>          data = guest_cpu_user_regs()->eax;
>  
> +    if ( port == VMPORT_PORT )
> +        return vmport_ioport(dir, size, data, guest_cpu_user_regs());
> +
>      rc = hvmemul_do_pio(port, &reps, size, 0, dir, 0, &data);
>  
>      switch ( rc )
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index 406d394..80cf2bf 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -56,6 +56,7 @@
>  #include <asm/hvm/svm/nestedsvm.h>
>  #include <asm/hvm/nestedhvm.h>
>  #include <asm/x86_emulate.h>
> +#include <asm/hvm/vmport.h>
>  #include <public/sched.h>
>  #include <asm/hvm/vpt.h>
>  #include <asm/hvm/trace.h>
> @@ -1904,6 +1905,105 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
>      return;
>  }
>  
> +static void svm_vmexit_gp_intercept(struct cpu_user_regs *regs, struct vcpu *v)
> +{
> +    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
> +    unsigned long inst_len, bytes_len;
> +    int frc;
> +    unsigned char bytes[15];
> +
> +    regs->error_code = vmcb->exitinfo1;
> +    if ( !cpu_has_svm_nrips || (vmcb->nextrip <= vmcb->rip) )
> +        inst_len = 0;
> +    else
> +        inst_len = vmcb->nextrip - vmcb->rip;
> +    bytes_len = 2 /* inst_len < 15 ? inst_len > 1 ? inst_len : 2 : 15 */;
> +    frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
> +                                            bytes_len,
> +                                            PFEC_page_present);
> +
> +    if ( hvm_long_mode_enabled(v) )
> +        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
> +                         regs->error_code,
> +                         TRC_PAR_LONG(vmcb->exitinfo2) );
> +    else
> +        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
> +                    regs->error_code, vmcb->exitinfo2 );
> +
> +    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* LOG_GP_FAIL_RD_INST */)
> +        printk("[HVM:%d.%d] <%s> "
> +               "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%ld,%d) nip(%d)=%lx(%d,%d(0x%x) 0x%x 0x%x)"
> +               "\n",
> +               current->domain->domain_id, current->vcpu_id, __func__,
> +               (unsigned long)vmcb->exitinfo2,
> +               (unsigned long)regs->error_code,
> +               (unsigned long)regs->eip, (unsigned int)bytes[0],
> +               (unsigned int)bytes[1], bytes_len, inst_len, frc,
> +               cpu_has_svm_nrips, (unsigned long)vmcb->nextrip,
> +               cpu_has_svm_decode, vmcb->guest_ins_len & 0xf, vmcb->guest_ins_len,
> +               vmcb->guest_ins[0], vmcb->guest_ins[1]);
> +
> +    if ( !frc && bytes[0] == 0xed && (regs->edx & 0xffff) == VMPORT_PORT &&
> +         vmcb->exitinfo2 == 0 && regs->error_code == 0 )
> +    {
> +        /*  in (%dx),%eax */
> +        uint32_t magic = regs->eax;
> +
> +        if ( magic == VMPORT_MAGIC ) {
> +            __update_guest_eip(regs, 1);
> +            vmport_ioport(IOREQ_READ, 4, 0, regs);
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* LOG_GP_VMWARE_AFTER */)
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (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);
> +            return;
> +        } else {
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* LOG_GP_NOT_VMWARE */)
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (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);
> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +        }
> +    } else if (!frc && regs->error_code == 0
> +               && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx == 0x10000)
> +    {
> +        /* "rdpmc 0x10000" */
> +        /* Not a very good emulation!  But just not faulting is good enough
> +         * to get NetApp booting. */
> +        regs->edx = regs->eax = 0;
> +
> +        __update_guest_eip(regs, inst_len);
> +
> +        /* Doing the log in this case was too noisy for NetApp, so I moved
> +         * it to 'else' */
> +    } else {
> +        if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x100000 /* LOG_GP_UNKNOWN */) {
> +            printk("[HVM:%d.%d] <%s> "
> +                   "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                   "\n",
> +                   current->domain->domain_id, current->vcpu_id, __func__,
> +                   (unsigned long)vmcb->exitinfo2, (unsigned long)regs->error_code,
> +                   (unsigned long)regs->eip, (unsigned int)bytes[0],
> +                   (unsigned int)bytes[1], inst_len, frc,
> +                   (unsigned long)regs->eax, (unsigned long)regs->ebx,
> +                   (unsigned long)regs->ecx, (unsigned long)regs->edx,
> +                   (unsigned long)regs->esi, (unsigned long)regs->edi);
> +        }
> +        hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +    }
> +}
> +
>  static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs)
>  {
>      struct hvm_emulate_ctxt ctxt;
> @@ -2253,6 +2353,10 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
>          break;
>      }
>  
> +    case VMEXIT_EXCEPTION_GP:
> +        svm_vmexit_gp_intercept(regs, v);
> +        break;
> +
>      case VMEXIT_EXCEPTION_UD:
>          svm_vmexit_ud_intercept(regs);
>          break;
> diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
> index 21292bb..791c045 100644
> --- a/xen/arch/x86/hvm/svm/vmcb.c
> +++ b/xen/arch/x86/hvm/svm/vmcb.c
> @@ -193,6 +193,7 @@ static int construct_vmcb(struct vcpu *v)
>  
>      vmcb->_exception_intercepts =
>          HVM_TRAP_MASK
> +        | (1U << TRAP_gp_fault)
>          | (1U << TRAP_no_device);
>  
>      if ( paging_mode_hap(v->domain) )
> diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
> index 44f33cb..21cde2f 100644
> --- a/xen/arch/x86/hvm/vmx/vmcs.c
> +++ b/xen/arch/x86/hvm/vmx/vmcs.c
> @@ -1074,6 +1074,7 @@ static int construct_vmcs(struct vcpu *v)
>  
>      v->arch.hvm_vmx.exception_bitmap = HVM_TRAP_MASK
>                | (paging_mode_hap(d) ? 0 : (1U << TRAP_page_fault))
> +              | (1U << TRAP_gp_fault)
>                | (1U << TRAP_no_device);
>      vmx_update_exception_bitmap(v);
>  
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index dfff628..248900d 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -44,6 +44,7 @@
>  #include <asm/hvm/support.h>
>  #include <asm/hvm/vmx/vmx.h>
>  #include <asm/hvm/vmx/vmcs.h>
> +#include <asm/hvm/vmport.h>
>  #include <public/sched.h>
>  #include <public/hvm/ioreq.h>
>  #include <asm/hvm/vpic.h>
> @@ -1211,6 +1212,7 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
>                  v->arch.hvm_vmx.exception_bitmap = HVM_TRAP_MASK
>                            | (paging_mode_hap(v->domain) ?
>                               0 : (1U << TRAP_page_fault))
> +                          | (1U << TRAP_gp_fault)
>                            | (1U << TRAP_no_device);
>                  vmx_update_exception_bitmap(v);
>                  vmx_update_debug_state(v);
> @@ -2454,6 +2456,113 @@ static void vmx_idtv_reinject(unsigned long idtv_info)
>      }
>  }
>  
> +void do_gp_fault(struct cpu_user_regs *regs, struct vcpu *v)
> +{
> +    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +    unsigned long exit_qualification;
> +    unsigned long inst_len;
> +    unsigned long ecode;
> +
> +    __vmread(EXIT_QUALIFICATION, &exit_qualification);
> +    __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
> +    __vmread(VM_EXIT_INTR_ERROR_CODE, &ecode);
> +    regs->error_code = ecode;
> +    if ( hvm_long_mode_enabled(v) )
> +        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
> +                         regs->error_code,
> +                         TRC_PAR_LONG(exit_qualification) );
> +    else
> +        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
> +                    regs->error_code, exit_qualification );
> +
> +    if ( inst_len == 1 && (regs->edx & 0xffff) == VMPORT_PORT &&
> +         exit_qualification == 0 && regs->error_code == 0 ) {
> +        uint32_t magic = regs->eax;
> +
> +        if ( magic == VMPORT_MAGIC ) {
> +            unsigned char bytes[1];
> +            int frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
> +                                                        1, PFEC_page_present);
> +            if (!frc && bytes[0] == 0xed) { /*  in (%dx),%eax */
> +                update_guest_eip();
> +                vmport_ioport(IOREQ_READ, 4, 0, regs);
> +                if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* LOG_GP_VMWARE_AFTER */)
> +                    printk("[HVM:%d.%d] <%s> "
> +                           "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                           "\n",
> +                           current->domain->domain_id, current->vcpu_id, __func__,
> +                           (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);
> +                return;
> +            } else {
> +                if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* LOG_GP_FAIL_RD_INST */)
> +                    printk("[HVM:%d.%d] <%s> "
> +                           "gp: VMware? ip=%lx=>0x%x(%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                           "\n",
> +                           current->domain->domain_id, current->vcpu_id, __func__,
> +                           (unsigned long)regs->eip, bytes[0], frc,
> +                           (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 (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* LOG_GP_NOT_VMWARE */)
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (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);
> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +        }
> +    } else {
> +        unsigned char bytes[15];
> +        int frc;
> +
> +        /*
> +         * We can conditionalize this call on inst_len == 2 if we decide to
> +         * remove the following printk.
> +         */
> +        frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
> +                                                inst_len < 15 ? inst_len : 15,
> +                                                PFEC_page_present);
> +
> +        /* Emulate "rdpmc 0x10000" */
> +        if (!frc && inst_len == 2 && regs->error_code == 0
> +            && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx == 0x10000)
> +        {
> +            /* Not a very good emulation!  But just not faulting is good enough
> +             * to get NetApp booting. */
> +            regs->edx = regs->eax = 0;
> +
> +            update_guest_eip();
> +
> +            /* Doing the log in this case was too noisy for NetApp, so I moved
> +             * it to 'else' */
> +        } else {
> +            /* We should probably turn this log off by default in production in
> +             * case somebody decides to do a lot of #GPs. */
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x100000 /* LOG_GP_UNKNOWN */) {
> +                printk("[HVM:%d.%d] <%s> "
> +                       "gp: eq=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%d) ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                       "\n",
> +                       current->domain->domain_id, current->vcpu_id, __func__,
> +                       (unsigned long)exit_qualification, (unsigned long)regs->error_code,
> +                       (unsigned long)regs->eip, (unsigned int)bytes[0],
> +                       (unsigned int)bytes[1], inst_len, frc,
> +                       (unsigned long)regs->eax, (unsigned long)regs->ebx,
> +                       (unsigned long)regs->ecx, (unsigned long)regs->edx,
> +                       (unsigned long)regs->esi, (unsigned long)regs->edi);
> +            }
> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
> +        }
> +    }
> +}
> +
>  static int vmx_handle_apic_write(void)
>  {
>      unsigned long exit_qualification;
> @@ -2562,6 +2671,19 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
>                   && vector != TRAP_nmi 
>                   && vector != TRAP_machine_check ) 
>              {
> +                if (vector == TRAP_gp_fault ) {
> +                    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +
> +                    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x8000000 /* LOG_REALMODE_GP */)
> +                        printk("[HVM:%d.%d] <%s> "
> +                               "realmode gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
> +                               "\n",
> +                               current->domain->domain_id, current->vcpu_id, __func__,
> +                               (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);
> +                }
>                  perfc_incr(realmode_exits);
>                  v->arch.hvm_vmx.vmx_emulate = 1;
>                  HVMTRACE_0D(REALMODE_EMULATE);
> @@ -2677,6 +2799,9 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
>              HVMTRACE_1D(TRAP, vector);
>              vmx_fpu_dirty_intercept();
>              break;
> +        case TRAP_gp_fault:
> +            do_gp_fault(regs, v);
> +            break;
>          case TRAP_page_fault:
>              __vmread(EXIT_QUALIFICATION, &exit_qualification);
>              __vmread(VM_EXIT_INTR_ERROR_CODE, &ecode);
> diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
> index 0daad79..fcd03dd 100644
> --- a/xen/arch/x86/hvm/vmx/vvmx.c
> +++ b/xen/arch/x86/hvm/vmx/vvmx.c
> @@ -2166,6 +2166,19 @@ int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs,
>              if ( v->fpu_dirtied )
>                  nvcpu->nv_vmexit_pending = 1;
>          }
> +        else if ( vector == TRAP_gp_fault )
> +        {
> +            struct cpu_user_regs *ur = guest_cpu_user_regs();
> +            struct hvm_domain *hd = &v->domain->arch.hvm_domain;
> +
> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x1000000 /* LOG_VGP_UNKNOWN */)
> +                gdprintk(XENLOG_ERR, "Unexpected gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx\n",
> +                         (unsigned long)ur->eip,
> +                         (unsigned long)ur->eax, (unsigned long)ur->ebx,
> +                         (unsigned long)ur->ecx, (unsigned long)ur->edx,
> +                         (unsigned long)ur->esi, (unsigned long)ur->edi);
> +                nvcpu->nv_vmexit_pending = 1;
> +        }
>          else if ( (intr_info & valid_mask) == valid_mask )
>          {
>              exec_bitmap =__get_vvmcs(nvcpu->nv_vvmcx, EXCEPTION_BITMAP);
> diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h
> index e2f60a6..32489f0 100644
> --- a/xen/include/public/trace.h
> +++ b/xen/include/public/trace.h
> @@ -223,6 +223,7 @@
>  #define TRC_HVM_NPF             (TRC_HVM_HANDLER + 0x21)
>  #define TRC_HVM_REALMODE_EMULATE (TRC_HVM_HANDLER + 0x22)
>  #define TRC_HVM_TRAP             (TRC_HVM_HANDLER + 0x23)
> +#define TRC_HVM_TRAP64           (TRC_HVM_HANDLER + TRC_64_FLAG + 0x23)
>  #define TRC_HVM_TRAP_DEBUG       (TRC_HVM_HANDLER + 0x24)
>  #define TRC_HVM_VLAPIC           (TRC_HVM_HANDLER + 0x25)
>  
> -- 
> 1.8.4
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 00/10] Xen VMware tools support
  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
  0 siblings, 1 reply; 54+ messages in thread
From: Don Slutz @ 2013-12-19  0:46 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, xen-devel, Jan Beulich,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/17/13 14:03, Konrad Rzeszutek Wilk wrote:
> On Thu, Dec 12, 2013 at 02:15:08PM -0500, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> See
>>
>> http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458
> Can you say how this benefits Xen to detect this and take
> advantage of it? Or is this Xen emulating VMWare so to a guest
> it looks like its running under VMWare?
This is Xen emulating part of VMWare.  Some parts of guests will think 
it is running on VMware.
    -Don Slutz
> Thank you.
>> for info on detecting VMware.
>>
>> Linux does not follow this exactly.  It checks for CPUID 1st.  If
>> that fails, it checks for SMBIOS containing "VMware" (not VMware- or
>> VMW).
>>
>> So this patch set provides:
>>
>>          SMBIOS -- Add string VMware-
>>          CPUID -- Add VMware's CPUID (Note: currently HyperV (viridian support) breaks this check.)
>>          Add the magic VMware port
>>              Allow VMware tools poweroff and reboot
>>              Enable access to VMware's guest info
>>              Provide the VMware tools build number
>>
>> Don Slutz (10):
>>    smbios: Add "plus VMware-Tools" to HVM_XS_SYSTEM_PRODUCT_NAME.
>>    Add VMware HVM params
>>    Add cpuid_vmware_leaves
>>    tools: Add support for new HVM params
>>    vmport: Add VMware provided include files.
>>    Add vmport structs
>>    Add new vmport code.
>>    connect vmport up
>>    libxl: Add VTPOWER, VTREBOOT and VTPING
>>    Add VMware guest info access
>>
>>   tools/firmware/hvmloader/smbios.c        |   2 +-
>>   tools/libxc/xc_domain.c                  | 112 +++++
>>   tools/libxc/xc_domain_restore.c          |  27 ++
>>   tools/libxc/xc_domain_save.c             |  24 ++
>>   tools/libxc/xenctrl.h                    |  24 ++
>>   tools/libxc/xg_save_restore.h            |   2 +
>>   tools/libxl/libxl.c                      |  12 +
>>   tools/libxl/libxl_create.c               |   4 +-
>>   tools/libxl/libxl_dom.c                  |   5 +
>>   tools/libxl/libxl_types.idl              |   5 +
>>   tools/libxl/xl_cmdimpl.c                 |  10 +
>>   tools/libxl/xl_cmdtable.c                |   2 +-
>>   tools/libxl/xl_sxp.c                     |   4 +
>>   xen/arch/x86/domctl.c                    |  34 ++
>>   xen/arch/x86/hvm/Makefile                |   1 +
>>   xen/arch/x86/hvm/hvm.c                   | 209 ++++++++-
>>   xen/arch/x86/hvm/io.c                    |   4 +
>>   xen/arch/x86/hvm/svm/svm.c               | 104 +++++
>>   xen/arch/x86/hvm/svm/vmcb.c              |   1 +
>>   xen/arch/x86/hvm/vmport/Makefile         |   1 +
>>   xen/arch/x86/hvm/vmport/backdoor_def.h   | 167 +++++++
>>   xen/arch/x86/hvm/vmport/guest_msg_def.h  |  87 ++++
>>   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/arch/x86/hvm/vmx/vmcs.c              |   1 +
>>   xen/arch/x86/hvm/vmx/vmx.c               | 125 ++++++
>>   xen/arch/x86/hvm/vmx/vvmx.c              |  13 +
>>   xen/arch/x86/traps.c                     |  58 ++-
>>   xen/include/asm-x86/hvm/domain.h         |   4 +
>>   xen/include/asm-x86/hvm/hvm.h            |   3 +
>>   xen/include/asm-x86/hvm/trace.h          |   3 +
>>   xen/include/asm-x86/hvm/vmport.h         |  77 ++++
>>   xen/include/asm-x86/processor.h          |   2 +
>>   xen/include/public/domctl.h              |   3 +
>>   xen/include/public/hvm/hvm_op.h          |  18 +
>>   xen/include/public/hvm/params.h          |  11 +-
>>   xen/include/public/trace.h               |   1 +
>>   38 files changed, 1926 insertions(+), 6 deletions(-)
>>   create mode 100644 xen/arch/x86/hvm/vmport/Makefile
>>   create mode 100644 xen/arch/x86/hvm/vmport/backdoor_def.h
>>   create mode 100644 xen/arch/x86/hvm/vmport/guest_msg_def.h
>>   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
>>   create mode 100644 xen/include/asm-x86/hvm/vmport.h
>>
>> -- 
>> 1.8.4
>>
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xen.org
>> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 02/10] Add VMware HVM params
  2013-12-17 20:02   ` Konrad Rzeszutek Wilk
@ 2013-12-19  0:47     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  0:47 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, xen-devel, Jan Beulich,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/17/13 15:02, Konrad Rzeszutek Wilk wrote:
> On Thu, Dec 12, 2013 at 02:15:10PM -0500, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> Signed-off-by: Don Slutz <dslutz@verizon.com>
>> ---
>>   xen/include/public/hvm/params.h | 11 ++++++++++-
>>   1 file changed, 10 insertions(+), 1 deletion(-)
>>
>> diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
>> index 517a184..c571a1e 100644
>> --- a/xen/include/public/hvm/params.h
>> +++ b/xen/include/public/hvm/params.h
>> @@ -145,6 +145,15 @@
>>   /* SHUTDOWN_* action in case of a triple fault */
>>   #define HVM_PARAM_TRIPLE_FAULT_REASON 31
>>   
>> -#define HVM_NR_PARAMS          32
>> +/* Params for VMware */
>> +#define HVM_PARAM_VMWARE_HW                 32
>> +#define HVM_PARAM_VMPORT_LOGMASK            33
>> +#define HVM_PARAM_VMPORT_STATUS             34
>> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_TIME  35
>> +#define HVM_PARAM_VMPORT_BUILD_NUMBER_VALUE 36
>> +#define HVM_PARAM_VMPORT_RESET_TIME         37
> Could these values be passed via XenBus?
Could be.  I just went with what I knew at the time.
    -Don Slutz
>> +
>> +#define HVM_NR_PARAMS          38
>> +
>>   
>>   #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
>> -- 
>> 1.8.4
>>
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xen.org
>> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 03/10] Add cpuid_vmware_leaves
  2013-12-16  8:13           ` Jan Beulich
@ 2013-12-19  0:51             ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  0:51 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Keir Fraser, Ian Campbell, StefanoStabellini, Jun Nakajima,
	Andrew Cooper, Ian Jackson, Don Slutz, Eddie Dong,
	Suravee Suthikulpanit, xen-devel, Boris Ostrovsky

On 12/16/13 03:13, Jan Beulich wrote:
>>>> On 13.12.13 at 19:55, Don Slutz <dslutz@verizon.com> wrote:
>> On 12/13/13 08:38, Andrew Cooper wrote:
>>> On 13/12/2013 10:55, Jan Beulich wrote:
>>>>>>> On 12.12.13 at 23:27, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>>>>> On 12/12/2013 19:15, Don Slutz wrote:
>>>>>> +    if ( is_viridian_domain(d) )
>>>>>> +        base += 0x100;
>>>>>> +    if ( is_vmware_domain(d) )
>>>>>> +        base += 0x100;
>>>>>> +
>> As a related question: Should I reply to each e-mail, or is the reply at the
>> thread place (like here) ok?
> Generally per-mail answers are preferred, as that makes the context
> more obvious. Occasionally you'll find that overall effect is better if
> you reply to multiple levels of contexts at once.
>
> But please, for legibility's sake, include blank lines between quoted
> text and your responses.
>

Thanks for the info.  I will try and remember to do this.

>>>> And it seems highly questionable to me whether having both at the
>>>> same time makes much sense.
>>>>
>>>> Plus the new function doesn't belong in xen/arch/x86/traps.c ...
>> I read this as "Change to some sort of data structure to get the answer
>> instead of a function".  This is because I do not see how to return the
>> correct data from a function if it is not in xen/arch/x86/traps.c (like
>> cpuid_hypervisor_leaves is) or called from there, which I would see as more
>> confusing.
> Just like cpuid_viridian_leaves() lives in xen/arch/x86/hvm/viridian.c,
> your new function should live in e.g. xen/arch/x86/hvm/vmware.c.
>
> Jan

Ah, I now understand.  Will move this function there.
    -Don Slutz

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 05/10] vmport: Add VMware provided include files.
  2013-12-17 20:22   ` Konrad Rzeszutek Wilk
@ 2013-12-19  0:54     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  0:54 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, xen-devel, Jan Beulich,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/17/13 15:22, Konrad Rzeszutek Wilk wrote:
> On Thu, Dec 12, 2013 at 02:15:13PM -0500, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> These 2 files: backdoor_def.h and guest_msg_def.h come from:
>>
>> http://packages.vmware.com/tools/esx/3.5latest/rhel4/SRPMS/index.html
>>   open-vm-tools-kmod-7.4.8-396269.423167.src.rpm
>>    open-vm-tools-kmod-7.4.8.tar.gz
>>     vmhgfs/backdoor_def.h
>>     vmhgfs/guest_msg_def.h
>>
>> and are unchanged.
>>
>> Signed-off-by: Don Slutz <dslutz@verizon.com>
>> ---
>>   xen/arch/x86/hvm/vmport/backdoor_def.h  | 167 ++++++++++++++++++++++++++++++++
>>   xen/arch/x86/hvm/vmport/guest_msg_def.h |  87 +++++++++++++++++
>>   2 files changed, 254 insertions(+)
>>   create mode 100644 xen/arch/x86/hvm/vmport/backdoor_def.h
>>   create mode 100644 xen/arch/x86/hvm/vmport/guest_msg_def.h
>>
>> diff --git a/xen/arch/x86/hvm/vmport/backdoor_def.h b/xen/arch/x86/hvm/vmport/backdoor_def.h
>> new file mode 100644
>> index 0000000..e76795f
>> --- /dev/null
>> +++ b/xen/arch/x86/hvm/vmport/backdoor_def.h
>> @@ -0,0 +1,167 @@
>> +/* **********************************************************
>> + * Copyright 1998 VMware, Inc.  All rights reserved.
>> + * **********************************************************
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the
>> + * Free Software Foundation version 2 and no later version.
>> + *
>> + * This program is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
>> + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>> + * for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, write to the Free Software Foundation, Inc.,
>> + * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
> Please don't include the address. It should be:
>
>   You should have received a copy of the GNU General Public License
>   along with this program.  If not, see <http://www.gnu.org/licenses/>.

I agree in general.  However this is the unchanged file from VMware.

[snip]

>> diff --git a/xen/arch/x86/hvm/vmport/guest_msg_def.h b/xen/arch/x86/hvm/vmport/guest_msg_def.h
>> new file mode 100644
>> index 0000000..44ae0fa
>> --- /dev/null
>> +++ b/xen/arch/x86/hvm/vmport/guest_msg_def.h
>> @@ -0,0 +1,87 @@
>> +/* **********************************************************
>> + * Copyright 1998 VMware, Inc.  All rights reserved.
>> + * **********************************************************
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the
>> + * Free Software Foundation version 2 and no later version.
>> + *
>> + * This program is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
>> + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>> + * for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, write to the Free Software Foundation, Inc.,
>> + * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
> Ditto:
>
>   You should have received a copy of the GNU General Public License
>      along with this program.  If not, see <http://www.gnu.org/licenses/>.

Same as above.
    -Don Slutz

[snip]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 06/10] Add vmport structs
  2013-12-12 23:10   ` Andrew Cooper
@ 2013-12-19  1:26     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  1:26 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, xen-devel, Jan Beulich,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/12/13 18:10, Andrew Cooper wrote:
> On 12/12/2013 19:15, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> Signed-off-by: Don Slutz <dslutz@verizon.com>
>> ---
>>   xen/arch/x86/hvm/hvm.c           | 59 +++++++++++++++++++++++++++++-
>>   xen/include/asm-x86/hvm/domain.h |  4 +++
>>   xen/include/asm-x86/hvm/vmport.h | 77 ++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 139 insertions(+), 1 deletion(-)
>>   create mode 100644 xen/include/asm-x86/hvm/vmport.h
>>
>> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
>> index 38641c4..fa5d382 100644
>> --- a/xen/arch/x86/hvm/hvm.c
>> +++ b/xen/arch/x86/hvm/hvm.c
>> @@ -57,6 +57,7 @@
>>   #include <asm/hvm/cacheattr.h>
>>   #include <asm/hvm/trace.h>
>>   #include <asm/hvm/nestedhvm.h>
>> +#include <asm/hvm/vmport.h>
>>   #include <asm/mtrr.h>
>>   #include <asm/apic.h>
>>   #include <public/sched.h>
>> @@ -536,6 +537,7 @@ static int handle_pvh_io(
>>   int hvm_domain_initialise(struct domain *d)
>>   {
>>       int rc;
>> +    long vmport_mem = 0;
>>   
>>       if ( !hvm_enabled )
>>       {
>> @@ -562,6 +564,7 @@ int hvm_domain_initialise(struct domain *d)
>>   
>>       spin_lock_init(&d->arch.hvm_domain.irq_lock);
>>       spin_lock_init(&d->arch.hvm_domain.uc_lock);
>> +    spin_lock_init(&d->arch.hvm_domain.vmport_lock);
>>   
>>       INIT_LIST_HEAD(&d->arch.hvm_domain.msixtbl_list);
>>       spin_lock_init(&d->arch.hvm_domain.msixtbl_list_lock);
>> @@ -574,11 +577,47 @@ int hvm_domain_initialise(struct domain *d)
>>   
>>       d->arch.hvm_domain.params = xzalloc_array(uint64_t, HVM_NR_PARAMS);
>>       d->arch.hvm_domain.io_handler = xmalloc(struct hvm_io_handler);
>> +    d->arch.hvm_domain.vmport_data = xzalloc(struct vmport_state);
>>       rc = -ENOMEM;
>> -    if ( !d->arch.hvm_domain.params || !d->arch.hvm_domain.io_handler )
>> +    if ( !d->arch.hvm_domain.params || !d->arch.hvm_domain.io_handler ||
>> +         !d->arch.hvm_domain.vmport_data )
>>           goto fail1;
>>       d->arch.hvm_domain.io_handler->num_slot = 0;
>>   
>> +    vmport_mem += sizeof(struct vmport_state);
>> +    d->arch.hvm_domain.vmport_data->open_cookie = ('C' << 8) + 'S';
> This is one place where multicharacter constants would really help.
> However, I suspect a change to add -Wno-multichar to the build might not
> go down too well.

Maybe.  This particular field is a starting value.  It gets changed on 
every VMware rpc channel open:

hvm/vmport/vmport.c  vmport_new_chan       224 c->cookie = 
vs->open_cookie++;

so using 0, 42, etc would be just as good.  These characters made it a 
little easier to see that the right things were happening during unit 
testing.


>
>> +    d->arch.hvm_domain.vmport_data->used_guestinfo = 10;
>> +
>> +    for (rc = 0; rc < d->arch.hvm_domain.vmport_data->used_guestinfo; rc++) {
> Xen style - space inside brackets and braces lined up.

Well, I need to fix up a lot to match Xen style.  Not sure if I can get 
emacs to do it all.  Do you have a astyle options file that matches 
CODING_STYLE?

If not it looks like I will work on one.


>
>> +        d->arch.hvm_domain.vmport_data->guestinfo[rc] = xzalloc(vmport_guestinfo_t);
> xzalloc_array() of used_guestinfo entries, and needs to be checked for
> an allocation failure.
>

Yes. will add.

>> +        vmport_mem += sizeof(vmport_guestinfo_t);
>> +    }
>> +    d->arch.hvm_domain.vmport_data->guestinfo[0]->key_len = 2;
>> +    memcpy(d->arch.hvm_domain.vmport_data->guestinfo[0]->key_data, "ip", 2);
>> +
>> +    gdprintk(XENLOG_DEBUG, "vmport_mem=%ld bytes (%ld KiB, %ld MiB)\n",
>> +             vmport_mem,
>> +             (vmport_mem + (1 << 10) - 1) >> 10,
>> +             (vmport_mem + (1 << 20) - 1) >> 20);
>> +    vmport_mem += sizeof(uint64_t) * HVM_NR_PARAMS;
>> +    vmport_mem += sizeof(struct hvm_io_handler);
>> +    gdprintk(XENLOG_DEBUG, "hvm overhead=%ld bytes (%ld KiB, %ld MiB)\n",
>> +             vmport_mem,
>> +             (vmport_mem + (1 << 10) - 1) >> 10,
>> +             (vmport_mem + (1 << 20) - 1) >> 20);
>> +    gdprintk(XENLOG_DEBUG, "tot_pages=%d bytes (%d KiB, %d MiB)\n",
>> +             d->tot_pages,
>> +             (d->tot_pages + (1 << 10) - 1) >> 10,
>> +             (d->tot_pages + (1 << 20) - 1) >> 20);
>> +    gdprintk(XENLOG_DEBUG, "max_pages=%d bytes (%d KiB, %d MiB)\n",
>> +             d->max_pages,
>> +             (d->max_pages + (1 << 10) - 1) >> 10,
>> +             (d->max_pages + (1 << 20) - 1) >> 20);
> These two gdprintk()s do not appear to be related to the content of this
> patch.

You are right.  They were some temporary debug information to see if the 
calculation of the Xen overhead on it's heap per domain was giving good 
answers.  Will drop them.

>> +
>> +#if 0
>> +    vmport_flush(&d->arch.hvm_domain);
>> +#endif
> Is this stray debugging?

Nope, stray patch splitting.   Will correct in the next round.


>> +
>>       if ( is_pvh_domain(d) )
>>       {
>>           register_portio_handler(d, 0, 0x10003, handle_pvh_io);
>> @@ -617,6 +656,15 @@ int hvm_domain_initialise(struct domain *d)
>>       stdvga_deinit(d);
>>       vioapic_deinit(d);
>>    fail1:
>> +    if (d->arch.hvm_domain.vmport_data) {
>> +        struct vmport_state *vs = d->arch.hvm_domain.vmport_data;
>> +        int idx;
>> +
>> +        for (idx = 0; idx < vs->used_guestinfo; idx++) {
>> +            xfree(vs->guestinfo[idx]);
>> +        }
>> +    }
>> +    xfree(d->arch.hvm_domain.vmport_data);
>>       xfree(d->arch.hvm_domain.io_handler);
>>       xfree(d->arch.hvm_domain.params);
>>    fail0:
>> @@ -626,6 +674,15 @@ int hvm_domain_initialise(struct domain *d)
>>   
>>   void hvm_domain_relinquish_resources(struct domain *d)
>>   {
>> +    if (d->arch.hvm_domain.vmport_data) {
>> +        struct vmport_state *vs = d->arch.hvm_domain.vmport_data;
>> +        int idx;
>> +
>> +        for (idx = 0; idx < vs->used_guestinfo; idx++) {
>> +            xfree(vs->guestinfo[idx]);
>> +        }
>> +        xfree(d->arch.hvm_domain.vmport_data);
>> +    }
>>       xfree(d->arch.hvm_domain.io_handler);
>>       xfree(d->arch.hvm_domain.params);
>>   
>> diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
>> index b1e3187..0ca2778 100644
>> --- a/xen/include/asm-x86/hvm/domain.h
>> +++ b/xen/include/asm-x86/hvm/domain.h
>> @@ -62,6 +62,10 @@ struct hvm_domain {
>>       /* emulated irq to pirq */
>>       struct radix_tree_root emuirq_pirq;
>>   
>> +    /* VMware special port */
>> +    spinlock_t             vmport_lock;
>> +    struct  vmport_state  *vmport_data;
>> +
> Stray space between struct and vmport.

Will fix.


>
>>       uint64_t              *params;
>>   
>>       /* Memory ranges with pinned cache attributes. */
>> diff --git a/xen/include/asm-x86/hvm/vmport.h b/xen/include/asm-x86/hvm/vmport.h
>> new file mode 100644
>> index 0000000..180ddac
>> --- /dev/null
>> +++ b/xen/include/asm-x86/hvm/vmport.h
>> @@ -0,0 +1,77 @@
>> +/*
>> + * vmport.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 __ASM_X86_HVM_VMPORT_H__
>> +#define __ASM_X86_HVM_VMPORT_H__
>> +
>> +/* Note: VMPORT_PORT and VMPORT_MAGIC is also defined as BDOOR_PORT
>> + * and BDOOR_MAGIC in backdoor_def.h Defined here so that other
>> + * parts of XEN can use it.
>> + */
>> +
>> +#define VMPORT_PORT 0x5658
>> +#define VMPORT_MAGIC 0x564D5868
> You should include backdoor_def.h rather than having the same constant
> defined twice in the codebase.
>

Will look into getting it done.  The include of backdoor_def.h (with it 
unchanged) is not as simple.  Did not know if it was better to leave it 
unchanged, or just keep what is needed.


>> +
>> +#define VMPORT_MAX_KEY_LEN 30
>> +#define VMPORT_MAX_VAL_LEN 128
>> +#define VMPORT_MAX_NUM_KEY 128
>> +
>> +#define VMPORT_MAX_SEND_BUF ((22 + VMPORT_MAX_KEY_LEN + VMPORT_MAX_VAL_LEN + 3)/4)
>> +#define VMPORT_MAX_RECV_BUF ((2 + VMPORT_MAX_VAL_LEN + 3)/4)
>> +#define VMPORT_MAX_CHANS    4
>> +#define VMPORT_MAX_BKTS     8
>> +
>> +
>> +typedef struct vmport_guestinfo_ {
> Why the trailing underscores in the non-typedef'd name?

It does help to know this is a struct name.  It came  from one of the 
many coding styles I have used in the past.  Happy to change it any way 
that is "Xen" style.

>> +    uint8_t key_len;
>> +    uint8_t val_len;
>> +    char key_data[VMPORT_MAX_KEY_LEN];
>> +    char val_data[VMPORT_MAX_VAL_LEN];
>> +} vmport_guestinfo_t;
>> +
>> +typedef struct vmport_bucket_ {
>> +    uint16_t recv_len;
>> +    uint16_t recv_idx;
>> +    uint32_t recv_buf[VMPORT_MAX_RECV_BUF + 1];
>> +    uint8_t  recv_slot;
>> +} vmport_bucket_t;
>> +
>> +typedef struct vmport_channel_ {
>> +    unsigned long active_time;
>> +    uint32_t chan_id;
>> +    uint32_t cookie;
>> +    uint32_t proto_num;
>> +    uint16_t send_len;
>> +    uint16_t send_idx;
>> +    uint32_t send_buf[VMPORT_MAX_SEND_BUF + 1];
>> +    vmport_bucket_t recv_bkt[VMPORT_MAX_BKTS];
>> +    uint8_t recv_read;
>> +    uint8_t recv_write;
>> +} vmport_channel_t;
>> +
>> +struct vmport_state {
>> +    unsigned long ping_time;
>> +    uint32_t open_cookie;
>> +    uint32_t used_guestinfo;
>> +    vmport_channel_t chans[VMPORT_MAX_CHANS];
>> +    vmport_guestinfo_t *guestinfo[VMPORT_MAX_NUM_KEY];
>> +};
>> +
>> +int vmport_ioport(int dir, int size, unsigned long data, struct cpu_user_regs *regs);
>> +void vmport_ctrl_send(struct hvm_domain *hd, char *msg, int slot);
>> +void vmport_flush(struct hvm_domain *hd);
> These declarations need to be in the same patch as defines them.

Will do.

    -Don Slutz
> ~Andrew
>
>> +
>> +#endif /* __ASM_X86_HVM_VMPORT_H__ */

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 07/10] Add new vmport code.
  2013-12-13  0:06   ` Andrew Cooper
@ 2013-12-19  2:22     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  2:22 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, xen-devel, Jan Beulich,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/12/13 19:06, Andrew Cooper wrote:
> On 12/12/2013 19:15, Don Slutz wrote:
>> 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.
> What do you mean by this?

In VMware it looks like this file that is included by backdoor_def.h 
does a lot of defines that I have no use for.  So to be able to use 
backdoor_def.h without any changes I needed an include file with the 
name includeCheck.h;  Not sure which is the better way to go.


>
>> + */
>> 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"
> #include <asm/hvm/support.h>

Will fix. Thanks.

>
>> +
>> +#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);
> Please include the appropriate header files.

Will do (assuming you mean for get_sec).

>> +
>> +/* 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);
>> +}
> What is the point of these functions being separated out?

It was attempt to may the code more readable.  Just noticed that these 
are in camelCase (getHighBits vs get_high_bits).  Which way should I go?

> setHighBits only seems to be used with regs->ecx (which is actually a
> 64bit value not a 32bit value) to set a status value.
> Why not set_status(cpu_user_regs *, uint16_t val) ?


Will change to this.


>
>> +
>> +static inline long getLogMask(struct hvm_domain *hd)
>> +{
>> +    return hd->params[HVM_PARAM_VMPORT_LOGMASK];
> A param is unsigned long, not long...

Will fix.


>> +}
>> +
>> +static inline char *getStatus(struct hvm_domain *hd)
>> +{
>> +    return (char*)&hd->params[HVM_PARAM_VMPORT_STATUS];
> ... And most certainly not a string.

Current planning on dropping all code that uses this.

>> +}
>> +
>> +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);
> the correct format for any sizeof is %zu or %zx depending on decimal/hex.

Will fix.

>> +}
>> +
>> +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;
> This (and every use of getStatus() below) most certainly needs to
> guarentee that slot is strictly in the bound 0 to 7, and writing the
> integer 200 to a char is undefined I believe.

You are right.  Current planning on dropping all code that uses getStatus.



>
>> +        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 ";
> I cant remember offhand whether Xen is compiled with or without
> read-only strings,

Not sure why it matters.  What ret_msg points to is not changed. ret_msg 
it's self is changed to point to different strings.

0 hvm/vmport/vmport.c vmport_process_send_payload 274 char * ret_msg = "1 ";
1 hvm/vmport/vmport.c vmport_process_send_payload 311 ret_msg = ret_buffer;
2 hvm/vmport/vmport.c vmport_process_send_payload 316 ret_msg = "0 No 
value found";
3 hvm/vmport/vmport.c vmport_process_send_payload 319 ret_msg = "0 Key 
is too long";
4 hvm/vmport/vmport.c vmport_process_send_payload 364 ret_msg = "0 Too 
many keys";
5 hvm/vmport/vmport.c vmport_process_send_payload 373 ret_msg = "0 Value 
too long";
6 hvm/vmport/vmport.c vmport_process_send_payload 376 ret_msg = "0 Key 
is too long";
7 hvm/vmport/vmport.c vmport_process_send_payload 384 ret_msg = "0 Two 
and exactly two arguments expected";
8 hvm/vmport/vmport.c vmport_process_send_payload 388 vmport_send(hd, c, 
ret_msg, 5);

And it looks like I should change:

void vmport_send(struct hvm_domain *hd, vmport_channel_t *c, char *msg, 
int slot)

into:

void vmport_send(struct hvm_domain *hd, vmport_channel_t *c, const char 
*msg, int slot)


>> +            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;
> Again this hard coded constant.

Will be looking into how to fix correctly.

>
>> +        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:
>> + */
> Frankly, this while file is quite nasty.  There is a huge amount of
> pointer arithmetic and array indexing with guest data, which doesn't
> appear at a glance to have sufficient validation.

Will look into make it clearer.

> The vast majority of the ints should be unsigned as they are used as
> indices.  All the times should probably be s_time_t's

Will fix.

> The idiom
>
> if ( getLogMask(hd) & LOG_$SOMETHING )
>      gdprintk(XENLOG_$SOMETHING, ...);
>
> Can probably be moved into a single macro, which will simply the reading
> of the code quite a bit.

Will do.

>
> Is there a spec for what this code is trying to accomplish?  Some of the
> comments suggest that it has been reverse engineered?

I am not aware of such a spec.  I will attempt to find one.  It looks 
like add what I know as a documnet file would be helpful. Some of it has 
been "reverse" engineered in that it comes from decoding the code 
provided by:

http://packages.vmware.com/tools/esx/3.5latest/rhel4/SRPMS/index.html
  open-vm-tools-kmod-7.4.8-396269.423167.src.rpm

And also seeing the debug output of doing some actions using VMware tools.



>
> I think I have counted 4 coding styles in there.  Given the Xen block on
> the bottom, can it settle on a single style.

Sure, I will working on getting this to 1 style.

>
>> 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>
> What is the point of this header file?

At some point in the past there was multiple users.  I see that there is 
only one now, and so will be removed.

>
>> +
>> +#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
> There are already traps for io ports, which I believe are part of the
> generic vmexit traps.
>

Looks like the name is not good.  And normal ports to not use or change 
other cpu registers.  These last 2 are used:

     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);

I.E. they are VMware backdoor port only traces.  As such, it would be 
good to drop the fixed and duplicated data, and add the missing data.  
I.E. Change them to:


     if (dir == IOREQ_READ)
         HVMTRACE_ND(IOPORT_READ, 0, 1/*cycles*/, 6,
                     regs->eax, regs->ebx, regs->ecx,
                     regs->edx, regs->esi, regs->edi);
     else
         HVMTRACE_ND(IOPORT_WRITE, 0, 1/*cycles*/, 6,
                     regs->eax, regs->ebx, regs->ecx,
                     regs->edx, regs->esi, regs->edi);

With IOPORT_READ changed also to something like VMWARE_PORT_READ.


   -Don Slutz

> ~Andrew
>
>>   
>>   
>>   #define TRC_PAR_LONG(par) ((par)&0xFFFFFFFF),((par)>>32)

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 07/10] Add new vmport code.
  2013-12-13 10:59   ` Jan Beulich
@ 2013-12-19  2:25     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  2:25 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, Suravee Suthikulpanit,
	xen-devel, Boris Ostrovsky

On 12/13/13 05:59, Jan Beulich wrote:
>>>> On 12.12.13 at 20:15, Don Slutz <dslutz@verizon.com> wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> enable vmport_flush call.
>>
>> Signed-off-by: Don Slutz <dslutz@verizon.com>
> Again - please be more verbose.
>
> And clean up the coding style before submitting.
>
> Jan
>
Will do.
    -Don Slutz

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 07/10] Add new vmport code.
  2013-12-17 20:36   ` Konrad Rzeszutek Wilk
@ 2013-12-19  2:29     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  2:29 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Don Slutz, xen-devel, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/17/13 15:36, Konrad Rzeszutek Wilk wrote:
> On Thu, Dec 12, 2013 at 02:15:15PM -0500, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> enable vmport_flush call.
> I think this patch needs a bigger description of what it does!

I see that you agree with Jan.    Looks like the description from an 
intermediate patch during coding and development ended up here. Will 
spend a lot of time writing some thing that will help understand this code.


[snip]

    -Don Slutz

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 08/10] connect vmport up
  2013-12-13  0:51   ` Andrew Cooper
@ 2013-12-19  2:53     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  2:53 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Ian Jackson, Eddie Dong, Don Slutz, xen-devel, Jan Beulich,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/12/13 19:51, Andrew Cooper wrote:
> On 12/12/2013 19:15, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> Signed-off-by: Don Slutz <dslutz@verizon.com>
>> ---
>>   xen/arch/x86/hvm/io.c       |   4 ++
>>   xen/arch/x86/hvm/svm/svm.c  | 104 ++++++++++++++++++++++++++++++++++++
>>   xen/arch/x86/hvm/svm/vmcb.c |   1 +
>>   xen/arch/x86/hvm/vmx/vmcs.c |   1 +
>>   xen/arch/x86/hvm/vmx/vmx.c  | 125 ++++++++++++++++++++++++++++++++++++++++++++
>>   xen/arch/x86/hvm/vmx/vvmx.c |  13 +++++
>>   xen/include/public/trace.h  |   1 +
>>   7 files changed, 249 insertions(+)
>>
>> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
>> index bf6309d..4bc4716 100644
>> --- a/xen/arch/x86/hvm/io.c
>> +++ b/xen/arch/x86/hvm/io.c
>> @@ -42,6 +42,7 @@
>>   #include <asm/hvm/vlapic.h>
>>   #include <asm/hvm/trace.h>
>>   #include <asm/hvm/emulate.h>
>> +#include <asm/hvm/vmport.h>
>>   #include <public/sched.h>
>>   #include <xen/iocap.h>
>>   #include <public/hvm/ioreq.h>
>> @@ -236,6 +237,9 @@ int handle_pio(uint16_t port, unsigned int size, int dir)
>>       if ( dir == IOREQ_WRITE )
>>           data = guest_cpu_user_regs()->eax;
>>   
>> +    if ( port == VMPORT_PORT )
>> +        return vmport_ioport(dir, size, data, guest_cpu_user_regs());
>> +
> Use register_portio_handler(), which is the already-existing
> infrastructure for intercepting ports.

Will try it out.

>
>>       rc = hvmemul_do_pio(port, &reps, size, 0, dir, 0, &data);
>>   
>>       switch ( rc )
>> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
>> index 406d394..80cf2bf 100644
>> --- a/xen/arch/x86/hvm/svm/svm.c
>> +++ b/xen/arch/x86/hvm/svm/svm.c
>> @@ -56,6 +56,7 @@
>>   #include <asm/hvm/svm/nestedsvm.h>
>>   #include <asm/hvm/nestedhvm.h>
>>   #include <asm/x86_emulate.h>
>> +#include <asm/hvm/vmport.h>
>>   #include <public/sched.h>
>>   #include <asm/hvm/vpt.h>
>>   #include <asm/hvm/trace.h>
>> @@ -1904,6 +1905,105 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
>>       return;
>>   }
>>   
>> +static void svm_vmexit_gp_intercept(struct cpu_user_regs *regs, struct vcpu *v)
>> +{
>> +    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
>> +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
>> +    unsigned long inst_len, bytes_len;
>> +    int frc;
>> +    unsigned char bytes[15];
>> +
>> +    regs->error_code = vmcb->exitinfo1;
>> +    if ( !cpu_has_svm_nrips || (vmcb->nextrip <= vmcb->rip) )
>> +        inst_len = 0;
>> +    else
>> +        inst_len = vmcb->nextrip - vmcb->rip;
>> +    bytes_len = 2 /* inst_len < 15 ? inst_len > 1 ? inst_len : 2 : 15 */;
>> +    frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
>> +                                            bytes_len,
>> +                                            PFEC_page_present);
>> +
>> +    if ( hvm_long_mode_enabled(v) )
>> +        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
>> +                         regs->error_code,
>> +                         TRC_PAR_LONG(vmcb->exitinfo2) );
>> +    else
>> +        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
>> +                    regs->error_code, vmcb->exitinfo2 );
>> +
>> +    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* LOG_GP_FAIL_RD_INST */)
>> +        printk("[HVM:%d.%d] <%s> "
>> +               "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%ld,%d) nip(%d)=%lx(%d,%d(0x%x) 0x%x 0x%x)"
>> +               "\n",
>> +               current->domain->domain_id, current->vcpu_id, __func__,
>> +               (unsigned long)vmcb->exitinfo2,
>> +               (unsigned long)regs->error_code,
>> +               (unsigned long)regs->eip, (unsigned int)bytes[0],
>> +               (unsigned int)bytes[1], bytes_len, inst_len, frc,
>> +               cpu_has_svm_nrips, (unsigned long)vmcb->nextrip,
>> +               cpu_has_svm_decode, vmcb->guest_ins_len & 0xf, vmcb->guest_ins_len,
>> +               vmcb->guest_ins[0], vmcb->guest_ins[1]);
>> +
>> +    if ( !frc && bytes[0] == 0xed && (regs->edx & 0xffff) == VMPORT_PORT &&
>> +         vmcb->exitinfo2 == 0 && regs->error_code == 0 )
>> +    {
>> +        /*  in (%dx),%eax */
>> +        uint32_t magic = regs->eax;
>> +
>> +        if ( magic == VMPORT_MAGIC ) {
>> +            __update_guest_eip(regs, 1);
>> +            vmport_ioport(IOREQ_READ, 4, 0, regs);
> This appears to be intercepting an L2 guest doing vmport magic IO to the
> L1 hypervisor.
>
> Is this sane/sensible/wise?

If I am reading this right; my answer is yes.  This is how VMware 
defined it's backdoor port.  What might be worse is that many "commands" 
work in ring 3.

L1 hypervisor is Xen.
L2 guest is both dom0 and domU.

I.E. you are not talking about nested (xen on xen) case.

>> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* LOG_GP_VMWARE_AFTER */)
>> +                printk("[HVM:%d.%d] <%s> "
>> +                       "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
>> +                       "\n",
>> +                       current->domain->domain_id, current->vcpu_id, __func__,
>> +                       (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);
>> +            return;
>> +        } else {
>> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* LOG_GP_NOT_VMWARE */)
>> +                printk("[HVM:%d.%d] <%s> "
>> +                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
>> +                       "\n",
>> +                       current->domain->domain_id, current->vcpu_id, __func__,
>> +                       (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);
>> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
>> +        }
>> +    } else if (!frc && regs->error_code == 0
>> +               && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx == 0x10000)
>> +    {
>> +        /* "rdpmc 0x10000" */
>> +        /* Not a very good emulation!  But just not faulting is good enough
>> +         * to get NetApp booting. */
>> +        regs->edx = regs->eax = 0;
> This doesn't look like it is logically part of "connecting vmport up"

You are right.  This code should not be part of this patch set. Will 
drop it.


> ~Andrew
>

[snip]

>> diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h
>> index e2f60a6..32489f0 100644
>> --- a/xen/include/public/trace.h
>> +++ b/xen/include/public/trace.h
>> @@ -223,6 +223,7 @@
>>   #define TRC_HVM_NPF             (TRC_HVM_HANDLER + 0x21)
>>   #define TRC_HVM_REALMODE_EMULATE (TRC_HVM_HANDLER + 0x22)
>>   #define TRC_HVM_TRAP             (TRC_HVM_HANDLER + 0x23)
>> +#define TRC_HVM_TRAP64           (TRC_HVM_HANDLER + TRC_64_FLAG + 0x23)
> Haven't you already defined this in a previous patch?

Nope, just a related one.  Will factor both out into their own patch.

    -Don Slutz

>>   #define TRC_HVM_TRAP_DEBUG       (TRC_HVM_HANDLER + 0x24)
>>   #define TRC_HVM_VLAPIC           (TRC_HVM_HANDLER + 0x25)
>>   

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 08/10] connect vmport up
  2013-12-13 15:46   ` Boris Ostrovsky
@ 2013-12-19  3:45     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  3:45 UTC (permalink / raw)
  To: Boris Ostrovsky
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Jun Nakajima,
	Eddie Dong, Ian Jackson, Don Slutz, xen-devel, Jan Beulich,
	Suravee Suthikulpanit

On 12/13/13 10:46, Boris Ostrovsky wrote:
> On 12/12/2013 02:15 PM, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
>>
>> Signed-off-by: Don Slutz <dslutz@verizon.com>
>> ---
>>   xen/arch/x86/hvm/io.c       |   4 ++
>>   xen/arch/x86/hvm/svm/svm.c  | 104 ++++++++++++++++++++++++++++++++++++
>>   xen/arch/x86/hvm/svm/vmcb.c |   1 +
>>   xen/arch/x86/hvm/vmx/vmcs.c |   1 +
>>   xen/arch/x86/hvm/vmx/vmx.c  | 125 
>> ++++++++++++++++++++++++++++++++++++++++++++
>>   xen/arch/x86/hvm/vmx/vvmx.c |  13 +++++
>>   xen/include/public/trace.h  |   1 +
>>   7 files changed, 249 insertions(+)
>>
>> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
>> index bf6309d..4bc4716 100644
>> --- a/xen/arch/x86/hvm/io.c
>> +++ b/xen/arch/x86/hvm/io.c
>> @@ -42,6 +42,7 @@
>>   #include <asm/hvm/vlapic.h>
>>   #include <asm/hvm/trace.h>
>>   #include <asm/hvm/emulate.h>
>> +#include <asm/hvm/vmport.h>
>>   #include <public/sched.h>
>>   #include <xen/iocap.h>
>>   #include <public/hvm/ioreq.h>
>> @@ -236,6 +237,9 @@ int handle_pio(uint16_t port, unsigned int size, 
>> int dir)
>>       if ( dir == IOREQ_WRITE )
>>           data = guest_cpu_user_regs()->eax;
>>   +    if ( port == VMPORT_PORT )
>> +        return vmport_ioport(dir, size, data, guest_cpu_user_regs());
>> +
>>       rc = hvmemul_do_pio(port, &reps, size, 0, dir, 0, &data);
>>         switch ( rc )
>> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
>> index 406d394..80cf2bf 100644
>> --- a/xen/arch/x86/hvm/svm/svm.c
>> +++ b/xen/arch/x86/hvm/svm/svm.c
>> @@ -56,6 +56,7 @@
>>   #include <asm/hvm/svm/nestedsvm.h>
>>   #include <asm/hvm/nestedhvm.h>
>>   #include <asm/x86_emulate.h>
>> +#include <asm/hvm/vmport.h>
>>   #include <public/sched.h>
>>   #include <asm/hvm/vpt.h>
>>   #include <asm/hvm/trace.h>
>> @@ -1904,6 +1905,105 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
>>       return;
>>   }
>>   +static void svm_vmexit_gp_intercept(struct cpu_user_regs *regs, 
>> struct vcpu *v)
>> +{
>> +    struct hvm_domain *hd = &v->domain->arch.hvm_domain;
>> +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
>> +    unsigned long inst_len, bytes_len;
>> +    int frc;
>> +    unsigned char bytes[15];
>> +
>> +    regs->error_code = vmcb->exitinfo1;
>> +    if ( !cpu_has_svm_nrips || (vmcb->nextrip <= vmcb->rip) )
>> +        inst_len = 0;
>> +    else
>> +        inst_len = vmcb->nextrip - vmcb->rip;
>
> You can use svm_nextrip_insn_length(), with some adjustments to NDEBUG 
> case there.

Will check it out.

>
>> +    bytes_len = 2 /* inst_len < 15 ? inst_len > 1 ? inst_len : 2 : 
>> 15 */;
>
> Saying this in words would be preferable --- I am not sure I 
> understand why it's 2. Do you only expect specific instructions here? 
> Or are you only interested in the first two bytes of the opcode?
>

I only expect specific instructions here that are all 1 or 2 bytes. It 
turns out the 2 byte ones should have been a later patch.   Will fix.

The 1 byte instruction "0xed" is either "in %ax,%dx" or "in %eax,%dx" 
depending on mode guest is in.  I just found a web page that states that 
"out %eax,%dx" should also work.  Need to test out that VMware does 
support this.

>> +    frc = hvm_fetch_from_guest_virt_nofault(bytes, regs->eip,
>> +                                            bytes_len,
>> +                                            PFEC_page_present);
>> +
>> +    if ( hvm_long_mode_enabled(v) )
>> +        HVMTRACE_LONG_4D(TRAP, TRAP_gp_fault, inst_len,
>> +                         regs->error_code,
>> +                         TRC_PAR_LONG(vmcb->exitinfo2) );
>> +    else
>> +        HVMTRACE_4D(TRAP, TRAP_gp_fault, inst_len,
>> +                    regs->error_code, vmcb->exitinfo2 );
>> +
>> +    if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x400000 /* 
>> LOG_GP_FAIL_RD_INST */)
>> +        printk("[HVM:%d.%d] <%s> "
>> +               "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%ld,%d) 
>> nip(%d)=%lx(%d,%d(0x%x) 0x%x 0x%x)"
>> +               "\n",
>> +               current->domain->domain_id, current->vcpu_id, __func__,
>> +               (unsigned long)vmcb->exitinfo2,
>> +               (unsigned long)regs->error_code,
>> +               (unsigned long)regs->eip, (unsigned int)bytes[0],
>> +               (unsigned int)bytes[1], bytes_len, inst_len, frc,
>> +               cpu_has_svm_nrips, (unsigned long)vmcb->nextrip,
>> +               cpu_has_svm_decode, vmcb->guest_ins_len & 0xf, 
>> vmcb->guest_ins_len,
>> +               vmcb->guest_ins[0], vmcb->guest_ins[1]);
>> +
>> +    if ( !frc && bytes[0] == 0xed && (regs->edx & 0xffff) == 
>> VMPORT_PORT &&
>> +         vmcb->exitinfo2 == 0 && regs->error_code == 0 )
>> +    {
>> +        /*  in (%dx),%eax */
>> +        uint32_t magic = regs->eax;
>> +
>> +        if ( magic == VMPORT_MAGIC ) {
>> +            __update_guest_eip(regs, 1);
>> +            vmport_ioport(IOREQ_READ, 4, 0, regs);
>> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x800000 /* 
>> LOG_GP_VMWARE_AFTER */)
>> +                printk("[HVM:%d.%d] <%s> "
>> +                       "gp: VMware ip=%lx ax=%lx bx=%lx cx=%lx 
>> dx=%lx si=%lx di=%lx"
>> +                       "\n",
>> +                       current->domain->domain_id, current->vcpu_id, 
>> __func__,
>> +                       (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);
>> +            return;
>> +        } else {
>> +            if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x200000 /* 
>> LOG_GP_NOT_VMWARE */)
>> +                printk("[HVM:%d.%d] <%s> "
>> +                       "gp: ip=%lx ax=%lx bx=%lx cx=%lx dx=%lx 
>> si=%lx di=%lx"
>> +                       "\n",
>> +                       current->domain->domain_id, current->vcpu_id, 
>> __func__,
>> +                       (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);
>> +            hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
>> +        }
>> +    } else if (!frc && regs->error_code == 0
>> +               && bytes[0] == 0x0f && bytes[1] == 0x33 && regs->ecx 
>> == 0x10000)
>> +    {
>> +        /* "rdpmc 0x10000" */
>> +        /* Not a very good emulation!  But just not faulting is good 
>> enough
>> +         * to get NetApp booting. */
>> +        regs->edx = regs->eax = 0;
>> +
>> +        __update_guest_eip(regs, inst_len);
>
> What if inst_len is zero? (e.g. if NRIP is not supported?)

Needs to be handled (but this line is part of the lines that are planned 
to be dropped from this patch).


>
>
>
> -boris
>

    -Don Slutz

>> +
>> +        /* Doing the log in this case was too noisy for NetApp, so I 
>> moved
>> +         * it to 'else' */
>> +    } else {
>> +        if (hd->params[HVM_PARAM_VMPORT_LOGMASK] & 0x100000 /* 
>> LOG_GP_UNKNOWN */) {
>> +            printk("[HVM:%d.%d] <%s> "
>> +                   "gp: e2=%lx ec=%lx ip=%lx=>0x%x 0x%x(%ld,%d) 
>> ax=%lx bx=%lx cx=%lx dx=%lx si=%lx di=%lx"
>> +                   "\n",
>> +                   current->domain->domain_id, current->vcpu_id, 
>> __func__,
>> +                   (unsigned long)vmcb->exitinfo2, (unsigned 
>> long)regs->error_code,
>> +                   (unsigned long)regs->eip, (unsigned int)bytes[0],
>> +                   (unsigned int)bytes[1], inst_len, frc,
>> +                   (unsigned long)regs->eax, (unsigned long)regs->ebx,
>> +                   (unsigned long)regs->ecx, (unsigned long)regs->edx,
>> +                   (unsigned long)regs->esi, (unsigned long)regs->edi);
>> +        }
>> +        hvm_inject_hw_exception(TRAP_gp_fault, regs->error_code);
>> +    }
>> +}
>> +
>>
>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 08/10] connect vmport up
  2013-12-17 20:37   ` Konrad Rzeszutek Wilk
@ 2013-12-19  3:46     ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19  3:46 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Keir Fraser, Ian Campbell, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Don Slutz, xen-devel, Jan Beulich, Jun Nakajima,
	Boris Ostrovsky, Suravee Suthikulpanit

On 12/17/13 15:37, Konrad Rzeszutek Wilk wrote:
> On Thu, Dec 12, 2013 at 02:15:16PM -0500, Don Slutz wrote:
>> From: Don Slutz <dslutz@verizon.com>
> Please add a description of what this does.
Will do.
>> Signed-off-by: Don Slutz <dslutz@verizon.com>
>> ---
>>
[snip]

    -Don Slutz

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 00/10] Xen VMware tools support
  2013-12-19  0:46   ` Don Slutz
@ 2013-12-19  9:50     ` Ian Campbell
  2013-12-19 14:08       ` Don Slutz
  0 siblings, 1 reply; 54+ messages in thread
From: Ian Campbell @ 2013-12-19  9:50 UTC (permalink / raw)
  To: Don Slutz
  Cc: Keir Fraser, Jun Nakajima, Stefano Stabellini, Ian Jackson,
	Eddie Dong, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On Wed, 2013-12-18 at 19:46 -0500, Don Slutz wrote:
> On 12/17/13 14:03, Konrad Rzeszutek Wilk wrote:
> > On Thu, Dec 12, 2013 at 02:15:08PM -0500, Don Slutz wrote:
> >> From: Don Slutz <dslutz@verizon.com>
> >>
> >> See
> >>
> >> http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458
> > Can you say how this benefits Xen to detect this and take
> > advantage of it? Or is this Xen emulating VMWare so to a guest
> > it looks like its running under VMWare?
> This is Xen emulating part of VMWare.  Some parts of guests will think 
> it is running on VMware.

That doesn't answer the important part Konrad's question though: how
this benefits Xen.

A series like this should have a cover letter which explains what the
feature is, what use case it solves, why this is a useful thing and why
it is worth the burden of maintaining it going forward.

Ian.

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC PATCH 00/10] Xen VMware tools support
  2013-12-19  9:50     ` Ian Campbell
@ 2013-12-19 14:08       ` Don Slutz
  0 siblings, 0 replies; 54+ messages in thread
From: Don Slutz @ 2013-12-19 14:08 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Keir Fraser, Jun Nakajima, Stefano Stabellini, Ian Jackson,
	Eddie Dong, Don Slutz, xen-devel, Jan Beulich, Boris Ostrovsky,
	Suravee Suthikulpanit

On 12/19/13 04:50, Ian Campbell wrote:
> On Wed, 2013-12-18 at 19:46 -0500, Don Slutz wrote:
>> On 12/17/13 14:03, Konrad Rzeszutek Wilk wrote:
>>> On Thu, Dec 12, 2013 at 02:15:08PM -0500, Don Slutz wrote:
>>>> From: Don Slutz <dslutz@verizon.com>
>>>>
>>>> See
>>>>
>>>> http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458
>>> Can you say how this benefits Xen to detect this and take
>>> advantage of it? Or is this Xen emulating VMWare so to a guest
>>> it looks like its running under VMWare?
>> This is Xen emulating part of VMWare.  Some parts of guests will think
>> it is running on VMware.
> That doesn't answer the important part Konrad's question though: how
> this benefits Xen.
>
> A series like this should have a cover letter which explains what the
> feature is, what use case it solves, why this is a useful thing and why
> it is worth the burden of maintaining it going forward.
>
> Ian.
>
>
I see.  Some quick points that might help, I am working on a much better 
description.

This is a small part of the changes needed to allow running linux and 
windows (and others) guests that were built on VMware and run run them 
unchanged on Xen.

This small part is the start of Xen support of VMware backdoor io port 
which is how VMware tools (a standard addition installed on a guest) 
communicates to the hypervisor.

I picked this subset to start with because it only has changes in Xen.

Some of this code is already in QEMU and so KVM has some of this 
already.  QEMU supported backdoor commands include VMware mouse 
support.  A later patch set exists that links these changes, new code 
and Xen changes to QEMU to provide VMware mouse support under Xen.  The 
important part is that VMware mouse is an absolute position mouse and so 
network delays do not effect usage of the virtual mouse.

    -Don Slutz

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2013-12-19 14:08 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [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

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.