From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Don Slutz <dslutz@verizon.com>, xen-devel@lists.xen.org
Cc: Keir Fraser <keir@xen.org>,
Ian Campbell <ian.campbell@citrix.com>,
Jan Beulich <jbeulich@suse.com>
Subject: Re: [RFC][PATCH v2 1/1] Add IOREQ_TYPE_VMWARE_PORT
Date: Thu, 2 Oct 2014 21:33:41 +0100 [thread overview]
Message-ID: <542DB6A5.7080207@citrix.com> (raw)
In-Reply-To: <1412274977-6098-2-git-send-email-dslutz@verizon.com>
On 02/10/14 19:36, Don Slutz wrote:
> Signed-off-by: Don Slutz <dslutz@verizon.com>
> ---
> v2:
> Fixup usage of hvmtrace_io_assist().
> VMware only changes the 32bit part of the register.
> Added vmware_ioreq_t
>
> xen/arch/x86/hvm/emulate.c | 72 +++++++++++++++++++++++++++++++++++++++
> xen/arch/x86/hvm/io.c | 19 +++++++++++
> xen/arch/x86/hvm/vmware/vmport.c | 24 ++++++++++++-
> xen/include/asm-x86/hvm/emulate.h | 2 ++
> xen/include/asm-x86/hvm/vcpu.h | 1 +
> xen/include/public/hvm/ioreq.h | 19 +++++++++++
> 6 files changed, 136 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
> index c0f47d2..215f049 100644
> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -50,6 +50,78 @@ static void hvmtrace_io_assist(int is_mmio, ioreq_t *p)
> trace_var(event, 0/*!cycles*/, size, buffer);
> }
>
> +int hvmemul_do_vmport(uint16_t addr, int size, int dir,
> + struct cpu_user_regs *regs)
> +{
> + struct vcpu *curr = current;
> + struct hvm_vcpu_io *vio = &curr->arch.hvm_vcpu.hvm_io;
> + vmware_ioreq_t p = {
> + .type = IOREQ_TYPE_VMWARE_PORT,
> + .addr = addr,
> + .size = size,
> + .dir = dir,
> + .eax = regs->rax,
> + .ebx = regs->rbx,
> + .ecx = regs->rcx,
> + .edx = regs->rdx,
> + .esi = regs->rsi,
> + .edi = regs->rdi,
> + };
> + ioreq_t *pp = (ioreq_t *)&p;
> + ioreq_t op;
Eww.
Just because the C type system lets you abuse it like this doesn't mean
it is a clever idea to. Please refer to c/s 15a9f34d1b as an example of
the kinds of bugs it causes.
> +
> + ASSERT(sizeof(p) == sizeof(op));
> + ASSERT(offsetof(ioreq_t, type) == offsetof(vmware_ioreq_t, type));
> + ASSERT(offsetof(ioreq_t, vp_eport) == offsetof(vmware_ioreq_t, vp_eport));
These can be evaluated by the compiler. They should be BUILD_BUG_ON()s
rather than ASSERT()s.
> +
> + switch ( vio->io_state )
> + {
> + case HVMIO_none:
> + break;
> + case HVMIO_completed:
> + vio->io_state = HVMIO_none;
> + goto finish_access_vmport;
> + case HVMIO_dispatched:
> + /* May have to wait for previous cycle of a multi-write to complete. */
> + default:
> + return X86EMUL_UNHANDLEABLE;
> + }
> +
> + if ( hvm_io_pending(curr) )
> + {
> + gdprintk(XENLOG_WARNING, "WARNING: io already pending?\n");
> + return X86EMUL_UNHANDLEABLE;
> + }
> +
> + vio->io_state = HVMIO_handle_vmport_awaiting_completion;
> + vio->io_size = size;
> +
> + /* If there is no backing DM, just ignore accesses */
> + if ( !hvm_has_dm(curr->domain) )
> + {
> + vio->io_state = HVMIO_none;
> + vio->io_data = ~0ul;
> + }
> + else
> + {
> + if ( !hvm_send_assist_req(pp) )
> + vio->io_state = HVMIO_none;
> + return X86EMUL_RETRY;
> + }
> +
> + finish_access_vmport:
> + memset(&op, 0, sizeof(op));
> + op.dir = dir;
> + op.addr = (uint16_t)regs->rdx;
> + op.data_is_ptr = 0;
> + op.data = vio->io_data;
Most of this can be achieved with struct initialisation similar to 'p'
above.
> + hvmtrace_io_assist(0, &op);
> +
> + memcpy(®s->rax, &vio->io_data, vio->io_size);
This is going to need some justification. Clobbering the registers like
this looks bogus.
> +
> + return X86EMUL_OKAY;
> +}
> +
> static int hvmemul_do_io(
> int is_mmio, paddr_t addr, unsigned long *reps, int size,
> paddr_t ram_gpa, int dir, int df, void *p_data)
> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
> index 68fb890..a8bf324 100644
> --- a/xen/arch/x86/hvm/io.c
> +++ b/xen/arch/x86/hvm/io.c
> @@ -197,6 +197,25 @@ void hvm_io_assist(ioreq_t *p)
> else
> memcpy(&guest_cpu_user_regs()->rax, &p->data, vio->io_size);
> break;
> + case HVMIO_handle_vmport_awaiting_completion:
> + {
> + struct cpu_user_regs *regs = guest_cpu_user_regs();
> + vmware_ioreq_t *vp = (vmware_ioreq_t *)p;
> +
> + ASSERT(sizeof(*p) == sizeof(*vp));
> + ASSERT(offsetof(ioreq_t, type) == offsetof(vmware_ioreq_t, type));
> + ASSERT(offsetof(ioreq_t, vp_eport) == offsetof(vmware_ioreq_t, vp_eport));
> +
> + /* Always zero extension for eax */
> + regs->rax = vp->eax;
> + /* Only change the 32bit part of the register */
> + regs->rbx = (regs->rbx & 0xffffffff00000000ull) | vp->ebx;
regs->_e?? allows you to directly access the lower half, avoiding these
bit manipulations.
~Andrew
> + regs->rcx = (regs->rcx & 0xffffffff00000000ull) | vp->ecx;
> + regs->rdx = (regs->rdx & 0xffffffff00000000ull) | vp->edx;
> + regs->rsi = (regs->rsi & 0xffffffff00000000ull) | vp->esi;
> + regs->rdi = (regs->rdi & 0xffffffff00000000ull) | vp->edi;
> + }
> + break;
> default:
> break;
> }
> diff --git a/xen/arch/x86/hvm/vmware/vmport.c b/xen/arch/x86/hvm/vmware/vmport.c
> index 962ee32..0649106 100644
> --- a/xen/arch/x86/hvm/vmware/vmport.c
> +++ b/xen/arch/x86/hvm/vmware/vmport.c
> @@ -147,9 +147,31 @@ int vmport_ioport(int dir, uint32_t port, uint32_t bytes, uint32_t *val)
> regs->rax = 0x0;
> break;
> default:
> + { /* Let backing DM handle */
> + int rc;
> +
> HVMTRACE_ND(VMPORT_UNKNOWN, 0, 1/*cycles*/, 6,
> - (bytes << 8) + dir, cmd, regs->rbx,
> + (bytes << 8) | dir, cmd, regs->rbx,
> regs->rcx, regs->rsi, regs->rdi);
> + rc = hvmemul_do_vmport(BDOOR_PORT, bytes, dir, regs);
> + switch (rc)
> + {
> + case X86EMUL_OKAY:
> + break;
> + case X86EMUL_RETRY:
> + {
> + struct hvm_vcpu_io *vio = ¤t->arch.hvm_vcpu.hvm_io;
> +
> + if ( vio->io_state != HVMIO_handle_vmport_awaiting_completion )
> + return 0;
> + break;
> + }
> + default:
> + gdprintk(XENLOG_ERR, "Weird HVM ioemulation status %d.\n", rc);
> + domain_crash(current->domain);
> + break;
> + }
> + }
> break;
> }
>
> diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h
> index 5411302..7d18435 100644
> --- a/xen/include/asm-x86/hvm/emulate.h
> +++ b/xen/include/asm-x86/hvm/emulate.h
> @@ -53,6 +53,8 @@ struct segment_register *hvmemul_get_seg_reg(
> int hvmemul_do_pio(
> unsigned long port, unsigned long *reps, int size,
> paddr_t ram_gpa, int dir, int df, void *p_data);
> +int hvmemul_do_vmport(uint16_t addr, int size, int dir,
> + struct cpu_user_regs *regs);
>
> void hvm_dump_emulation_state(const char *prefix,
> struct hvm_emulate_ctxt *hvmemul_ctxt);
> diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
> index 01e0665..1e63d7f 100644
> --- a/xen/include/asm-x86/hvm/vcpu.h
> +++ b/xen/include/asm-x86/hvm/vcpu.h
> @@ -36,6 +36,7 @@ enum hvm_io_state {
> HVMIO_awaiting_completion,
> HVMIO_handle_mmio_awaiting_completion,
> HVMIO_handle_pio_awaiting_completion,
> + HVMIO_handle_vmport_awaiting_completion,
> HVMIO_completed
> };
>
> diff --git a/xen/include/public/hvm/ioreq.h b/xen/include/public/hvm/ioreq.h
> index 5b5fedf..7d5ba58 100644
> --- a/xen/include/public/hvm/ioreq.h
> +++ b/xen/include/public/hvm/ioreq.h
> @@ -35,6 +35,7 @@
> #define IOREQ_TYPE_PIO 0 /* pio */
> #define IOREQ_TYPE_COPY 1 /* mmio ops */
> #define IOREQ_TYPE_PCI_CONFIG 2
> +#define IOREQ_TYPE_VMWARE_PORT 3
> #define IOREQ_TYPE_TIMEOFFSET 7
> #define IOREQ_TYPE_INVALIDATE 8 /* mapcache */
>
> @@ -48,6 +49,8 @@
> *
> * 63....48|47..40|39..35|34..32|31........0
> * SEGMENT |BUS |DEV |FN |OFFSET
> + *
> + * For I/O type IOREQ_TYPE_VMWARE_PORT use the vmware_ioreq.
> */
> struct ioreq {
> uint64_t addr; /* physical address */
> @@ -66,6 +69,22 @@ struct ioreq {
> };
> typedef struct ioreq ioreq_t;
>
> +struct vmware_ioreq {
> + uint32_t esi;
> + uint32_t edi;
> + uint32_t eax;
> + uint32_t ebx;
> + uint32_t ecx;
> + uint32_t edx;
> + uint32_t vp_eport; /* evtchn for notifications to/from device model */
> + uint16_t addr;
> + uint8_t state:4;
> + uint8_t dir:1; /* 1=read, 0=write */
> + uint8_t size:3;
> + uint8_t type; /* I/O type */
> +};
> +typedef struct vmware_ioreq vmware_ioreq_t;
> +
> struct shared_iopage {
> struct ioreq vcpu_ioreq[1];
> };
next prev parent reply other threads:[~2014-10-02 20:33 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-02 18:36 [RFC][PATCH v2 0/1] Add support for Xen access to vmport Don Slutz
2014-10-02 18:36 ` [RFC][PATCH v2 1/1] Add IOREQ_TYPE_VMWARE_PORT Don Slutz
2014-10-02 20:33 ` Andrew Cooper [this message]
2014-10-02 21:56 ` Don Slutz
2014-10-02 22:23 ` Andrew Cooper
2014-10-03 9:47 ` Stefano Stabellini
2014-10-03 9:51 ` Ian Campbell
2014-10-03 9:54 ` Stefano Stabellini
2014-10-03 19:27 ` Don Slutz
2014-10-06 7:55 ` Jan Beulich
2014-10-06 9:21 ` Stefano Stabellini
2014-10-06 9:39 ` Jan Beulich
2014-10-06 19:51 ` Don Slutz
2014-10-07 8:05 ` Jan Beulich
2014-10-06 9:54 ` Paul Durrant
2014-10-03 9:29 ` Paul Durrant
2014-10-03 19:44 ` Don Slutz
2014-10-03 9:46 ` Paul Durrant
2014-10-03 19:56 ` [Qemu-devel] [Xen-devel] " Don Slutz
2014-10-09 14:26 ` [RFC][PATCH v2x prototype " Don Slutz
2014-10-13 13:26 ` Paul Durrant
2014-10-13 17:11 ` Don Slutz
2014-10-14 9:57 ` Paul Durrant
2014-10-14 19:06 ` Don Slutz
2014-10-03 19:56 ` [RFC][PATCH v2 " 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=542DB6A5.7080207@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=dslutz@verizon.com \
--cc=ian.campbell@citrix.com \
--cc=jbeulich@suse.com \
--cc=keir@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 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.