xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: George Dunlap <george.dunlap@eu.citrix.com>
To: Don Slutz <dslutz@verizon.com>, xen-devel@lists.xen.org
Cc: Kevin Tian <kevin.tian@intel.com>, Keir Fraser <keir@xen.org>,
	Ian Campbell <ian.campbell@citrix.com>,
	Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
	Jun Nakajima <jun.nakajima@intel.com>,
	Eddie Dong <eddie.dong@intel.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>, Tim Deegan <tim@xen.org>,
	Aravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com>,
	Jan Beulich <jbeulich@suse.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Subject: Re: [PATCH for-4.5 v6 04/16] xen: Add vmware_port support
Date: Wed, 24 Sep 2014 17:01:47 +0100	[thread overview]
Message-ID: <5422EAEB.2050807@eu.citrix.com> (raw)
In-Reply-To: <1411236447-7435-5-git-send-email-dslutz@verizon.com>

On 09/20/2014 07:07 PM, Don Slutz wrote:
> This includes adding is_vmware_port_enabled
>
> This is a new domain_create() flag, DOMCRF_vmware_port.  It is
> passed to domctl as XEN_DOMCTL_CDF_vmware_port.
>
> This enables limited support of VMware's hyper-call.
>
> This is both a more complete support then in currently provided by
> QEMU and/or KVM and less.  The missing part requires QEMU changes
> and has been left out until the QEMU patches are accepted upstream.
>
> VMware's hyper-call is also known as VMware Backdoor I/O Port.
>
> Note: this support does not depend on vmware_hw being non-zero.
>
> Summary is that VMware treats "in (%dx),%eax" (or "out %eax,(%dx)")
> to port 0x5658 specially.  Note: since many operations return data
> in EAX, "in (%dx),%eax" is the one to use.  The other lengths like
> "in (%dx),%al" will still do things, only AL part of EAX will be
> changed.  For "out %eax,(%dx)" of all lengths, EAX will remain
> unchanged.
>
> Also this instruction is allowed to be used from ring 3.  To
> support this the vmexit for GP needs to be enabled.  I have not
> fully tested that nested HVM is doing the right thing for this.
>
> An open source example of using this is:
>
> http://open-vm-tools.sourceforge.net/
>
> Which only uses "inl (%dx)".  Also
>
> http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458
>
> The support included is enough to allow VMware tools to install in a
> HVM domU.
>
> For a debug=y build there is a new command line option
> vmport_debug=.  It enabled output to the console of various
> stages of handling the "in (%dx)" instruction.
>
> Signed-off-by: Don Slutz <dslutz@verizon.com>

[snip]

> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index 7b1dfe6..e2e4aad 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -510,6 +510,8 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
>       d->arch.hvm_domain.mem_sharing_enabled = 0;
>   
>       d->arch.s3_integrity = !!(domcr_flags & DOMCRF_s3_integrity);
> +    d->arch.hvm_domain.is_vmware_port_enabled =
> +        (domcr_flags & DOMCRF_vmware_port);

Should this be "!!(domcr..."?

> diff --git a/xen/arch/x86/hvm/vmware/vmport.c b/xen/arch/x86/hvm/vmware/vmport.c
> new file mode 100644
> index 0000000..811c303
> --- /dev/null
> +++ b/xen/arch/x86/hvm/vmware/vmport.c
> @@ -0,0 +1,326 @@
> +/*
> + * 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/config.h>
> +#include <xen/lib.h>
> +#include <asm/hvm/hvm.h>
> +#include <asm/hvm/support.h>
> +#include <asm/hvm/vmport.h>
> +
> +#include "backdoor_def.h"
> +#include "guest_msg_def.h"
> +
> +#define MAX_INST_LEN 15
> +
> +#ifndef NDEBUG
> +unsigned int opt_vmport_debug __read_mostly;
> +integer_param("vmport_debug", opt_vmport_debug);
> +#endif
> +
> +/* More VMware defines */
> +
> +#define VMWARE_GUI_AUTO_GRAB              0x001
> +#define VMWARE_GUI_AUTO_UNGRAB            0x002
> +#define VMWARE_GUI_AUTO_SCROLL            0x004
> +#define VMWARE_GUI_AUTO_RAISE             0x008
> +#define VMWARE_GUI_EXCHANGE_SELECTIONS    0x010
> +#define VMWARE_GUI_WARP_CURSOR_ON_UNGRAB  0x020
> +#define VMWARE_GUI_FULL_SCREEN            0x040
> +
> +#define VMWARE_GUI_TO_FULL_SCREEN         0x080
> +#define VMWARE_GUI_TO_WINDOW              0x100
> +
> +#define VMWARE_GUI_AUTO_RAISE_DISABLED    0x200
> +
> +#define VMWARE_GUI_SYNC_TIME              0x400
> +
> +/* When set, toolboxes should not show the cursor options page. */
> +#define VMWARE_DISABLE_CURSOR_OPTIONS     0x800
> +
> +void vmport_register(struct domain *d)
> +{
> +    register_portio_handler(d, BDOOR_PORT, 4, vmport_ioport);
> +}
> +
> +int vmport_ioport(int dir, uint32_t port, uint32_t bytes, uint32_t *val)
> +{
> +    struct cpu_user_regs *regs = guest_cpu_user_regs();
> +    uint32_t cmd = regs->rcx & 0xffff;
> +    uint32_t magic = regs->rax;
> +    int rc = X86EMUL_OKAY;
> +
> +    if ( magic == BDOOR_MAGIC )
> +    {
> +        uint64_t saved_rax = regs->rax;
> +        uint64_t value;
> +
> +        VMPORT_DBG_LOG(VMPORT_LOG_TRACE,
> +                       "VMware trace dir=%d bytes=%u ip=%"PRIx64" cmd=%d ax=%"
> +                       PRIx64" bx=%"PRIx64" cx=%"PRIx64" dx=%"PRIx64" si=%"
> +                       PRIx64" di=%"PRIx64"\n", dir, bytes,
> +                       regs->rip, cmd, regs->rax, regs->rbx, regs->rcx,
> +                       regs->rdx, regs->rsi, regs->rdi);
> +        switch ( cmd )
> +        {
> +        case BDOOR_CMD_GETMHZ:
> +            /* ... */
> +            regs->rbx = BDOOR_MAGIC;
> +            regs->rax = current->domain->arch.tsc_khz / 1000;
> +            break;
> +        case BDOOR_CMD_GETVERSION:
> +            /* ... */
> +            regs->rbx = BDOOR_MAGIC;
> +            /* VERSION_MAGIC */
> +            regs->rax = 6;
> +            /* Claim we are an ESX. VMX_TYPE_SCALABLE_SERVER */
> +            regs->rcx = 2;
> +            break;
> +        case BDOOR_CMD_GETSCREENSIZE:
> +            /* We have no screen size */
> +            regs->rax = 0;
> +            break;
> +        case BDOOR_CMD_GETHWVERSION:
> +            /* vmware_hw */
> +            regs->rax = 0;
> +            if ( is_hvm_vcpu(current) )
> +            {
> +                struct hvm_domain *hd = &current->domain->arch.hvm_domain;
> +
> +                regs->rax = hd->params[HVM_PARAM_VMWARE_HW];
> +            }
> +            if ( !regs->rax )
> +                regs->rax = 4;  /* Act like version 4 */
> +            break;
> +        case BDOOR_CMD_GETHZ:
> +            value = current->domain->arch.tsc_khz * 1000;
> +            /* apic-frequency (bus speed) */
> +            regs->rcx = (uint32_t)(1000000000ULL / APIC_BUS_CYCLE_NS);
> +            /* High part of tsc-frequency */
> +            regs->rbx = (uint32_t)(value >> 32);
> +            /* Low part of tsc-frequency */
> +            regs->rax = value;

Either the comment or the code here is wrong -- this is clearly not the 
lower 32 bits, at least on 64-bit guests. :-)

If the code is right -- that is, if a 32-bit guest find this truncated 
automatically, but a 64-bit guest find all 64 bits here (and thus not 
have to reconstruct it) -- you should make the comment more informative; 
for example:
  /* On 32-bit systems this will be the lower 32 bits.  64-bit systems 
can just use the full value from rax. */

(Word-wrapped, of course.)

Hmm -- looks like regs->rax will be clipped to 32 bits for a 4-byte IO 
read?  In which case the comment here should reflect this, but you have 
the same basic issue for BDOOR_CMD_GETTIMEFUL regs->rdx (which will not 
be clipped, I don't think).

> +            break;
> +        case BDOOR_CMD_GETTIME:
> +            value = get_localtime_us(current->domain);
> +            /* hostUsecs */
> +            regs->rbx = (uint32_t)(value % 1000000UL);
> +            /* hostSecs */
> +            regs->rax = value / 1000000ULL;
> +            /* maxTimeLag */
> +            regs->rcx = 0;
> +            break;
> +        case BDOOR_CMD_GETTIMEFULL:
> +            value = get_localtime_us(current->domain);
> +            /* ... */
> +            regs->rax = BDOOR_MAGIC;
> +            /* hostUsecs */
> +            regs->rbx = (uint32_t)(value % 1000000UL);
> +            /* High part of hostSecs */
> +            regs->rsi = (uint32_t)((value / 1000000ULL) >> 32);
> +            /* Low part of hostSecs */
> +            regs->rdx = (uint32_t)(value / 1000000ULL);

Same here.

> +            /* maxTimeLag */
> +            regs->rcx = 0;
> +            break;
> +        case BDOOR_CMD_GETGUIOPTIONS:
> +            regs->rax = VMWARE_GUI_AUTO_GRAB | VMWARE_GUI_AUTO_UNGRAB |
> +                VMWARE_GUI_AUTO_RAISE_DISABLED | VMWARE_GUI_SYNC_TIME |
> +                VMWARE_DISABLE_CURSOR_OPTIONS;
> +            break;
> +        case BDOOR_CMD_SETGUIOPTIONS:
> +            regs->rax = 0x0;
> +            break;
> +        default:
> +            VMPORT_DBG_LOG(VMPORT_LOG_ERROR,
> +                           "VMware bytes=%d dir=%d cmd=%d",
> +                           bytes, dir, cmd);
> +            break;
> +        }
> +        VMPORT_DBG_LOG(VMPORT_LOG_VMWARE_AFTER,
> +                       "VMware after ip=%"PRIx64" cmd=%d ax=%"PRIx64" bx=%"
> +                       PRIx64" cx=%"PRIx64" dx=%"PRIx64" si=%"PRIx64" di=%"
> +                       PRIx64"\n",
> +                       regs->rip, cmd, regs->rax, regs->rbx, regs->rcx,
> +                       regs->rdx, regs->rsi, regs->rdi);
> +        if ( dir == IOREQ_READ )
> +        {
> +            switch ( bytes )
> +            {
> +            case 1:
> +                regs->rax = (saved_rax & 0xffffff00) | (regs->rax & 0xff);
> +                break;
> +            case 2:
> +                regs->rax = (saved_rax & 0xffff0000) | (regs->rax & 0xffff);
> +                break;
> +            case 4:
> +                regs->rax = (uint32_t)regs->rax;
> +                break;
> +            }
> +            *val = regs->rax;
> +        }
> +        else
> +            regs->rax = saved_rax;
> +    }
> +    else
> +    {
> +        rc = X86EMUL_UNHANDLEABLE;
> +        VMPORT_DBG_LOG(VMPORT_LOG_ERROR,
> +                       "Not VMware %x vs %x; ip=%"PRIx64" ax=%"PRIx64
> +                       " bx=%"PRIx64" cx=%"PRIx64" dx=%"PRIx64" si=%"PRIx64
> +                       " di=%"PRIx64"",
> +                       magic, BDOOR_MAGIC, regs->rip, regs->rax, regs->rbx,
> +                       regs->rcx, regs->rdx, regs->rsi, regs->rdi);
> +    }
> +
> +    return rc;
> +}
> +
> +int vmport_gp_check(struct cpu_user_regs *regs, struct vcpu *v,
> +                    unsigned long *inst_len, unsigned long inst_addr,
> +                    unsigned long ei1, unsigned long ei2)

I've wondered, in another e-mail, whether it would make more sense to 
try to re-use the normal Xen emulation code, instead of duplicating its 
IO instruction decoding stuff here.

I think I probably wouldn't make that a blocker for acceptance, though.  
However...

> +{
> +    ASSERT(v->domain->arch.hvm_domain.is_vmware_port_enabled);

At the moment I think this ASSERT is misplaced; there are no checks for 
this anywhere in the handler path to this point.  If at any time in the 
future (or for any other reason) #GP exiting gets enabled (for example, 
if the introspection stuff wants to be notifed on #GPs), you'll end up 
going through this path whether or not is_vmware_port_enabled is true.

I think you should instead "if(!is_vmware_port_enabled) return" here.  
That would effectively isolate these new changes from being able to 
introduce security issues for VMs which don't enable vmware_port, making 
it less risky to accept as-is.

[snip]

> diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
> index fc1f882..6fe9389 100644
> --- a/xen/arch/x86/hvm/vmx/vmcs.c
> +++ b/xen/arch/x86/hvm/vmx/vmcs.c
> @@ -1102,6 +1102,8 @@ 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))
> +              | (v->domain->arch.hvm_domain.is_vmware_port_enabled ?
> +                 (1U << TRAP_gp_fault) : 0)
>                 | (1U << TRAP_no_device);

Probably not mandatory, but it might be nice to pull this bitmap logic 
into a function, so that you don't have the code duplication (here and 
in vmx_update_guest_cr()).

  -George

  parent reply	other threads:[~2014-09-24 16:01 UTC|newest]

Thread overview: 93+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-20 18:07 [PATCH for-4.5 v6 00/16] Xen VMware tools support Don Slutz
2014-09-20 18:07 ` [PATCH for-4.5 v6 01/16] xen: Add support for VMware cpuid leaves Don Slutz
2014-09-22 11:49   ` Andrew Cooper
2014-09-22 16:53     ` Don Slutz
2014-09-24 14:33   ` George Dunlap
2014-09-20 18:07 ` [PATCH for-4.5 v6 02/16] tools: Add vmware_hw support Don Slutz
2014-09-22 13:34   ` Ian Campbell
2014-09-22 22:08     ` Don Slutz
2014-09-24 14:44   ` George Dunlap
2014-09-24 21:06     ` Don Slutz
2014-09-20 18:07 ` [PATCH for-4.5 v6 03/16] vmware: Add VMware provided include files Don Slutz
2014-09-20 18:07 ` [PATCH for-4.5 v6 04/16] xen: Add vmware_port support Don Slutz
2014-09-23 17:16   ` Boris Ostrovsky
2014-09-24  8:28     ` Jan Beulich
2014-09-26 19:09     ` Don Slutz
2014-09-24 16:01   ` George Dunlap [this message]
2014-09-24 16:48     ` Don Slutz
2014-09-24 17:42       ` Andrew Cooper
2014-09-20 18:07 ` [PATCH for-4.5 v6 05/16] tools: " Don Slutz
2014-09-22 13:41   ` Ian Campbell
2014-09-22 16:34     ` Andrew Cooper
2014-09-22 21:22       ` Don Slutz
2014-09-24 16:24         ` George Dunlap
2014-09-24 18:25           ` Don Slutz
2014-09-22 16:42     ` Don Slutz
2014-09-23 12:20       ` Ian Campbell
2014-09-24 16:31         ` Don Slutz
2014-09-24 16:44           ` George Dunlap
2014-09-24 18:29             ` Don Slutz
2014-09-25 11:24           ` Ian Campbell
2014-09-25 14:17             ` George Dunlap
2014-09-25 14:21               ` Ian Campbell
2014-09-26 19:19             ` Don Slutz
2014-09-20 18:07 ` [PATCH for-4.5 v6 06/16] xen: Convert vmware_port to xentrace usage Don Slutz
2014-09-24 17:27   ` George Dunlap
2014-09-24 19:07     ` Don Slutz
2014-09-25 15:14       ` George Dunlap
2014-09-29 18:10         ` Don Slutz
2014-09-20 18:07 ` [PATCH for-4.5 v6 07/16] tools: " Don Slutz
2014-09-25 15:18   ` George Dunlap
2014-09-20 18:07 ` [PATCH for-4.5 v6 08/16] xen: Add limited support of VMware's hyper-call rpc Don Slutz
2014-09-22 13:47   ` Ian Campbell
2014-09-22 21:18     ` Don Slutz
2014-09-23 12:34       ` Ian Campbell
2014-09-23 22:03         ` Slutz, Donald Christopher
2014-09-25 16:28     ` George Dunlap
2014-09-20 18:07 ` [PATCH for-4.5 v6 09/16] tools: " Don Slutz
2014-09-22 13:52   ` Ian Campbell
2014-09-22 21:32     ` Don Slutz
2014-09-23 12:35       ` Ian Campbell
2014-09-20 18:07 ` [PATCH for-4.5 v6 10/16] Add VMware tool's triggers Don Slutz
2014-09-20 18:07 ` [PATCH for-4.5 v6 11/16] Add live migration of VMware's hyper-call RPC Don Slutz
2014-09-20 18:07 ` [PATCH for-4.5 v6 12/16] Add dump of HVM_SAVE_CODE(VMPORT) to xen-hvmctx Don Slutz
2014-09-20 18:07 ` [OPTIONAL][PATCH for-4.5 v6 13/16] Add xen-hvm-param Don Slutz
2014-09-20 18:07 ` [OPTIONAL][PATCH for-4.5 v6 14/16] Add xen-vmware-guestinfo Don Slutz
2014-09-20 18:07 ` [OPTIONAL][PATCH for-4.5 v6 15/16] Add xen-list-vmware-guestinfo Don Slutz
2014-09-20 18:07 ` [OPTIONAL][PATCH for-4.5 v6 16/16] Add xen-hvm-send-trigger Don Slutz
2014-09-22 13:56 ` [PATCH for-4.5 v6 00/16] Xen VMware tools support Ian Campbell
2014-09-22 15:19   ` George Dunlap
2014-09-22 15:34     ` Ian Campbell
2014-09-22 15:38       ` George Dunlap
2014-09-22 15:50         ` Ian Campbell
2014-09-22 15:55           ` George Dunlap
2014-09-22 17:19             ` Don Slutz
2014-09-22 22:00               ` Tian, Kevin
2014-09-23 12:30               ` Ian Campbell
2014-09-23 12:35                 ` George Dunlap
2014-09-23 12:40                   ` Ian Campbell
2014-09-24 15:52                 ` George Dunlap
2014-09-24 18:09                   ` Don Slutz
2014-09-24 17:19                 ` Don Slutz
2014-09-24 20:21                   ` Konrad Rzeszutek Wilk
2014-09-26 19:03                     ` Don Slutz
2014-09-26 19:28                       ` Konrad Rzeszutek Wilk
2014-09-25 11:35                   ` Ian Campbell
2014-09-22 16:18         ` Jan Beulich
2014-09-22 18:32           ` Don Slutz
2014-09-25 10:37           ` Tim Deegan
2014-09-26 20:00             ` Don Slutz
2014-09-29  6:50               ` Jan Beulich
2014-09-29 13:27                 ` George Dunlap
2014-09-29 13:49                   ` Jan Beulich
2014-09-29 23:13                   ` Don Slutz
2014-09-30  7:05                     ` Jan Beulich
2014-09-30 10:02                       ` George Dunlap
2014-09-30 22:11                         ` Slutz, Donald Christopher
2014-09-30 10:09                     ` George Dunlap
2014-09-30 22:23                       ` Slutz, Donald Christopher
2014-10-02 10:05               ` Tim Deegan
2014-10-02 19:20                 ` Don Slutz
2014-10-03  7:09                   ` Tim Deegan
2014-09-22 15:52       ` Andrew Cooper
2014-09-22 18:39         ` Don Slutz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5422EAEB.2050807@eu.citrix.com \
    --to=george.dunlap@eu.citrix.com \
    --cc=Aravind.Gopalakrishnan@amd.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=dslutz@verizon.com \
    --cc=eddie.dong@intel.com \
    --cc=ian.campbell@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=jun.nakajima@intel.com \
    --cc=keir@xen.org \
    --cc=kevin.tian@intel.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=suravee.suthikulpanit@amd.com \
    --cc=tim@xen.org \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).