[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH RFC V2 4/6] xen: Support for VMCALL mem_events



On 11/07/14 16:43, Razvan Cojocaru wrote:
> Added support for VMCALL events (the memory introspection library
> will have the guest trigger VMCALLs, which will then be sent along
> via the mem_event mechanism).
>
> Changes since V1:
>  - Added a #define and an comment explaining a previous magic
>    constant.
>  - Had MEM_EVENT_REASON_VMCALL explicitly not honour
>    HVMPME_onchangeonly.
>
> Signed-off-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>
> ---
>  xen/arch/x86/hvm/hvm.c          |    9 +++++++++
>  xen/arch/x86/hvm/vmx/vmx.c      |   18 +++++++++++++++++-
>  xen/include/asm-x86/hvm/hvm.h   |    1 +
>  xen/include/public/hvm/params.h |    4 +++-
>  xen/include/public/mem_event.h  |    5 +++++
>  5 files changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 89a0382..6e86d7c 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -5564,6 +5564,7 @@ long do_hvm_op(unsigned long op, 
> XEN_GUEST_HANDLE_PARAM(void) arg)
>              case HVM_PARAM_MEMORY_EVENT_INT3:
>              case HVM_PARAM_MEMORY_EVENT_SINGLE_STEP:
>              case HVM_PARAM_MEMORY_EVENT_MSR:
> +            case HVM_PARAM_MEMORY_EVENT_VMCALL:
>                  if ( d == current->domain )
>                  {
>                      rc = -EPERM;
> @@ -6199,6 +6200,14 @@ void hvm_memory_event_msr(unsigned long msr, unsigned 
> long value)
>                             value, ~value, 1, msr);
>  }
>  
> +void hvm_memory_event_vmcall(unsigned long rip, unsigned long eax)
> +{
> +    hvm_memory_event_traps(current->domain->arch.hvm_domain
> +                             .params[HVM_PARAM_MEMORY_EVENT_VMCALL],
> +                           MEM_EVENT_REASON_VMCALL,
> +                           rip, ~rip, 1, eax);
> +}
> +
>  int hvm_memory_event_int3(unsigned long gla) 
>  {
>      uint32_t pfec = PFEC_page_present;
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index 2caa04a..6c63225 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -2879,8 +2879,24 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
>      case EXIT_REASON_VMCALL:
>      {
>          int rc;
> +        unsigned long eax = regs->eax;
> +
>          HVMTRACE_1D(VMMCALL, regs->eax);
> -        rc = hvm_do_hypercall(regs);
> +
> +        /* Don't send a VMCALL mem_event unless something
> +         * caused the guests's eax register to contain the
> +         * VMCALL_EVENT_REQUEST constant. */
> +        if ( regs->eax != VMCALL_EVENT_REQUEST )
> +        {
> +            rc = hvm_do_hypercall(regs);
> +        }
> +        else
> +        {
> +            hvm_memory_event_vmcall(guest_cpu_user_regs()->eip, eax);
> +            update_guest_eip();
> +            break;
> +        }

Thinking more about this, it is really a hypercall pretending not to
be.  It would be better to introduce a real HVMOP_send_mem_event.

From the point of view of your in-guest agent, it would be a vmcall with
rax = 34 (hvmop) rdi = $N (send_mem_event subop) rsi = data or pointer
to struct containing data, depending on how exactly you implement the
hypercall.

You would have the bonus of being able to detect errors, e.g. -ENOENT
for "mem_event not active", get SVM support for free, and not need magic
numbers, or vendor specific terms like "vmcall" finding their way into
the Xen public API.

> +
>          if ( rc != HVM_HCALL_preempted )
>          {
>              update_guest_eip(); /* Safe: VMCALL */
> diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
> index 0ebd478..3c0af30 100644
> --- a/xen/include/asm-x86/hvm/hvm.h
> +++ b/xen/include/asm-x86/hvm/hvm.h
> @@ -475,6 +475,7 @@ void hvm_memory_event_cr0(unsigned long value, unsigned 
> long old);
>  void hvm_memory_event_cr3(unsigned long value, unsigned long old);
>  void hvm_memory_event_cr4(unsigned long value, unsigned long old);
>  void hvm_memory_event_msr(unsigned long msr, unsigned long value);
> +void hvm_memory_event_vmcall(unsigned long rip, unsigned long eax);
>  /* Called for current VCPU on int3: returns -1 if no listener */
>  int hvm_memory_event_int3(unsigned long gla);
>  
> diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
> index 614ff5f..d8f89b5 100644
> --- a/xen/include/public/hvm/params.h
> +++ b/xen/include/public/hvm/params.h
> @@ -151,6 +151,8 @@
>  /* Location of the VM Generation ID in guest physical address space. */
>  #define HVM_PARAM_VM_GENERATION_ID_ADDR 34
>  
> -#define HVM_NR_PARAMS          35
> +#define HVM_PARAM_MEMORY_EVENT_VMCALL 35

What is this hvmparam actually used for?  This patch only reads it, and
as indicated previously, it is readwrite to the guest which likely
breaks any assumptions you have about the trustworthness of the value
found there.

~Andrew

> +
> +#define HVM_NR_PARAMS          36
>  
>  #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
> diff --git a/xen/include/public/mem_event.h b/xen/include/public/mem_event.h
> index b9af728..7a59083 100644
> --- a/xen/include/public/mem_event.h
> +++ b/xen/include/public/mem_event.h
> @@ -47,6 +47,11 @@
>  #define MEM_EVENT_REASON_SINGLESTEP  6    /* single step was invoked: 
> gla/gfn are RIP */
>  #define MEM_EVENT_REASON_MSR         7    /* MSR was hit: gfn is MSR value, 
> gla is MSR address;
>                                               does NOT honour 
> HVMPME_onchangeonly */
> +#define MEM_EVENT_REASON_VMCALL      8    /* VMCALL: gfn is RIP, gla is EAX;
> +                                             does NOT honour 
> HVMPME_onchangeonly */
> +
> +/* VMCALL mem_events will only be sent when the guest's EAX holds this 
> value. */
> +#define VMCALL_EVENT_REQUEST 0x494E5452 /* 'INTR' */
>  
>  /* Using a custom struct (not hvm_hw_cpu) so as to not fill
>   * the mem_event ring buffer too quickly. */


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.