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

Re: [Xen-devel] [PATCH v6] x86/mm: Suppresses vm_events caused by page-walks



On Mon, May 7, 2018 at 7:40 AM, Alexandru Isaila
<aisaila@xxxxxxxxxxxxxxx> wrote:
> This patch is adding a way to enable/disable inguest pagefault
> events. It introduces the xc_monitor_inguest_pagefault function
> and adds the inguest_pagefault_disabled in the monitor structure.
> This is needed by the introspection so it will only get gla
> faults and not get spammed with other faults.
> In p2m_mem_access_check() we emulate so no event will get sent.

Thanks for the changes!

Acked-by: Tamas K Lengyel <tamas@xxxxxxxxxxxxx>

> Signed-off-by: Alexandru Isaila <aisaila@xxxxxxxxxxxxxxx>
>
> ---
> Changes since V5:
>         - Add comment for the xc_monitor_inguest_pagefault() func.
>         - Add altp2m_write_no_gpt test in xen_access
> ---
>  tools/libxc/include/xenctrl.h       |  7 +++++++
>  tools/libxc/xc_monitor.c            | 14 ++++++++++++++
>  tools/tests/xen-access/xen-access.c | 36 +++++++++++++++++++++++++++++++++++-
>  xen/arch/x86/mm/mem_access.c        |  9 +++++++++
>  xen/arch/x86/monitor.c              | 13 +++++++++++++
>  xen/include/asm-x86/domain.h        |  5 +++++
>  xen/include/asm-x86/monitor.h       |  3 ++-
>  xen/include/public/domctl.h         |  2 ++
>  8 files changed, 87 insertions(+), 2 deletions(-)
>
> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> index 09e1363..6f9070d 100644
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -2056,6 +2056,13 @@ int xc_monitor_descriptor_access(xc_interface *xch, 
> uint32_t domain_id,
>                                   bool enable);
>  int xc_monitor_guest_request(xc_interface *xch, uint32_t domain_id,
>                               bool enable, bool sync, bool allow_userspace);
> +/*
> + * Disables page-walk mem_access events by emulating. If the
> + * emulation can not be performed then a VM_EVENT_REASON_EMUL_UNIMPLEMENTED
> + * event will be issued.
> + */
> +int xc_monitor_inguest_pagefault(xc_interface *xch, uint32_t domain_id,
> +                                 bool disable);
>  int xc_monitor_debug_exceptions(xc_interface *xch, uint32_t domain_id,
>                                  bool enable, bool sync);
>  int xc_monitor_cpuid(xc_interface *xch, uint32_t domain_id, bool enable);
> diff --git a/tools/libxc/xc_monitor.c b/tools/libxc/xc_monitor.c
> index 0233b87..4ac823e 100644
> --- a/tools/libxc/xc_monitor.c
> +++ b/tools/libxc/xc_monitor.c
> @@ -163,6 +163,20 @@ int xc_monitor_guest_request(xc_interface *xch, uint32_t 
> domain_id, bool enable,
>      return do_domctl(xch, &domctl);
>  }
>
> +int xc_monitor_inguest_pagefault(xc_interface *xch, uint32_t domain_id,
> +                                bool disable)
> +{
> +    DECLARE_DOMCTL;
> +
> +    domctl.cmd = XEN_DOMCTL_monitor_op;
> +    domctl.domain = domain_id;
> +    domctl.u.monitor_op.op = disable ? XEN_DOMCTL_MONITOR_OP_ENABLE
> +                                    : XEN_DOMCTL_MONITOR_OP_DISABLE;
> +    domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT;
> +
> +    return do_domctl(xch, &domctl);
> +}
> +
>  int xc_monitor_emulate_each_rep(xc_interface *xch, uint32_t domain_id,
>                                  bool enable)
>  {
> diff --git a/tools/tests/xen-access/xen-access.c 
> b/tools/tests/xen-access/xen-access.c
> index 9d960e2..e940137 100644
> --- a/tools/tests/xen-access/xen-access.c
> +++ b/tools/tests/xen-access/xen-access.c
> @@ -362,7 +362,7 @@ void usage(char* progname)
>  {
>      fprintf(stderr, "Usage: %s [-m] <domain_id> write|exec", progname);
>  #if defined(__i386__) || defined(__x86_64__)
> -            fprintf(stderr, 
> "|breakpoint|altp2m_write|altp2m_exec|debug|cpuid|desc_access|write_ctrlreg_cr4");
> +            fprintf(stderr, 
> "|breakpoint|altp2m_write|altp2m_exec|debug|cpuid|desc_access|write_ctrlreg_cr4|altp2m_write_no_gpt");
>  #elif defined(__arm__) || defined(__aarch64__)
>              fprintf(stderr, "|privcall");
>  #endif
> @@ -395,6 +395,7 @@ int main(int argc, char *argv[])
>      int cpuid = 0;
>      int desc_access = 0;
>      int write_ctrlreg_cr4 = 0;
> +    int altp2m_write_no_gpt = 0;
>      uint16_t altp2m_view_id = 0;
>
>      char* progname = argv[0];
> @@ -453,6 +454,13 @@ int main(int argc, char *argv[])
>          altp2m = 1;
>          memaccess = 1;
>      }
> +    else if ( !strcmp(argv[0], "altp2m_write_no_gpt") )
> +    {
> +        default_access = XENMEM_access_rw;
> +        altp2m_write_no_gpt = 1;
> +        memaccess = 1;
> +        altp2m = 1;
> +    }
>      else if ( !strcmp(argv[0], "debug") )
>      {
>          debug = 1;
> @@ -513,6 +521,22 @@ int main(int argc, char *argv[])
>          xen_pfn_t gfn = 0;
>          unsigned long perm_set = 0;
>
> +        if( altp2m_write_no_gpt )
> +        {
> +            rc = xc_monitor_inguest_pagefault(xch, domain_id, 1);
> +            if ( rc < 0 )
> +            {
> +                ERROR("Error %d setting inguest pagefault\n", rc);
> +                goto exit;
> +            }
> +            rc = xc_monitor_emul_unimplemented(xch, domain_id, 1);
> +            if ( rc < 0 )
> +            {
> +                ERROR("Error %d failed to enable emul unimplemented\n", rc);
> +                goto exit;
> +            }
> +        }
> +
>          rc = xc_altp2m_set_domain_state( xch, domain_id, 1 );
>          if ( rc < 0 )
>          {
> @@ -857,6 +881,16 @@ int main(int argc, char *argv[])
>                         req.u.write_ctrlreg.old_value,
>                         req.u.write_ctrlreg.new_value);
>                  break;
> +            case VM_EVENT_REASON_EMUL_UNIMPLEMENTED:
> +                if ( altp2m_write_no_gpt && req.flags & 
> VM_EVENT_FLAG_ALTERNATE_P2M )
> +                {
> +                    DPRINTF("\tSwitching back to default view!\n");
> +
> +                    rsp.flags |= (VM_EVENT_FLAG_ALTERNATE_P2M |
> +                                  VM_EVENT_FLAG_TOGGLE_SINGLESTEP);
> +                    rsp.altp2m_idx = 0;
> +                }
> +                break;
>              default:
>                  fprintf(stderr, "UNKNOWN REASON CODE %d\n", req.reason);
>              }
> diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
> index c0cd017..febe38d 100644
> --- a/xen/arch/x86/mm/mem_access.c
> +++ b/xen/arch/x86/mm/mem_access.c
> @@ -28,6 +28,7 @@
>  #include <public/vm_event.h>
>  #include <asm/p2m.h>
>  #include <asm/altp2m.h>
> +#include <asm/hvm/emulate.h>
>  #include <asm/vm_event.h>
>
>  #include "mm-locks.h"
> @@ -207,6 +208,14 @@ bool p2m_mem_access_check(paddr_t gpa, unsigned long gla,
>              return true;
>          }
>      }
> +    if ( vm_event_check_ring(d->vm_event_monitor) &&
> +         d->arch.monitor.inguest_pagefault_disabled &&
> +         npfec.kind != npfec_kind_with_gla ) /* don't send a mem_event */
> +    {
> +        hvm_emulate_one_vm_event(EMUL_KIND_NORMAL, TRAP_invalid_op, 
> X86_EVENT_NO_EC);
> +
> +        return true;
> +    }
>
>      *req_ptr = NULL;
>      req = xzalloc(vm_event_request_t);
> diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c
> index f229e69..ce5d1ba 100644
> --- a/xen/arch/x86/monitor.c
> +++ b/xen/arch/x86/monitor.c
> @@ -241,6 +241,19 @@ int arch_monitor_domctl_event(struct domain *d,
>          break;
>      }
>
> +    case XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT:
> +    {
> +        bool old_status = ad->monitor.inguest_pagefault_disabled;
> +
> +        if ( unlikely(old_status == requested_status) )
> +            return -EEXIST;
> +
> +        domain_pause(d);
> +        ad->monitor.inguest_pagefault_disabled = requested_status;
> +        domain_unpause(d);
> +        break;
> +    }
> +
>      case XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS:
>      {
>          bool old_status = ad->monitor.descriptor_access_enabled;
> diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
> index 4679d54..fbdc392 100644
> --- a/xen/include/asm-x86/domain.h
> +++ b/xen/include/asm-x86/domain.h
> @@ -412,6 +412,11 @@ struct arch_domain
>          unsigned int descriptor_access_enabled                             : 
> 1;
>          unsigned int guest_request_userspace_enabled                       : 
> 1;
>          unsigned int emul_unimplemented_enabled                            : 
> 1;
> +        /*
> +         * By default all events are sent.
> +         * This is used to filter out pagefaults.
> +         */
> +        unsigned int inguest_pagefault_disabled                            : 
> 1;
>          struct monitor_msr_bitmap *msr_bitmap;
>          uint64_t write_ctrlreg_mask[4];
>      } monitor;
> diff --git a/xen/include/asm-x86/monitor.h b/xen/include/asm-x86/monitor.h
> index a0444d1..647df4a 100644
> --- a/xen/include/asm-x86/monitor.h
> +++ b/xen/include/asm-x86/monitor.h
> @@ -84,7 +84,8 @@ static inline uint32_t arch_monitor_get_capabilities(struct 
> domain *d)
>                     (1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION) |
>                     (1U << XEN_DOMCTL_MONITOR_EVENT_CPUID) |
>                     (1U << XEN_DOMCTL_MONITOR_EVENT_INTERRUPT) |
> -                   (1U << XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED);
> +                   (1U << XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED) |
> +                   (1U << XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT);
>
>      /* Since we know this is on VMX, we can just call the hvm func */
>      if ( hvm_is_singlestep_supported() )
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index 9ae72959..ab89f35 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -1014,6 +1014,8 @@ struct xen_domctl_psr_cmt_op {
>  #define XEN_DOMCTL_MONITOR_EVENT_INTERRUPT             8
>  #define XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS           9
>  #define XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED    10
> +/* Enabled by default */
> +#define XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT     11
>
>  struct xen_domctl_monitor_op {
>      uint32_t op; /* XEN_DOMCTL_MONITOR_OP_* */
> --
> 2.7.4

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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