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

Re: [Xen-devel] [RFC PATCH V3 10/12] xen: Introduce monitor_op domctl



> From: Tamas K Lengyel [mailto:tamas.lengyel@xxxxxxxxxxxx]
> Sent: Friday, January 30, 2015 5:47 AM
> 
> In preparation for allowing for introspecting ARM and PV domains the old
> control interface via the hvm_op hypercall is retired. A new control
> mechanism
> is introduced via the domctl hypercall: monitor_op.
> 
> This patch aims to establish a base API on which future applications can build
> on.
> 
> Suggested-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> Signed-off-by: Tamas K Lengyel <tamas.lengyel@xxxxxxxxxxxx>

for VMX changes: 
Acked-by: Kevin Tian <kevin.tian@xxxxxxxxx> 

> ---
>  tools/libxc/Makefile                |   1 +
>  tools/libxc/include/xenctrl.h       |  19 ++++
>  tools/libxc/xc_mem_access.c         |   9 +-
>  tools/libxc/xc_monitor.c            | 118 +++++++++++++++++++++
>  tools/libxc/xc_private.h            |   2 +-
>  tools/libxc/xc_vm_event.c           |   7 +-
>  tools/tests/xen-access/xen-access.c |  14 +--
>  xen/arch/x86/Makefile               |   1 +
>  xen/arch/x86/hvm/event.c            |  41 ++------
>  xen/arch/x86/hvm/hvm.c              |  38 +------
>  xen/arch/x86/hvm/vmx/vmcs.c         |   4 +-
>  xen/arch/x86/hvm/vmx/vmx.c          |   2 +-
>  xen/arch/x86/mm/p2m.c               |   9 --
>  xen/arch/x86/monitor.c              | 197
> ++++++++++++++++++++++++++++++++++++
>  xen/common/domctl.c                 |  11 ++
>  xen/common/vm_event.c               |   7 --
>  xen/include/asm-arm/monitor.h       |  13 +++
>  xen/include/asm-x86/domain.h        |  45 ++++++++
>  xen/include/asm-x86/monitor.h       |   9 ++
>  xen/include/public/domctl.h         |  55 +++++++++-
>  xen/include/public/hvm/params.h     |  15 ---
>  xen/include/public/vm_event.h       |   2 +-
>  22 files changed, 495 insertions(+), 124 deletions(-)
>  create mode 100644 tools/libxc/xc_monitor.c
>  create mode 100644 xen/arch/x86/monitor.c
>  create mode 100644 xen/include/asm-arm/monitor.h
>  create mode 100644 xen/include/asm-x86/monitor.h
> 
> diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
> index 6ef17ec..2d79e7c 100644
> --- a/tools/libxc/Makefile
> +++ b/tools/libxc/Makefile
> @@ -27,6 +27,7 @@ CTRL_SRCS-y       += xc_cpu_hotplug.c
>  CTRL_SRCS-y       += xc_resume.c
>  CTRL_SRCS-y       += xc_tmem.c
>  CTRL_SRCS-y       += xc_vm_event.c
> +CTRL_SRCS-y       += xc_monitor.c
>  CTRL_SRCS-y       += xc_mem_paging.c
>  CTRL_SRCS-y       += xc_mem_access.c
>  CTRL_SRCS-y       += xc_memshr.c
> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> index 0ad8b8d..6428365 100644
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -2308,6 +2308,25 @@ int xc_get_mem_access(xc_interface *xch,
> domid_t domain_id,
>                        uint64_t pfn, xenmem_access_t *access);
> 
>  /***
> + * Monitor control operations.
> + */
> +int xc_monitor_mov_to_cr0(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op, unsigned int sync,
> +                          unsigned int onchangeonly);
> +int xc_monitor_mov_to_cr3(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op, unsigned int sync,
> +                          unsigned int onchangeonly);
> +int xc_monitor_mov_to_cr4(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op, unsigned int sync,
> +                          unsigned int onchangeonly);
> +int xc_monitor_mov_to_msr(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op, unsigned int
> extended_capture);
> +int xc_monitor_singlestep(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op);
> +int xc_monitor_software_breakpoint(xc_interface *xch, domid_t domain_id,
> +                                   unsigned int op);
> +
> +/***
>   * Memory sharing operations.
>   *
>   * Unles otherwise noted, these calls return 0 on succes, -1 and errno on
> diff --git a/tools/libxc/xc_mem_access.c b/tools/libxc/xc_mem_access.c
> index aa6e777..70cc8d0 100644
> --- a/tools/libxc/xc_mem_access.c
> +++ b/tools/libxc/xc_mem_access.c
> @@ -27,14 +27,7 @@
>  void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id,
> uint32_t *port)
>  {
>      return xc_vm_event_enable(xch, domain_id,
> HVM_PARAM_MONITOR_RING_PFN,
> -                              port, 0);
> -}
> -
> -void *xc_mem_access_enable_introspection(xc_interface *xch, domid_t
> domain_id,
> -                                         uint32_t *port)
> -{
> -    return xc_vm_event_enable(xch, domain_id,
> HVM_PARAM_MONITOR_RING_PFN,
> -                              port, 1);
> +                              port);
>  }
> 
>  int xc_mem_access_disable(xc_interface *xch, domid_t domain_id)
> diff --git a/tools/libxc/xc_monitor.c b/tools/libxc/xc_monitor.c
> new file mode 100644
> index 0000000..ee5a37b
> --- /dev/null
> +++ b/tools/libxc/xc_monitor.c
> @@ -0,0 +1,118 @@
> +/**************************************************************
> ****************
> + *
> + * xc_monitor.c
> + *
> + * Interface to VM event monitor
> + *
> + * Copyright (c) 2015 Tamas K Lengyel (tamas@xxxxxxxxxxxxx)
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library 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
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
> USA
> + */
> +
> +#include "xc_private.h"
> +
> +int xc_monitor_mov_to_cr0(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op, unsigned int sync,
> +                          unsigned int onchangeonly)
> +{
> +    DECLARE_DOMCTL;
> +
> +    domctl.cmd = XEN_DOMCTL_monitor_op;
> +    domctl.domain = domain_id;
> +    domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
> +                                :
> XEN_DOMCTL_MONITOR_OP_DISABLE;
> +    domctl.u.monitor_op.subop =
> XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR0;
> +    domctl.u.monitor_op.options.mov_to_cr0.sync = sync;
> +    domctl.u.monitor_op.options.mov_to_cr0.onchangeonly =
> onchangeonly;
> +
> +    return do_domctl(xch, &domctl);
> +}
> +
> +int xc_monitor_mov_to_cr3(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op, unsigned int sync,
> +                          unsigned int onchangeonly)
> +{
> +    DECLARE_DOMCTL;
> +
> +    domctl.cmd = XEN_DOMCTL_monitor_op;
> +    domctl.domain = domain_id;
> +    domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
> +                                :
> XEN_DOMCTL_MONITOR_OP_DISABLE;
> +    domctl.u.monitor_op.subop =
> XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR3;
> +    domctl.u.monitor_op.options.mov_to_cr3.sync = sync;
> +    domctl.u.monitor_op.options.mov_to_cr3.onchangeonly =
> onchangeonly;
> +
> +    return do_domctl(xch, &domctl);
> +}
> +
> +int xc_monitor_mov_to_cr4(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op, unsigned int sync,
> +                          unsigned int onchangeonly)
> +{
> +    DECLARE_DOMCTL;
> +
> +    domctl.cmd = XEN_DOMCTL_monitor_op;
> +    domctl.domain = domain_id;
> +    domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
> +                                :
> XEN_DOMCTL_MONITOR_OP_DISABLE;
> +    domctl.u.monitor_op.subop =
> XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR4;
> +    domctl.u.monitor_op.options.mov_to_cr4.sync = sync;
> +    domctl.u.monitor_op.options.mov_to_cr4.onchangeonly =
> onchangeonly;
> +
> +    return do_domctl(xch, &domctl);
> +}
> +
> +int xc_monitor_mov_to_msr(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op, unsigned int
> extended_capture)
> +{
> +    DECLARE_DOMCTL;
> +
> +    domctl.cmd = XEN_DOMCTL_monitor_op;
> +    domctl.domain = domain_id;
> +    domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
> +                                :
> XEN_DOMCTL_MONITOR_OP_DISABLE;
> +    domctl.u.monitor_op.subop =
> XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_MSR;
> +    domctl.u.monitor_op.options.mov_to_msr.extended_capture =
> extended_capture;
> +
> +    return do_domctl(xch, &domctl);
> +}
> +
> +int xc_monitor_software_breakpoint(xc_interface *xch, domid_t domain_id,
> +                                   unsigned int op)
> +{
> +    DECLARE_DOMCTL;
> +
> +    domctl.cmd = XEN_DOMCTL_monitor_op;
> +    domctl.domain = domain_id;
> +    domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
> +                                :
> XEN_DOMCTL_MONITOR_OP_DISABLE;
> +    domctl.u.monitor_op.subop =
> XEN_DOMCTL_MONITOR_SUBOP_SOFTWARE_BREAKPOINT;
> +
> +    return do_domctl(xch, &domctl);
> +}
> +
> +int xc_monitor_singlestep(xc_interface *xch, domid_t domain_id,
> +                          unsigned int op)
> +{
> +    DECLARE_DOMCTL;
> +
> +    domctl.cmd = XEN_DOMCTL_monitor_op;
> +    domctl.domain = domain_id;
> +    domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
> +                                :
> XEN_DOMCTL_MONITOR_OP_DISABLE;
> +    domctl.u.monitor_op.subop =
> XEN_DOMCTL_MONITOR_SUBOP_SINGLESTEP;
> +
> +    return do_domctl(xch, &domctl);
> +}
> diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
> index 843540c..9f55309 100644
> --- a/tools/libxc/xc_private.h
> +++ b/tools/libxc/xc_private.h
> @@ -430,6 +430,6 @@ int xc_vm_event_control(xc_interface *xch, domid_t
> domain_id, unsigned int op,
>   * param can be HVM_PARAM_PAGING/ACCESS/SHARING_RING_PFN
>   */
>  void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int
> param,
> -                         uint32_t *port, int enable_introspection);
> +                         uint32_t *port);
> 
>  #endif /* __XC_PRIVATE_H__ */
> diff --git a/tools/libxc/xc_vm_event.c b/tools/libxc/xc_vm_event.c
> index bd14c9d..12d2169 100644
> --- a/tools/libxc/xc_vm_event.c
> +++ b/tools/libxc/xc_vm_event.c
> @@ -41,7 +41,7 @@ int xc_vm_event_control(xc_interface *xch, domid_t
> domain_id, unsigned int op,
>  }
> 
>  void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int
> param,
> -                          uint32_t *port, int enable_introspection)
> +                          uint32_t *port)
>  {
>      void *ring_page = NULL;
>      uint64_t pfn;
> @@ -104,10 +104,7 @@ void *xc_vm_event_enable(xc_interface *xch,
> domid_t domain_id, int param,
>          break;
> 
>      case HVM_PARAM_MONITOR_RING_PFN:
> -        if ( enable_introspection )
> -            op =
> XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE_INTROSPECTION;
> -        else
> -            op = XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE;
> +        op = XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE;
>          mode = XEN_DOMCTL_VM_EVENT_OP_MONITOR;
>          break;
> 
> diff --git a/tools/tests/xen-access/xen-access.c
> b/tools/tests/xen-access/xen-access.c
> index c9aaed4..5411eab 100644
> --- a/tools/tests/xen-access/xen-access.c
> +++ b/tools/tests/xen-access/xen-access.c
> @@ -447,13 +447,13 @@ int main(int argc, char *argv[])
>      }
> 
>      if ( int3 )
> -        rc = xc_hvm_param_set(xch, domain_id,
> HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_sync);
> -    else
> -        rc = xc_hvm_param_set(xch, domain_id,
> HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
> -    if ( rc < 0 )
>      {
> -        ERROR("Error %d setting int3 vm_event\n", rc);
> -        goto exit;
> +        rc = xc_monitor_software_breakpoint(xch, domain_id, 1);
> +        if ( rc < 0 )
> +        {
> +            ERROR("Error %d setting int3 vm_event\n", rc);
> +            goto exit;
> +        }
>      }
> 
>      /* Wait for access */
> @@ -467,7 +467,7 @@ int main(int argc, char *argv[])
>              rc = xc_set_mem_access(xch, domain_id,
> XENMEM_access_rwx, ~0ull, 0);
>              rc = xc_set_mem_access(xch, domain_id,
> XENMEM_access_rwx, 0,
> 
> xenaccess->domain_info->max_pages);
> -            rc = xc_hvm_param_set(xch, domain_id,
> HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
> +            rc = xc_monitor_software_breakpoint(xch, domain_id, 0);
> 
>              shutting_down = 1;
>          }
> diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
> index 86ca5f8..37e547c 100644
> --- a/xen/arch/x86/Makefile
> +++ b/xen/arch/x86/Makefile
> @@ -36,6 +36,7 @@ obj-y += microcode_intel.o
>  # This must come after the vendor specific files.
>  obj-y += microcode.o
>  obj-y += mm.o
> +obj-y += monitor.o
>  obj-y += mpparse.o
>  obj-y += nmi.o
>  obj-y += numa.o
> diff --git a/xen/arch/x86/hvm/event.c b/xen/arch/x86/hvm/event.c
> index 65f80a7..34975b4 100644
> --- a/xen/arch/x86/hvm/event.c
> +++ b/xen/arch/x86/hvm/event.c
> @@ -55,15 +55,12 @@ static void hvm_event_fill_regs(vm_event_request_t
> *req)
>      req->regs.x86.cr4 = curr->arch.hvm_vcpu.guest_cr[4];
>  }
> 
> -static int hvm_event_traps(long parameters, vm_event_request_t *req)
> +static int hvm_event_traps(uint8_t sync, vm_event_request_t *req)
>  {
>      int rc;
>      struct vcpu *curr = current;
>      struct domain *currd = curr->domain;
> 
> -    if ( !(parameters & HVMPME_MODE_MASK) )
> -        return 0;
> -
>      rc = vm_event_claim_slot(currd, &currd->vm_event->monitor);
>      if ( rc == -ENOSYS )
>      {
> @@ -74,7 +71,7 @@ static int hvm_event_traps(long parameters,
> vm_event_request_t *req)
>      else if ( rc < 0 )
>          return rc;
> 
> -    if ( (parameters & HVMPME_MODE_MASK) == HVMPME_mode_sync )
> +    if ( sync )
>      {
>          req->flags |= VM_EVENT_FLAG_VCPU_PAUSED;
>          vm_event_vcpu_pause(curr);
> @@ -97,12 +94,10 @@ void hvm_event_cr0(unsigned long value, unsigned
> long old)
>          .data.mov_to_cr.old_value = old
>      };
> 
> -    long params =
> currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_CR0];
> -
> -    if ( (params & HVMPME_onchangeonly) && (value == old) )
> +    if ( currd->arch.monitor_options.mov_to_cr0.onchangeonly && value ==
> old )
>          return;
> 
> -    hvm_event_traps(params, &req);
> +    hvm_event_traps(currd->arch.monitor_options.mov_to_cr0.sync, &req);
>  }
> 
>  void hvm_event_cr3(unsigned long value, unsigned long old)
> @@ -116,12 +111,10 @@ void hvm_event_cr3(unsigned long value, unsigned
> long old)
>          .data.mov_to_cr.old_value = old
>      };
> 
> -    long params =
> currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_CR3];
> -
> -    if ( (params & HVMPME_onchangeonly) && (value == old) )
> +    if ( currd->arch.monitor_options.mov_to_cr3.onchangeonly && value ==
> old )
>          return;
> 
> -    hvm_event_traps(params, &req);
> +    hvm_event_traps(currd->arch.monitor_options.mov_to_cr3.sync, &req);
>  }
> 
>  void hvm_event_cr4(unsigned long value, unsigned long old)
> @@ -135,18 +128,15 @@ void hvm_event_cr4(unsigned long value, unsigned
> long old)
>          .data.mov_to_cr.old_value = old
>      };
> 
> -    long params =
> currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_CR4];
> -
> -    if ( (params & HVMPME_onchangeonly) && (value == old) )
> +    if ( currd->arch.monitor_options.mov_to_cr4.onchangeonly && value ==
> old )
>          return;
> 
> -    hvm_event_traps(params, &req);
> +    hvm_event_traps(currd->arch.monitor_options.mov_to_cr3.sync, &req);
>  }
> 
>  void hvm_event_msr(unsigned long msr, unsigned long value)
>  {
>      struct vcpu *curr = current;
> -    struct domain *currd = curr->domain;
>      vm_event_request_t req = {
>          .reason = VM_EVENT_REASON_MOV_TO_MSR,
>          .vcpu_id = curr->vcpu_id,
> @@ -154,42 +144,33 @@ void hvm_event_msr(unsigned long msr, unsigned
> long value)
>          .data.mov_to_msr.value = value,
>      };
> 
> -    long params =
> currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_MSR];
> -
> -    hvm_event_traps(params, &req);
> +    hvm_event_traps(1, &req);
>  }
> 
>  int hvm_event_int3(unsigned long gla)
>  {
>      uint32_t pfec = PFEC_page_present;
>      struct vcpu *curr = current;
> -    struct domain *currd = curr->domain;
>      vm_event_request_t req = {
>          .reason = VM_EVENT_REASON_SOFTWARE_BREAKPOINT,
>          .vcpu_id = curr->vcpu_id,
>          .data.software_breakpoint.gfn = paging_gva_to_gfn(curr, gla,
> &pfec)
>      };
> 
> -    long params =
> currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_INT3];
> -
> -    return hvm_event_traps(params, &req);
> +    return hvm_event_traps(1, &req);
>  }
> 
>  int hvm_event_single_step(unsigned long gla)
>  {
>      uint32_t pfec = PFEC_page_present;
>      struct vcpu *curr = current;
> -    struct domain *currd = curr->domain;
>      vm_event_request_t req = {
>          .reason = VM_EVENT_REASON_SINGLESTEP,
>          .vcpu_id = curr->vcpu_id,
>          .data.singlestep.gfn = paging_gva_to_gfn(curr, gla, &pfec)
>      };
> 
> -    long params = currd->arch.hvm_domain
> -                    .params[HVM_PARAM_MEMORY_EVENT_SINGLE_ST
> EP];
> -
> -    return hvm_event_traps(params, &req);
> +    return hvm_event_traps(1, &req);
>  }
> 
>  /*
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 97f769a..0baeee3 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -5727,23 +5727,6 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
>              case HVM_PARAM_ACPI_IOPORTS_LOCATION:
>                  rc = pmtimer_change_ioport(d, a.value);
>                  break;
> -            case HVM_PARAM_MEMORY_EVENT_CR0:
> -            case HVM_PARAM_MEMORY_EVENT_CR3:
> -            case HVM_PARAM_MEMORY_EVENT_CR4:
> -                if ( d == current->domain )
> -                    rc = -EPERM;
> -                break;
> -            case HVM_PARAM_MEMORY_EVENT_INT3:
> -            case HVM_PARAM_MEMORY_EVENT_SINGLE_STEP:
> -            case HVM_PARAM_MEMORY_EVENT_MSR:
> -                if ( d == current->domain )
> -                {
> -                    rc = -EPERM;
> -                    break;
> -                }
> -                if ( a.value & HVMPME_onchangeonly )
> -                    rc = -EINVAL;
> -                break;
>              case HVM_PARAM_NESTEDHVM:
>                  rc = xsm_hvm_param_nested(XSM_PRIV, d);
>                  if ( rc )
> @@ -5802,29 +5785,10 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
>              }
>              }
> 
> -            if ( rc == 0 )
> +            if ( rc == 0 )
>              {
>                  d->arch.hvm_domain.params[a.index] = a.value;
> -
> -                switch( a.index )
> -                {
> -                case HVM_PARAM_MEMORY_EVENT_INT3:
> -                case HVM_PARAM_MEMORY_EVENT_SINGLE_STEP:
> -                {
> -                    domain_pause(d);
> -                    domain_unpause(d); /* Causes guest to latch new
> status */
> -                    break;
> -                }
> -                case HVM_PARAM_MEMORY_EVENT_CR3:
> -                {
> -                    for_each_vcpu ( d, v )
> -                        hvm_funcs.update_guest_cr(v, 0); /* Latches
> new CR3 mask through CR0 code */
> -                    break;
> -                }
> -                }
> -
>              }
> -
>          }
>          else
>          {
> diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
> index 0f2b2e6..9787f3f 100644
> --- a/xen/arch/x86/hvm/vmx/vmcs.c
> +++ b/xen/arch/x86/hvm/vmx/vmcs.c
> @@ -1375,8 +1375,8 @@ void vmx_do_resume(struct vcpu *v)
>      }
> 
>      debug_state = v->domain->debugger_attached
> -                  ||
> v->domain->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_INT3]
> -                  ||
> v->domain->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_SING
> LE_STEP];
> +                  ||
> v->domain->arch.monitor_options.software_breakpoint.enabled
> +                  ||
> v->domain->arch.monitor_options.singlestep.enabled;
> 
>      if ( unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) )
>      {
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index c5e6771..ce3dcbd 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -1232,7 +1232,7 @@ static void vmx_update_guest_cr(struct vcpu *v,
> unsigned int cr)
>                  v->arch.hvm_vmx.exec_control |= cr3_ctls;
> 
>              /* Trap CR3 updates if CR3 memory events are enabled. */
> -            if
> ( v->domain->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_CR3
> ] )
> +            if ( v->domain->arch.monitor_options.mov_to_cr3.enabled )
>                  v->arch.hvm_vmx.exec_control |=
> CPU_BASED_CR3_LOAD_EXITING;
> 
>              vmx_update_cpu_exec_control(v);
> diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
> index c7a0bde..3b58700 100644
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -1445,15 +1445,6 @@ void p2m_vm_event_emulate_check(struct vcpu
> *v, const vm_event_response_t *rsp)
>      }
>  }
> 
> -void p2m_setup_introspection(struct domain *d)
> -{
> -    if ( hvm_funcs.enable_msr_exit_interception )
> -    {
> -        d->arch.hvm_domain.introspection_enabled = 1;
> -        hvm_funcs.enable_msr_exit_interception(d);
> -    }
> -}
> -
>  bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla,
>                              struct npfec npfec,
>                              vm_event_request_t **req_ptr)
> diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c
> new file mode 100644
> index 0000000..c172aaf
> --- /dev/null
> +++ b/xen/arch/x86/monitor.c
> @@ -0,0 +1,197 @@
> +/*
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License v2 as published by the Free Software Foundation.
> + *
> + * This program 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.
> + *
> + * You should have received a copy of the GNU General Public
> + * License along with this program; if not, write to the
> + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> + * Boston, MA 021110-1307, USA.
> + */
> +
> +#include <xen/config.h>
> +#include <xen/sched.h>
> +#include <xen/mm.h>
> +#include <asm/domain.h>
> +
> +#define DISABLE_OPTION(option)          \
> +    if ( !option->enabled )             \
> +        return -EFAULT;                 \
> +    memset(option, 0, sizeof(*option))
> +
> +int monitor_domctl(struct xen_domctl_monitor_op *domctl, struct domain
> *d)
> +{
> +    /*
> +     * At the moment only HVM domains are supported. However, event
> delivery
> +     * could be extended to PV domains. See comments below.
> +     */
> +    if ( !is_hvm_domain(d) )
> +        return -ENOSYS;
> +
> +    if ( domctl->op != XEN_DOMCTL_MONITOR_OP_ENABLE &&
> +         domctl->op != XEN_DOMCTL_MONITOR_OP_DISABLE )
> +        return -EFAULT;
> +
> +    switch ( domctl->subop )
> +    {
> +    case XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR0:
> +    {
> +        /* Note: could be supported on PV domains. */
> +        struct mov_to_cr0 *options =
> &d->arch.monitor_options.mov_to_cr0;
> +
> +        if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
> +        {
> +            if ( options->enabled )
> +                return -EBUSY;
> +
> +            options->enabled = 1;
> +            options->sync = domctl->options.mov_to_cr0.sync;
> +            options->onchangeonly =
> domctl->options.mov_to_cr0.onchangeonly;
> +        }
> +        else
> +        {
> +            DISABLE_OPTION(options);
> +        }
> +        break;
> +    }
> +    case XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR3:
> +    {
> +        /* Note: could be supported on PV domains. */
> +        struct vcpu *v;
> +        struct mov_to_cr3 *options =
> &d->arch.monitor_options.mov_to_cr3;
> +
> +        if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
> +        {
> +            if ( options->enabled )
> +                return -EBUSY;
> +
> +            options->enabled = 1;
> +            options->sync = domctl->options.mov_to_cr3.sync;
> +            options->onchangeonly =
> domctl->options.mov_to_cr3.onchangeonly;
> +        }
> +        else
> +        {
> +            DISABLE_OPTION(options);
> +        }
> +
> +        /* Latches new CR3 mask through CR0 code */
> +        for_each_vcpu ( d, v )
> +            hvm_funcs.update_guest_cr(v, 0);
> +        break;
> +    }
> +
> +    case XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR4:
> +    {
> +        /* Note: could be supported on PV domains. */
> +        struct mov_to_cr4 *options =
> &d->arch.monitor_options.mov_to_cr4;
> +
> +        if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
> +        {
> +            if ( options->enabled )
> +                return -EBUSY;
> +
> +            options->enabled = 1;
> +            options->sync = domctl->options.mov_to_cr4.sync;
> +            options->onchangeonly =
> domctl->options.mov_to_cr4.onchangeonly;
> +        }
> +        else
> +        {
> +            DISABLE_OPTION(options);
> +        }
> +        break;
> +    }
> +    case XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_MSR:
> +    {
> +        struct mov_to_msr *options =
> &d->arch.monitor_options.mov_to_msr;
> +
> +        if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
> +        {
> +            if ( options->enabled )
> +                return -EBUSY;
> +
> +            options->enabled = 1;
> +
> +            if ( domctl->options.mov_to_msr.extended_capture )
> +            {
> +                if ( hvm_funcs.enable_msr_exit_interception )
> +                {
> +                    options->extended_capture = 1;
> +                    hvm_funcs.enable_msr_exit_interception(d);
> +                }
> +                else
> +                {
> +                    return -ENOSYS;
> +                }
> +            }
> +        }
> +        else
> +        {
> +            DISABLE_OPTION(options);
> +        }
> +
> +        break;
> +    }
> +    case XEN_DOMCTL_MONITOR_SUBOP_SINGLESTEP:
> +    {
> +        struct singlestep *options = &d->arch.monitor_options.singlestep;
> +
> +        if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
> +        {
> +            if ( options->enabled )
> +                return -EBUSY;
> +
> +            options->enabled = 1;
> +        }
> +        else
> +        {
> +            DISABLE_OPTION(options);
> +        }
> +
> +        /* Causes guest to latch new status */
> +        domain_pause(d);
> +        domain_unpause(d);
> +        break;
> +    }
> +    case XEN_DOMCTL_MONITOR_SUBOP_SOFTWARE_BREAKPOINT:
> +    {
> +        struct software_breakpoint *options =
> +            &d->arch.monitor_options.software_breakpoint;
> +
> +        if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
> +        {
> +            if ( options->enabled )
> +                return -EBUSY;
> +
> +            options->enabled = 1;
> +        }
> +        else
> +        {
> +            DISABLE_OPTION(options);
> +        }
> +
> +        domain_pause(d);
> +        domain_unpause(d); /* Causes guest to latch new status */
> +        break;
> +    }
> +
> +    default:
> +        return -EFAULT;
> +
> +    };
> +
> +    return 0;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/common/domctl.c b/xen/common/domctl.c
> index 44d45d1..98c2dc6 100644
> --- a/xen/common/domctl.c
> +++ b/xen/common/domctl.c
> @@ -29,6 +29,7 @@
>  #include <asm/irq.h>
>  #include <asm/page.h>
>  #include <asm/p2m.h>
> +#include <asm/monitor.h>
>  #include <public/domctl.h>
>  #include <xsm/xsm.h>
> 
> @@ -1179,6 +1180,16 @@ long
> do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>      }
>      break;
> 
> +    case XEN_DOMCTL_monitor_op:
> +    {
> +        ret = -EPERM;
> +        if ( current->domain == d )
> +            break;
> +
> +        ret = monitor_domctl(&op->u.monitor_op, d);
> +    }
> +    break;
> +
>      default:
>          ret = arch_do_domctl(op, d, u_domctl);
>          break;
> diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
> index 0db899e..0b30750 100644
> --- a/xen/common/vm_event.c
> +++ b/xen/common/vm_event.c
> @@ -617,16 +617,10 @@ int vm_event_domctl(struct domain *d,
> xen_domctl_vm_event_op_t *vec,
>          switch( vec->op )
>          {
>          case XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE:
> -        case
> XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE_INTROSPECTION:
>          {
>              rc = vm_event_enable(d, vec, ved, _VPF_mem_access,
> 
> HVM_PARAM_MONITOR_RING_PFN,
>                                      mem_access_notification);
> -
> -            if ( vec->op ==
> XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE_INTROSPECTION
> -                 && !rc )
> -                p2m_setup_introspection(d);
> -
>          }
>          break;
> 
> @@ -635,7 +629,6 @@ int vm_event_domctl(struct domain *d,
> xen_domctl_vm_event_op_t *vec,
>              if ( ved->ring_page )
>              {
>                  rc = vm_event_disable(d, ved);
> -                d->arch.hvm_domain.introspection_enabled = 0;
>              }
>          }
>          break;
> diff --git a/xen/include/asm-arm/monitor.h b/xen/include/asm-arm/monitor.h
> new file mode 100644
> index 0000000..ef8f38a
> --- /dev/null
> +++ b/xen/include/asm-arm/monitor.h
> @@ -0,0 +1,13 @@
> +#ifndef __ASM_ARM_MONITOR_H__
> +#define __ASM_ARM_MONITOR_H__
> +
> +#include <xen/config.h>
> +#include <public/domctl.h>
> +
> +static inline
> +int monitor_domctl(struct xen_domctl_monitor_op *op, struct domain *d)
> +{
> +    return -ENOSYS;
> +}
> +
> +#endif /* __ASM_X86_MONITOR_H__ */
> diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
> index 20ede1e..99fcd94 100644
> --- a/xen/include/asm-x86/domain.h
> +++ b/xen/include/asm-x86/domain.h
> @@ -236,6 +236,41 @@ struct time_scale {
>      u32 mul_frac;
>  };
> 
> +/************************************************/
> +/*            monitor event options             */
> +/************************************************/
> +struct mov_to_cr0 {
> +    uint8_t enabled;
> +    uint8_t sync;
> +    uint8_t onchangeonly;
> +};
> +
> +struct mov_to_cr3 {
> +    uint8_t enabled;
> +    uint8_t sync;
> +    uint8_t onchangeonly;
> +};
> +
> +struct mov_to_cr4 {
> +    uint8_t enabled;
> +    uint8_t sync;
> +    uint8_t onchangeonly;
> +};
> +
> +struct mov_to_msr {
> +    uint8_t enabled;
> +    uint8_t extended_capture;
> +};
> +
> +struct singlestep {
> +    uint8_t enabled;
> +};
> +
> +struct software_breakpoint {
> +    uint8_t enabled;
> +};
> +
> +
>  struct pv_domain
>  {
>      l1_pgentry_t **gdt_ldt_l1tab;
> @@ -330,6 +365,16 @@ struct arch_domain
>      unsigned long pirq_eoi_map_mfn;
> 
>      unsigned int psr_rmid; /* RMID assigned to the domain for CMT */
> +
> +    /* Monitor options */
> +    struct {
> +        struct mov_to_cr0 mov_to_cr0;
> +        struct mov_to_cr3 mov_to_cr3;
> +        struct mov_to_cr4 mov_to_cr4;
> +        struct mov_to_msr mov_to_msr;
> +        struct singlestep singlestep;
> +        struct software_breakpoint software_breakpoint;
> +    } monitor_options;
>  } __cacheline_aligned;
> 
>  #define has_arch_pdevs(d)    (!list_empty(&(d)->arch.pdev_list))
> diff --git a/xen/include/asm-x86/monitor.h b/xen/include/asm-x86/monitor.h
> new file mode 100644
> index 0000000..1d7cdd3
> --- /dev/null
> +++ b/xen/include/asm-x86/monitor.h
> @@ -0,0 +1,9 @@
> +#ifndef __ASM_X86_MONITOR_H__
> +#define __ASM_X86_MONITOR_H__
> +
> +#include <xen/config.h>
> +#include <public/domctl.h>
> +
> +int monitor_domctl(struct xen_domctl_monitor_op *op, struct domain *d);
> +
> +#endif /* __ASM_X86_MONITOR_H__ */
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index 5d48a4d..4f3b685 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -803,7 +803,6 @@ struct xen_domctl_gdbsx_domstatus {
> 
>  #define XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE
> 0
>  #define XEN_DOMCTL_VM_EVENT_OP_MONITOR_DISABLE
> 1
> -#define XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE_INTROSPECTION
> 2
> 
>  /*
>   * Sharing ENOMEM helper.
> @@ -1001,6 +1000,58 @@ struct xen_domctl_psr_cmt_op {
>  typedef struct xen_domctl_psr_cmt_op xen_domctl_psr_cmt_op_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t);
> 
> +/*  XEN_DOMCTL_MONITOR_*
> + *
> + * Enable/disable monitoring various VM events.
> + * This domctl configures what events will be reported to helper apps
> + * via the ring buffer "MONITOR". The ring has to be first enabled
> + * with the domctl XEN_DOMCTL_VM_EVENT_OP_MONITOR.
> + *
> + * NOTICE: mem_access events are also delivered via the "MONITOR" ring
> buffer;
> + * however, enabling/disabling those events is performed with the use of
> + * memory_op hypercalls!
> + *
> + */
> +#define XEN_DOMCTL_MONITOR_OP_ENABLE   0
> +#define XEN_DOMCTL_MONITOR_OP_DISABLE  1
> +
> +#define XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR0            0
> +#define XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR3            1
> +#define XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR4            2
> +#define XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_MSR            3
> +#define XEN_DOMCTL_MONITOR_SUBOP_SINGLESTEP            4
> +#define XEN_DOMCTL_MONITOR_SUBOP_SOFTWARE_BREAKPOINT   5
> +
> +struct xen_domctl_monitor_op {
> +    uint32_t op; /* XEN_DOMCTL_MONITOR_OP_* */
> +    uint32_t subop; /* XEN_DOMCTL_MONITOR_SUBOP_* */
> +
> +    /*
> +     * Further options when issuing XEN_DOMCTL_MONITOR_OP_ENABLE.
> +     */
> +    union {
> +        struct {
> +            uint8_t sync; /* Pause vCPU until response */
> +            uint8_t onchangeonly; /* Send event only on a change of value
> */
> +            uint8_t pad[6];
> +        } mov_to_cr0, mov_to_cr3, mov_to_cr4;
> +
> +        /* Enable the capture of msr events on
> +            MSR_IA32_SYSENTER_EIP
> +            MSR_IA32_SYSENTER_ESP
> +            MSR_IA32_SYSENTER_CS
> +            MSR_IA32_MC0_CTL
> +            MSR_STAR
> +            MSR_LSTAR */
> +        struct {
> +            uint8_t extended_capture;
> +            uint8_t pad[7];
> +        } mov_to_msr;
> +    } options;
> +};
> +typedef struct xen_domctl__op xen_domctl_monitor_op_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_domctl_monitor_op_t);
> +
>  struct xen_domctl {
>      uint32_t cmd;
>  #define XEN_DOMCTL_createdomain                   1
> @@ -1076,6 +1127,7 @@ struct xen_domctl {
>  #define XEN_DOMCTL_setvnumainfo                  74
>  #define XEN_DOMCTL_psr_cmt_op                    75
>  #define XEN_DOMCTL_arm_configure_domain          76
> +#define XEN_DOMCTL_monitor_op                    77
>  #define XEN_DOMCTL_gdbsx_guestmemio            1000
>  #define XEN_DOMCTL_gdbsx_pausevcpu             1001
>  #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
> @@ -1141,6 +1193,7 @@ struct xen_domctl {
>          struct xen_domctl_gdbsx_domstatus   gdbsx_domstatus;
>          struct xen_domctl_vnuma             vnuma;
>          struct xen_domctl_psr_cmt_op        psr_cmt_op;
> +        struct xen_domctl_monitor_op        monitor_op;
>          uint8_t                             pad[128];
>      } u;
>  };
> diff --git a/xen/include/public/hvm/params.h
> b/xen/include/public/hvm/params.h
> index 6efcc0b..5de6a4b 100644
> --- a/xen/include/public/hvm/params.h
> +++ b/xen/include/public/hvm/params.h
> @@ -162,21 +162,6 @@
>   */
>  #define HVM_PARAM_ACPI_IOPORTS_LOCATION 19
> 
> -/* Enable blocking memory events, async or sync (pause vcpu until response)
> - * onchangeonly indicates messages only on a change of value */
> -#define HVM_PARAM_MEMORY_EVENT_CR0          20
> -#define HVM_PARAM_MEMORY_EVENT_CR3          21
> -#define HVM_PARAM_MEMORY_EVENT_CR4          22
> -#define HVM_PARAM_MEMORY_EVENT_INT3         23
> -#define HVM_PARAM_MEMORY_EVENT_SINGLE_STEP  25
> -#define HVM_PARAM_MEMORY_EVENT_MSR          30
> -
> -#define HVMPME_MODE_MASK       (3 << 0)
> -#define HVMPME_mode_disabled   0
> -#define HVMPME_mode_async      1
> -#define HVMPME_mode_sync       2
> -#define HVMPME_onchangeonly    (1 << 2)
> -
>  /* Boolean: Enable nestedhvm (hvm only) */
>  #define HVM_PARAM_NESTEDHVM    24
> 
> diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h
> index 8fba3d1b..a057608 100644
> --- a/xen/include/public/vm_event.h
> +++ b/xen/include/public/vm_event.h
> @@ -67,7 +67,7 @@
>  #define VM_EVENT_REASON_MOV_TO_CR3              5
>  /* CR4 was updated */
>  #define VM_EVENT_REASON_MOV_TO_CR4              6
> -/* An MSR was updated. Does NOT honour HVMPME_onchangeonly */
> +/* An MSR was updated. */
>  #define VM_EVENT_REASON_MOV_TO_MSR              9
>  /* Debug operation executed (int3) */
>  #define VM_EVENT_REASON_SOFTWARE_BREAKPOINT     7
> --
> 2.1.4


_______________________________________________
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®.