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

Re: [Xen-devel] [PATCH RFC 5/6] xen-access: add support for slotted channel vm_events



On 11/28/18 5:29 PM, Petre Pircalabu wrote:
> Signed-off-by: Petre Pircalabu <ppircalabu@xxxxxxxxxxxxxxx>
> ---
>  tools/tests/xen-access/xen-access.c | 510 
> ++++++++++++++++++++++++++++--------
>  1 file changed, 408 insertions(+), 102 deletions(-)
> 
> diff --git a/tools/tests/xen-access/xen-access.c 
> b/tools/tests/xen-access/xen-access.c
> index 6aaee16..e44708d 100644
> --- a/tools/tests/xen-access/xen-access.c
> +++ b/tools/tests/xen-access/xen-access.c
> @@ -62,13 +62,33 @@
>  /* From xen/include/asm-x86/x86-defns.h */
>  #define X86_CR4_PGE        0x00000080 /* enable global pages */
>  
> -typedef struct vm_event {
> -    domid_t domain_id;
> +#ifndef round_pgup
> +#define round_pgup(p)    (((p) + (XC_PAGE_SIZE - 1)) & XC_PAGE_MASK)
> +#endif /* round_pgup */
> +
> +struct vm_event_ring
> +{
>      xenevtchn_handle *xce_handle;
>      int port;
>      vm_event_back_ring_t back_ring;
>      uint32_t evtchn_port;
> -    void *ring_page;
> +    void *buffer;
> +    unsigned int page_count;
> +};
> +
> +struct vm_event_channel
> +{
> +    xenevtchn_handle **xce_handles;
> +    int *ports;
> +    uint32_t *evtchn_ports;
> +    void *buffer;
> +};
> +
> +typedef struct vm_event {
> +    domid_t domain_id;
> +    unsigned int num_vcpus;
> +    struct vm_event_ring *ring;
> +    struct vm_event_channel *channel;
>  } vm_event_t;
>  
>  typedef struct xenaccess {
> @@ -79,6 +99,7 @@ typedef struct xenaccess {
>      vm_event_t vm_event;
>  } xenaccess_t;
>  
> +
>  static int interrupted;
>  bool evtchn_bind = 0, evtchn_open = 0, mem_access_enable = 0;
>  
> @@ -87,45 +108,181 @@ static void close_handler(int sig)
>      interrupted = sig;
>  }
>  
> -int xc_wait_for_event_or_timeout(xc_interface *xch, xenevtchn_handle *xce, 
> unsigned long ms)
> +static int xenaccess_wait_for_events(xenaccess_t *xenaccess,
> +                                     int **_ports,
> +                                     unsigned long ms)
>  {
> -    struct pollfd fd = { .fd = xenevtchn_fd(xce), .events = POLLIN | POLLERR 
> };
> -    int port;
> -    int rc;
> +    struct pollfd *fds;
> +    vm_event_t *vm_event;
> +    int rc, fd_count = 0, i = 0, found = 0;
> +    int *ports;
> +
> +    vm_event = &xenaccess->vm_event;
>  
> -    rc = poll(&fd, 1, ms);
> -    if ( rc == -1 )
> +    fd_count = ((vm_event->channel) ? vm_event->num_vcpus : 0) + 1;
> +
> +    fds = calloc(fd_count, sizeof(struct pollfd));
> +
> +    if ( vm_event->channel )
>      {
> -        if (errno == EINTR)
> -            return 0;
> +        for (i = 0; i < vm_event->num_vcpus; i++ )
> +        {
> +            fds[i].fd = xenevtchn_fd(vm_event->channel->xce_handles[i]);
> +            fds[i].events = POLLIN | POLLERR;
> +            fds[i].revents = 0;
> +        }
> +    }
>  
> -        ERROR("Poll exited with an error");
> -        goto err;
> +    fds[i].fd = xenevtchn_fd(vm_event->ring->xce_handle);
> +    fds[i].events = POLLIN | POLLERR;
> +    fds[i].revents = 0;
> +
> +    rc = poll(fds, fd_count, ms);
> +    if ( rc == -1 || rc == 0 )
> +    {
> +        if ( errno == EINTR )
> +            rc = 0;
> +        goto cleanup;
>      }
>  
> -    if ( rc == 1 )
> +    ports = malloc(rc * sizeof(int));
> +
> +    for ( i = 0; i < fd_count ; i++ )
>      {
> -        port = xenevtchn_pending(xce);
> -        if ( port == -1 )
> +        if ( fds[i].revents & POLLIN )
>          {
> -            ERROR("Failed to read port from event channel");
> -            goto err;
> +            xenevtchn_handle *xce = (i == (fd_count-1)) ? 
> vm_event->ring->xce_handle :
> +                                                        
> vm_event->channel->xce_handles[i];
> +            int port = xenevtchn_pending(xce);
> +
> +            if ( port == -1 )
> +            {
> +                ERROR("Failed to read port from event channel");
> +                rc = -1;
> +                goto cleanup;
> +            }
> +
> +            if ( xenevtchn_unmask(xce, port) )
> +            {
> +                ERROR("Failed to unmask event channel port");
> +                rc = -1;
> +                goto cleanup;
> +            }
> +
> +            ports[found++] = port;
>          }
> +    }
>  
> -        rc = xenevtchn_unmask(xce, port);
> -        if ( rc != 0 )
> +    *_ports = ports;
> +
> +cleanup:
> +    free(fds);
> +    return rc;
> +}
> +
> +static int xenaccess_evtchn_bind_port(uint32_t evtchn_port,
> +                                      domid_t domain_id,
> +                                      xenevtchn_handle **_handle,
> +                                      int *_port)
> +{
> +    xenevtchn_handle *handle;
> +    int rc;
> +
> +    if ( !_handle || !_port )
> +        return -EINVAL;
> +
> +    /* Open event channel */
> +    handle = xenevtchn_open(NULL, 0);
> +    if ( handle == NULL )
> +    {
> +        ERROR("Failed to open event channel\n");
> +        return -ENODEV;
> +    }
> +
> +    /* Bind event notification */
> +    rc = xenevtchn_bind_interdomain(handle, domain_id, evtchn_port);
> +    if ( rc < 0 )
> +    {
> +        ERROR("Failed to bind event channel\n");
> +        xenevtchn_close(handle);
> +        return rc;
> +    }
> +
> +    *_handle = handle;
> +    *_port = rc;
> +    return 0;
> +}
> +
> +static void xenaccess_evtchn_unbind_port(uint32_t evtchn_port,
> +                                         xenevtchn_handle **_handle,
> +                                         int *_port)
> +{
> +    if ( !_handle || !*_handle || !_port )
> +        return;
> +
> +    xenevtchn_unbind(*_handle, *_port);
> +    xenevtchn_close(*_handle);
> +    *_handle = NULL;
> +    *_port = 0;
> +}
> +
> +static int xenaccess_evtchn_bind(xenaccess_t *xenaccess)
> +{
> +    int rc, i = 0;
> +
> +    rc = xenaccess_evtchn_bind_port(xenaccess->vm_event.ring->evtchn_port,
> +                                    xenaccess->vm_event.domain_id,
> +                                    &xenaccess->vm_event.ring->xce_handle,
> +                                    &xenaccess->vm_event.ring->port);
> +    if ( rc < 0 )
> +    {
> +        ERROR("Failed to bind ring events\n");
> +        return rc;
> +    }
> +
> +    if ( xenaccess->vm_event.channel == NULL)
> +        return 0;
> +
> +    for ( i = 0; i < xenaccess->vm_event.num_vcpus; i++ )
> +    {
> +        rc = 
> xenaccess_evtchn_bind_port(xenaccess->vm_event.channel->evtchn_ports[i],
> +                                        xenaccess->vm_event.domain_id,
> +                                        
> &xenaccess->vm_event.channel->xce_handles[i],
> +                                        
> &xenaccess->vm_event.channel->ports[i]);
> +        if ( rc < 0 )
>          {
> -            ERROR("Failed to unmask event channel port");
> +            ERROR("Failed to bind channel events\n");
>              goto err;
>          }
>      }
> -    else
> -        port = -1;
>  
> -    return port;
> +    evtchn_bind = true;
> +    return 0;
>  
> - err:
> -    return -errno;
> +err:
> +    xenaccess_evtchn_unbind_port(xenaccess->vm_event.ring->evtchn_port,
> +                                 &xenaccess->vm_event.ring->xce_handle,
> +                                 &xenaccess->vm_event.ring->port);
> +
> +    for ( i--; i >= 0; i-- )

This for() looks peculiar.


Thanks,
Razvan

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