All of lore.kernel.org
 help / color / mirror / Atom feed
From: Razvan Cojocaru <rcojocaru@bitdefender.com>
To: Tamas K Lengyel <tamas.lengyel@zentific.com>,
	xen-devel@lists.xenproject.org
Cc: Kevin Tian <kevin.tian@intel.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Jan Beulich <jbeulich@suse.com>,
	George Dunlap <george.dunlap@eu.citrix.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Julien Grall <julien.grall@arm.com>,
	Paul Durrant <paul.durrant@citrix.com>,
	Jun Nakajima <jun.nakajima@intel.com>
Subject: Re: [PATCH 2/2] x86/vm_event: Allow returning i-cache for emulation
Date: Wed, 14 Sep 2016 10:58:49 +0300	[thread overview]
Message-ID: <7f0354d8-9cb2-82f7-5292-e67ce19d2780@bitdefender.com> (raw)
In-Reply-To: <20160913181223.1459-2-tamas.lengyel@zentific.com>

On 09/13/2016 09:12 PM, Tamas K Lengyel wrote:
> When emulating instructions the emulator maintains a small i-cache fetched
> from the guest memory. This patch extends the vm_event interface to allow
> returning this i-cache via the vm_event response instead.
> 
> When responding to a SOFTWARE_BREAKPOINT event (INT3) the monitor subscriber
> normally has to remove the INT3 from memory - singlestep - place back INT3
> to allow the guest to continue execution. This routine however is susceptible
> to a race-condition on multi-vCPU guests. By allowing the subscriber to return
> the i-cache to be used for emulation it can side-step the problem by returning
> a clean buffer without the INT3 present.
> 
> As part of this patch we rename hvm_mem_access_emulate_one to
> hvm_emulate_one_vm_event to better reflect that it is used in various vm_event
> scenarios now, not just in response to mem_access events.
> 
> Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com>
> ---
> Cc: Paul Durrant <paul.durrant@citrix.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: Jun Nakajima <jun.nakajima@intel.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: George Dunlap <george.dunlap@eu.citrix.com>
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> 
> Note: This patch only has been compile-tested.
> ---
>  xen/arch/x86/hvm/emulate.c        | 44 ++++++++++++++++++++++++++-------------
>  xen/arch/x86/hvm/hvm.c            |  9 +++++---
>  xen/arch/x86/hvm/vmx/vmx.c        |  1 +
>  xen/arch/x86/vm_event.c           |  9 +++++++-
>  xen/common/vm_event.c             |  1 -
>  xen/include/asm-x86/hvm/emulate.h |  8 ++++---
>  xen/include/asm-x86/vm_event.h    |  3 ++-
>  xen/include/public/vm_event.h     | 16 +++++++++++++-
>  8 files changed, 67 insertions(+), 24 deletions(-)
> 
> diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
> index cc25676..504ed35 100644
> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -76,9 +76,9 @@ static int set_context_data(void *buffer, unsigned int size)
>      if ( curr->arch.vm_event )
>      {
>          unsigned int safe_size =
> -            min(size, curr->arch.vm_event->emul_read_data.size);
> +            min(size, curr->arch.vm_event->emul_read.size);
>  
> -        memcpy(buffer, curr->arch.vm_event->emul_read_data.data, safe_size);
> +        memcpy(buffer, curr->arch.vm_event->emul_read.data, safe_size);
>          memset(buffer + safe_size, 0, size - safe_size);
>          return X86EMUL_OKAY;
>      }
> @@ -827,7 +827,7 @@ static int hvmemul_read(
>      struct hvm_emulate_ctxt *hvmemul_ctxt =
>          container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
>  
> -    if ( unlikely(hvmemul_ctxt->set_context) )
> +    if ( unlikely(hvmemul_ctxt->set_context_data) )
>          return set_context_data(p_data, bytes);
>  
>      return __hvmemul_read(
> @@ -1029,7 +1029,7 @@ static int hvmemul_cmpxchg(
>      struct hvm_emulate_ctxt *hvmemul_ctxt =
>          container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
>  
> -    if ( unlikely(hvmemul_ctxt->set_context) )
> +    if ( unlikely(hvmemul_ctxt->set_context_data) )
>      {
>          int rc = set_context_data(p_new, bytes);
>  
> @@ -1122,7 +1122,7 @@ static int hvmemul_rep_outs(
>      p2m_type_t p2mt;
>      int rc;
>  
> -    if ( unlikely(hvmemul_ctxt->set_context) )
> +    if ( unlikely(hvmemul_ctxt->set_context_data) )
>          return hvmemul_rep_outs_set_context(src_seg, src_offset, dst_port,
>                                              bytes_per_rep, reps, ctxt);
>  
> @@ -1264,7 +1264,7 @@ static int hvmemul_rep_movs(
>      if ( buf == NULL )
>          return X86EMUL_UNHANDLEABLE;
>  
> -    if ( unlikely(hvmemul_ctxt->set_context) )
> +    if ( unlikely(hvmemul_ctxt->set_context_data) )
>      {
>          rc = set_context_data(buf, bytes);
>  
> @@ -1470,7 +1470,7 @@ static int hvmemul_read_io(
>  
>      *val = 0;
>  
> -    if ( unlikely(hvmemul_ctxt->set_context) )
> +    if ( unlikely(hvmemul_ctxt->set_context_data) )
>          return set_context_data(val, bytes);
>  
>      return hvmemul_do_pio_buffer(port, bytes, IOREQ_READ, val);
> @@ -1793,7 +1793,14 @@ static int _hvm_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt,
>          pfec |= PFEC_user_mode;
>  
>      hvmemul_ctxt->insn_buf_eip = regs->eip;
> -    if ( !vio->mmio_insn_bytes )
> +
> +    if ( unlikely(hvmemul_ctxt->set_context_insn) && curr->arch.vm_event )
> +    {
> +        hvmemul_ctxt->insn_buf_bytes = sizeof(curr->arch.vm_event->emul_insn);
> +        memcpy(hvmemul_ctxt->insn_buf, &curr->arch.vm_event->emul_insn,
> +               hvmemul_ctxt->insn_buf_bytes);
> +    }
> +    else if ( !vio->mmio_insn_bytes )
>      {
>          hvmemul_ctxt->insn_buf_bytes =
>              hvm_get_insn_bytes(curr, hvmemul_ctxt->insn_buf) ?:
> @@ -1931,7 +1938,7 @@ int hvm_emulate_one_mmio(unsigned long mfn, unsigned long gla)
>      return rc;
>  }
>  
> -void hvm_mem_access_emulate_one(enum emul_kind kind, unsigned int trapnr,
> +void hvm_emulate_one_vm_event(enum emul_kind kind, unsigned int trapnr,
>      unsigned int errcode)
>  {
>      struct hvm_emulate_ctxt ctx = {{ 0 }};
> @@ -1944,11 +1951,19 @@ void hvm_mem_access_emulate_one(enum emul_kind kind, unsigned int trapnr,
>      case EMUL_KIND_NOWRITE:
>          rc = hvm_emulate_one_no_write(&ctx);
>          break;
> -    case EMUL_KIND_SET_CONTEXT:
> -        ctx.set_context = 1;
> -        /* Intentional fall-through. */
> -    default:
> +    case EMUL_KIND_SET_CONTEXT_DATA:
> +        ctx.set_context_data = 1;
> +        rc = hvm_emulate_one(&ctx);
> +        break;
> +    case EMUL_KIND_SET_CONTEXT_INSN:
> +        ctx.set_context_insn = 1;
>          rc = hvm_emulate_one(&ctx);
> +        break;
> +    case EMUL_KIND_NORMAL:
> +        rc = hvm_emulate_one(&ctx);
> +        break;
> +    default:
> +        return;
>      }
>  
>      switch ( rc )
> @@ -1983,7 +1998,8 @@ void hvm_emulate_prepare(
>      hvmemul_ctxt->ctxt.force_writeback = 1;
>      hvmemul_ctxt->seg_reg_accessed = 0;
>      hvmemul_ctxt->seg_reg_dirty = 0;
> -    hvmemul_ctxt->set_context = 0;
> +    hvmemul_ctxt->set_context_data = 0;
> +    hvmemul_ctxt->set_context_insn = 0;
>      hvmemul_get_seg_reg(x86_seg_cs, hvmemul_ctxt);
>      hvmemul_get_seg_reg(x86_seg_ss, hvmemul_ctxt);
>  }
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index ca96643..7462794 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -489,13 +489,16 @@ void hvm_do_resume(struct vcpu *v)
>  
>              if ( v->arch.vm_event->emulate_flags &
>                   VM_EVENT_FLAG_SET_EMUL_READ_DATA )
> -                kind = EMUL_KIND_SET_CONTEXT;
> +                kind = EMUL_KIND_SET_CONTEXT_DATA;
>              else if ( v->arch.vm_event->emulate_flags &
>                        VM_EVENT_FLAG_EMULATE_NOWRITE )
>                  kind = EMUL_KIND_NOWRITE;
> +            else if ( v->arch.vm_event->emulate_flags &
> +                 VM_EVENT_FLAG_SET_EMUL_INSN_DATA )
> +                kind = EMUL_KIND_SET_CONTEXT_INSN;
>  
> -            hvm_mem_access_emulate_one(kind, TRAP_invalid_op,
> -                                       HVM_DELIVER_NO_ERROR_CODE);
> +            hvm_emulate_one_vm_event(kind, TRAP_invalid_op,
> +                                     HVM_DELIVER_NO_ERROR_CODE);
>  
>              v->arch.vm_event->emulate_flags = 0;
>          }
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index 2759e6f..d214716 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -57,6 +57,7 @@
>  #include <asm/altp2m.h>
>  #include <asm/event.h>
>  #include <asm/monitor.h>
> +#include <asm/vm_event.h>
>  #include <public/arch-x86/cpuid.h>
>  
>  static bool_t __initdata opt_force_ept;
> diff --git a/xen/arch/x86/vm_event.c b/xen/arch/x86/vm_event.c
> index 343b9c8..03beed3 100644
> --- a/xen/arch/x86/vm_event.c
> +++ b/xen/arch/x86/vm_event.c
> @@ -209,11 +209,18 @@ void vm_event_emulate_check(struct vcpu *v, vm_event_response_t *rsp)
>          if ( p2m_mem_access_emulate_check(v, rsp) )
>          {
>              if ( rsp->flags & VM_EVENT_FLAG_SET_EMUL_READ_DATA )
> -                v->arch.vm_event->emul_read_data = rsp->data.emul_read_data;
> +                v->arch.vm_event->emul_read = rsp->data.emul.read;
>  
>              v->arch.vm_event->emulate_flags = rsp->flags;
>          }
>          break;
> +    case VM_EVENT_REASON_SOFTWARE_BREAKPOINT:
> +        if ( rsp->flags & VM_EVENT_FLAG_SET_EMUL_INSN_DATA )
> +        {
> +            v->arch.vm_event->emul_insn = rsp->data.emul.insn;
> +            v->arch.vm_event->emulate_flags = rsp->flags;
> +        }
> +        break;
>      default:
>          break;
>      };
> diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
> index 907ab40..d8ee7f3 100644
> --- a/xen/common/vm_event.c
> +++ b/xen/common/vm_event.c
> @@ -398,7 +398,6 @@ void vm_event_resume(struct domain *d, struct vm_event_domain *ved)
>           * In some cases the response type needs extra handling, so here
>           * we call the appropriate handlers.
>           */
> -
>          /* Check flags which apply only when the vCPU is paused */
>          if ( atomic_read(&v->vm_event_pause_count) )
>          {
> diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h
> index 3aabcbe..b52f99e 100644
> --- a/xen/include/asm-x86/hvm/emulate.h
> +++ b/xen/include/asm-x86/hvm/emulate.h
> @@ -34,20 +34,22 @@ struct hvm_emulate_ctxt {
>  
>      uint32_t intr_shadow;
>  
> -    bool_t set_context;
> +    bool_t set_context_data;
> +    bool_t set_context_insn;
>  };
>  
>  enum emul_kind {
>      EMUL_KIND_NORMAL,
>      EMUL_KIND_NOWRITE,
> -    EMUL_KIND_SET_CONTEXT
> +    EMUL_KIND_SET_CONTEXT_DATA,
> +    EMUL_KIND_SET_CONTEXT_INSN

Since this breaks compilation of existing clients, I think we should
increment some macro to alow for compile-time switching (maybe
VM_EVENT_INTERFACE_VERSION?).


Thanks,
Razvan

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2016-09-14  7:58 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-13 18:12 [PATCH 1/2] vm_event: Sanitize vm_event response handling Tamas K Lengyel
2016-09-13 18:12 ` [PATCH 2/2] x86/vm_event: Allow returning i-cache for emulation Tamas K Lengyel
2016-09-14  7:58   ` Razvan Cojocaru [this message]
2016-09-15 16:36     ` Tamas K Lengyel
2016-09-15 17:08       ` Razvan Cojocaru
2016-09-16  7:21         ` Razvan Cojocaru
2016-09-16 15:37           ` Tamas K Lengyel
2016-09-16 16:09             ` Razvan Cojocaru
2016-09-14 15:55   ` Jan Beulich
2016-09-14 16:20     ` Tamas K Lengyel
2016-09-15  5:58       ` Jan Beulich
2016-09-15 15:27         ` Tamas K Lengyel
2016-09-15 16:09           ` Jan Beulich
2016-09-14  7:49 ` [PATCH 1/2] vm_event: Sanitize vm_event response handling Razvan Cojocaru
2016-09-14  9:33 ` Julien Grall
2016-09-14 15:14   ` Tamas K Lengyel
2016-09-14 15:15     ` Julien Grall
2016-09-14 15:19       ` Tamas K Lengyel
2016-09-14 13:38 ` George Dunlap
2016-09-14 15:11   ` Tamas K Lengyel
2016-09-15 10:35     ` George Dunlap

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=7f0354d8-9cb2-82f7-5292-e67ce19d2780@bitdefender.com \
    --to=rcojocaru@bitdefender.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=george.dunlap@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=julien.grall@arm.com \
    --cc=jun.nakajima@intel.com \
    --cc=kevin.tian@intel.com \
    --cc=paul.durrant@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=tamas.lengyel@zentific.com \
    --cc=xen-devel@lists.xenproject.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.