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

Re: [Xen-devel] [PATCH 4/4] vm_event: Add support for multi-page ring buffer



On Thu, Sep 13, 2018 at 9:02 AM Petre Pircalabu
<ppircalabu@xxxxxxxxxxxxxxx> wrote:
>
> In high throughput introspection scenarios where lots of monitor
> vm_events are generated, the ring buffer can fill up before the monitor
> application gets a chance to handle all the requests thus blocking
> other vcpus which will have to wait for a slot to become available.
>
> This patch adds support for extending the ring buffer by allocating a
> number of pages from domheap and mapping them to the monitor
> application's domain using the foreignmemory_map_resource interface.
> Unlike the current implementation, the ring buffer pages are not part of
> the introspected DomU, so they will not be reclaimed when the monitor is
> disabled.
>
> Signed-off-by: Petre Pircalabu <ppircalabu@xxxxxxxxxxxxxxx>

Thanks for this addition, it has been on the TODO for a long while
now. Could you also please push the patches as a git branch somewhere?

> ---
>  tools/libxc/include/xenctrl.h       |   2 +
>  tools/libxc/xc_monitor.c            |   7 +
>  tools/libxc/xc_private.h            |   3 +
>  tools/libxc/xc_vm_event.c           |  49 +++++++
>  tools/tests/xen-access/xen-access.c |  33 +++--
>  xen/arch/x86/domain_page.c          |   3 +-
>  xen/arch/x86/mm.c                   |  14 ++
>  xen/common/vm_event.c               | 258 
> +++++++++++++++++++++++++++---------
>  xen/include/public/domctl.h         |   1 +
>  xen/include/public/memory.h         |   1 +
>  xen/include/xen/sched.h             |   5 +-
>  xen/include/xen/vm_event.h          |   4 +
>  12 files changed, 305 insertions(+), 75 deletions(-)
>
> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> index bb75bcc..4f91ee9 100644
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -2005,6 +2005,8 @@ int xc_get_mem_access(xc_interface *xch, uint32_t 
> domain_id,
>   * Caller has to unmap this page when done.
>   */
>  void *xc_monitor_enable(xc_interface *xch, uint32_t domain_id, uint32_t 
> *port);
> +void *xc_monitor_enable_ex(xc_interface *xch, uint32_t domain_id,
> +                           int order, uint32_t *port);

I don't think there is value in keeping both version of the API
around. As libxc is not considered to be a stable API extending the
existing API would be the route I would prefer. Also, perhaps instead
of "order" name the input variable "page_count" to make it more clear
what it's about.

>  int xc_monitor_disable(xc_interface *xch, uint32_t domain_id);
>  int xc_monitor_resume(xc_interface *xch, uint32_t domain_id);
>  /*
> diff --git a/tools/libxc/xc_monitor.c b/tools/libxc/xc_monitor.c
> index 15e6a0e..5188835 100644
> --- a/tools/libxc/xc_monitor.c
> +++ b/tools/libxc/xc_monitor.c
> @@ -28,6 +28,13 @@ void *xc_monitor_enable(xc_interface *xch, uint32_t 
> domain_id, uint32_t *port)
>                                port);
>  }
>
> +void *xc_monitor_enable_ex(xc_interface *xch, uint32_t domain_id, int order,
> +                           uint32_t *port)
> +{
> +    return xc_vm_event_enable_ex(xch, domain_id, XEN_VM_EVENT_TYPE_MONITOR,
> +                                 order, port);
> +}
> +
>  int xc_monitor_disable(xc_interface *xch, uint32_t domain_id)
>  {
>      return xc_vm_event_control(xch, domain_id,
> diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
> index be22986..03d9460 100644
> --- a/tools/libxc/xc_private.h
> +++ b/tools/libxc/xc_private.h
> @@ -436,6 +436,9 @@ int xc_vm_event_control(xc_interface *xch, uint32_t 
> domain_id, unsigned int op,
>  void *xc_vm_event_enable(xc_interface *xch, uint32_t domain_id, int type,
>                           uint32_t *port);
>
> +void *xc_vm_event_enable_ex(xc_interface *xch, uint32_t domain_id, int type,
> +                            int order, uint32_t *port);
> +
>  int do_dm_op(xc_interface *xch, uint32_t domid, unsigned int nr_bufs, ...);
>
>  #endif /* __XC_PRIVATE_H__ */
> diff --git a/tools/libxc/xc_vm_event.c b/tools/libxc/xc_vm_event.c
> index de37ca5..216bbe2 100644
> --- a/tools/libxc/xc_vm_event.c
> +++ b/tools/libxc/xc_vm_event.c
> @@ -21,6 +21,7 @@
>   */
>
>  #include "xc_private.h"
> +#include "xenforeignmemory.h"
>
>  int xc_vm_event_control(xc_interface *xch, uint32_t domain_id, unsigned int 
> op,
>                          unsigned int mode, uint32_t *port)
> @@ -184,6 +185,54 @@ void *xc_vm_event_enable(xc_interface *xch, uint32_t 
> domain_id, int type,
>      return ring_page;
>  }
>
> +void *xc_vm_event_enable_ex(xc_interface *xch, uint32_t domain_id, int type,
> +                            int order, uint32_t *port)
> +{
> +    xenforeignmemory_resource_handle *fres = NULL;
> +    int saved_errno;
> +    void *ring_buffer = NULL;
> +
> +    if ( !port )
> +    {
> +        errno = EINVAL;
> +        return NULL;
> +    }
> +
> +    /* Pause the domain for ring page setup */
> +    if ( xc_domain_pause(xch, domain_id) )
> +    {
> +        PERROR("Unable to pause domain\n");
> +        return NULL;
> +    }
> +
> +    fres = xenforeignmemory_map_resource(xch->fmem, domain_id,
> +                                         XENMEM_resource_vm_event, type, 0,
> +                                         order, &ring_buffer,
> +                                         PROT_READ | PROT_WRITE, 0);
> +    if ( !fres )
> +    {
> +        PERROR("Unable to map vm_event ring pages resource\n");
> +        goto out;
> +    }
> +
> +    if ( xc_vm_event_control(xch, domain_id, XEN_VM_EVENT_GET_PORT, type, 
> port) )
> +        PERROR("Unable to get vm_event channel port\n");
> +
> +out:
> +    saved_errno = errno;
> +    if ( xc_domain_unpause(xch, domain_id) != 0 )
> +    {
> +        if (fres)
> +            saved_errno = errno;
> +        PERROR("Unable to unpause domain");
> +    }
> +
> +    free(fres);
> +    errno = saved_errno;
> +    return ring_buffer;
> +}
> +
> +
>  /*
>   * Local variables:
>   * mode: C
> diff --git a/tools/tests/xen-access/xen-access.c 
> b/tools/tests/xen-access/xen-access.c
> index 6aaee16..f4c4eda 100644
> --- a/tools/tests/xen-access/xen-access.c
> +++ b/tools/tests/xen-access/xen-access.c
> @@ -68,7 +68,8 @@ typedef struct vm_event {
>      int port;
>      vm_event_back_ring_t back_ring;
>      uint32_t evtchn_port;
> -    void *ring_page;
> +    void *ring_buffer;
> +    unsigned int ring_page_count;
>  } vm_event_t;
>
>  typedef struct xenaccess {
> @@ -136,8 +137,9 @@ int xenaccess_teardown(xc_interface *xch, xenaccess_t 
> *xenaccess)
>          return 0;
>
>      /* Tear down domain xenaccess in Xen */
> -    if ( xenaccess->vm_event.ring_page )
> -        munmap(xenaccess->vm_event.ring_page, XC_PAGE_SIZE);
> +    if ( xenaccess->vm_event.ring_buffer )
> +        munmap(xenaccess->vm_event.ring_buffer,
> +               xenaccess->vm_event.ring_page_count * XC_PAGE_SIZE );
>
>      if ( mem_access_enable )
>      {
> @@ -210,12 +212,25 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, 
> domid_t domain_id)
>      /* Set domain id */
>      xenaccess->vm_event.domain_id = domain_id;
>
> -    /* Enable mem_access */
> -    xenaccess->vm_event.ring_page =
> +    /* Ring buffer page count */
> +    xenaccess->vm_event.ring_page_count = 2;
> +
> +    xenaccess->vm_event.ring_buffer = xc_monitor_enable_ex(
> +        xenaccess->xc_handle,
> +        xenaccess->vm_event.domain_id,
> +        xenaccess->vm_event.ring_page_count,
> +        &xenaccess->vm_event.evtchn_port);
> +
> +    if (xenaccess->vm_event.ring_buffer == NULL && errno == EOPNOTSUPP)

How would this situation ever arise? If there is a chance that you
can't setup multi-page rings, perhaps adding a hypercall that would
tell the user how many pages are max available for the ring is the
better route. This just seems like guessing right now.

> +    {
> +        xenaccess->vm_event.ring_page_count = 1;
> +        xenaccess->vm_event.ring_buffer =
>              xc_monitor_enable(xenaccess->xc_handle,
>                                xenaccess->vm_event.domain_id,
>                                &xenaccess->vm_event.evtchn_port);

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