All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Razvan Cojocaru <rcojocaru@bitdefender.com>, xen-devel@lists.xen.org
Cc: mdontu@bitdefender.com, tim@xen.org, JBeulich@suse.com
Subject: Re: [PATCH RFC V2 1/6] xen: Emulate with no writes
Date: Fri, 11 Jul 2014 17:23:48 +0100	[thread overview]
Message-ID: <53C00F94.5020907@citrix.com> (raw)
In-Reply-To: <1405093418-23481-1-git-send-email-rcojocaru@bitdefender.com>

On 11/07/14 16:43, Razvan Cojocaru wrote:
> Added support for emulating an instruction with no memory writes.
> Additionally, introduced hvm_emulate_one_full(), which acts upon all
> possible return values from the hvm_emulate_one() functions (RETRY,
> EXCEPTION, UNHANDLEABLE).
>
> Changes since V1:
>  - Removed the Linux code that computes the length of an instruction.
>  - Unused function parameters are no longer marked.
>  - Refactored the code to eliminate redundancy.
>  - Made the exception passed on to the guest by hvm_emulate_one_full()
>    configurable.
>
> Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
> ---
>  xen/arch/x86/hvm/emulate.c        |   73 +++++++++++++++++++++++++++++++++++--
>  xen/include/asm-x86/hvm/emulate.h |    5 +++
>  2 files changed, 75 insertions(+), 3 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
> index eac159f..114a77a 100644
> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -688,6 +688,17 @@ static int hvmemul_write(
>      return X86EMUL_OKAY;
>  }
>  
> +static int hvmemul_write_dummy(

hvmemul_write_discard() would make its purpose more clear.

> +    enum x86_segment seg,
> +    unsigned long offset,
> +    void *p_data,
> +    unsigned int bytes,
> +    struct x86_emulate_ctxt *ctxt)
> +{
> +    /* discarding the write */

Full stop please.

> +    return X86EMUL_OKAY;
> +}
> +
>  static int hvmemul_cmpxchg(
>      enum x86_segment seg,
>      unsigned long offset,
> @@ -1138,8 +1149,8 @@ static const struct x86_emulate_ops hvm_emulate_ops = {
>      .invlpg        = hvmemul_invlpg
>  };
>  
> -int hvm_emulate_one(
> -    struct hvm_emulate_ctxt *hvmemul_ctxt)
> +static int hvm_emulate_one_with_ops(struct hvm_emulate_ctxt *hvmemul_ctxt,
> +    const struct x86_emulate_ops *ops)

You could get away with a renaming this to _hvm_emulate_one() to help
identify that it is basically identical to hvm_emulate_one(), just with
slightly different parameters.

>  {
>      struct cpu_user_regs *regs = hvmemul_ctxt->ctxt.regs;
>      struct vcpu *curr = current;
> @@ -1191,7 +1202,7 @@ int hvm_emulate_one(
>      vio->mmio_retrying = vio->mmio_retry;
>      vio->mmio_retry = 0;
>  
> -    rc = x86_emulate(&hvmemul_ctxt->ctxt, &hvm_emulate_ops);
> +    rc = x86_emulate(&hvmemul_ctxt->ctxt, ops);
>  
>      if ( rc == X86EMUL_OKAY && vio->mmio_retry )
>          rc = X86EMUL_RETRY;
> @@ -1239,6 +1250,62 @@ int hvm_emulate_one(
>      return X86EMUL_OKAY;
>  }
>  
> +int hvm_emulate_one(
> +    struct hvm_emulate_ctxt *hvmemul_ctxt)
> +{
> +    return hvm_emulate_one_with_ops(hvmemul_ctxt, &hvm_emulate_ops);
> +}
> +
> +int hvm_emulate_one_no_write(
> +    struct hvm_emulate_ctxt *hvmemul_ctxt)
> +{
> +    struct x86_emulate_ops local_ops = hvm_emulate_ops;
> +    local_ops.write = hvmemul_write_dummy;

This is runtime constant and somwhat expensive to set up for each
function call.

You could make a static const struct x86_emulate_ops
hvm_emulate_ops_no_write and use that each time.

> +
> +    return hvm_emulate_one_with_ops(hvmemul_ctxt, &local_ops);
> +}
> +
> +void hvm_emulate_one_full(bool_t nowrite,
> +    unsigned int unhandleable_trapnr,
> +    int unhandleable_errcode)
> +{
> +    struct hvm_emulate_ctxt ctx[1] = {};

This construct looks suspect.  What is wrong with

struct hvm_emulate_ctxt ctx = { 0 }; and using &ctx below ?

> +    int rc = X86EMUL_RETRY;
> +
> +    hvm_emulate_prepare(ctx, guest_cpu_user_regs());
> +
> +    while ( rc == X86EMUL_RETRY )
> +    {
> +        if ( nowrite )
> +            rc = hvm_emulate_one_no_write(ctx);
> +        else
> +            rc = hvm_emulate_one(ctx);
> +    }

This however is not appropriate.  X86EMUL_RETRY can include "talk to
dom0 and get the paging subsystem to page in part of the VM", which
given some current work-in-progress can be to the other end of a network
connection on the far side of an optimistic migration.

You can't cause a Xen pcpu to spin like this for that length of time. 
Anything longer than a second and all other pcpus will block against the
time calibration rendezvous, and longer than 5 will panic on the NMI
watchdog.

> +
> +    switch ( rc )
> +    {
> +    case X86EMUL_UNHANDLEABLE:
> +        gdprintk(XENLOG_DEBUG, "Emulation failed @ %04x:%lx: "
> +               "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
> +               hvmemul_get_seg_reg(x86_seg_cs, ctx)->sel,
> +               ctx->insn_buf_eip,
> +               ctx->insn_buf[0], ctx->insn_buf[1],
> +               ctx->insn_buf[2], ctx->insn_buf[3],
> +               ctx->insn_buf[4], ctx->insn_buf[5],
> +               ctx->insn_buf[6], ctx->insn_buf[7],
> +               ctx->insn_buf[8], ctx->insn_buf[9]);

Hmm - I keep meaning to add a new %p custom format to print out hex
buffers like this.  It is sadly quite a long way down my todo list.

> +        hvm_inject_hw_exception(unhandleable_trapnr, unhandleable_errcode);
> +        break;
> +    case X86EMUL_EXCEPTION:
> +        if ( ctx->exn_pending )
> +            hvm_inject_hw_exception(ctx->exn_vector, ctx->exn_error_code);
> +        /* fall through */
> +    default:
> +        hvm_emulate_writeback(ctx);
> +        break;
> +    }
> +}
> +
>  void hvm_emulate_prepare(
>      struct hvm_emulate_ctxt *hvmemul_ctxt,
>      struct cpu_user_regs *regs)
> diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h
> index 00a06cc..d68b485 100644
> --- a/xen/include/asm-x86/hvm/emulate.h
> +++ b/xen/include/asm-x86/hvm/emulate.h
> @@ -37,6 +37,11 @@ struct hvm_emulate_ctxt {
>  
>  int hvm_emulate_one(
>      struct hvm_emulate_ctxt *hvmemul_ctxt);
> +int hvm_emulate_one_no_write(
> +    struct hvm_emulate_ctxt *hvmemul_ctxt);
> +void hvm_emulate_one_full(bool_t nowrite,
> +    unsigned int unhandleable_trapnr,
> +    int unhandleable_errcode);

Prevailing Xen nomenclature would be 'trapnr' and 'error_code'.  The
error code should be unsigned as well.

~Andrew

>  void hvm_emulate_prepare(
>      struct hvm_emulate_ctxt *hvmemul_ctxt,
>      struct cpu_user_regs *regs);

  parent reply	other threads:[~2014-07-11 16:23 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-11 15:43 [PATCH RFC V2 1/6] xen: Emulate with no writes Razvan Cojocaru
2014-07-11 15:43 ` [PATCH RFC V2 2/6] xen: Optimize introspection access to guest state Razvan Cojocaru
2014-07-11 16:54   ` Andrew Cooper
2014-07-11 16:57     ` Andrew Cooper
2014-07-11 18:03     ` Razvan Cojocaru
2014-07-11 18:09       ` Andrew Cooper
2014-07-11 15:43 ` [PATCH RFC V2 3/6] xen: Force-enable relevant MSR events; optimize the number of sent MSR events Razvan Cojocaru
2014-07-11 17:03   ` Andrew Cooper
2014-07-11 18:09     ` Razvan Cojocaru
     [not found]       ` <CAGU+ausrcu=L7Kf30gZJXRnnxrKe7EMYXTGByOY4agwoK0nXeA@mail.gmail.com>
2014-07-11 18:18         ` Aravindh Puthiyaparambil (aravindp)
2014-07-11 18:19       ` Andrew Cooper
2014-07-11 18:22         ` Razvan Cojocaru
2014-07-11 18:29           ` Andrew Cooper
2014-07-11 15:43 ` [PATCH RFC V2 4/6] xen: Support for VMCALL mem_events Razvan Cojocaru
2014-07-11 17:23   ` Andrew Cooper
2014-07-11 18:15     ` Razvan Cojocaru
2015-03-17 13:50     ` Razvan Cojocaru
2015-03-17 13:58       ` Jan Beulich
2015-03-17 14:07         ` Razvan Cojocaru
2015-03-17 14:20           ` Jan Beulich
2015-03-17 14:33             ` Razvan Cojocaru
2014-07-11 15:43 ` [PATCH RFC V2 5/6] xen, libxc: Request page fault injection via libxc Razvan Cojocaru
2014-07-11 18:06   ` Andrew Cooper
2014-07-17 11:53     ` Ian Campbell
2014-07-17 12:07       ` Razvan Cojocaru
2014-07-17 12:22     ` Razvan Cojocaru
2014-07-17 12:38       ` Andrew Cooper
2014-07-11 15:43 ` [PATCH RFC V2 6/6] xen: Handle resumed instruction based on previous mem_event reply Razvan Cojocaru
2014-07-11 18:36   ` Andrew Cooper
2014-07-11 18:41     ` Razvan Cojocaru
2014-07-11 19:12       ` Andrew Cooper
2014-07-11 16:23 ` Andrew Cooper [this message]
2014-07-11 18:00   ` [PATCH RFC V2 1/6] xen: Emulate with no writes Razvan Cojocaru
2014-07-14  8:37   ` Razvan Cojocaru

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=53C00F94.5020907@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=mdontu@bitdefender.com \
    --cc=rcojocaru@bitdefender.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 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.