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

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



Signed-off-by: Petre Pircalabu <ppircalabu@xxxxxxxxxxxxxxx>
---
 tools/tests/xen-access/xen-access.c | 545 +++++++++++++++++++++++++++++-------
 1 file changed, 441 insertions(+), 104 deletions(-)

diff --git a/tools/tests/xen-access/xen-access.c 
b/tools/tests/xen-access/xen-access.c
index 6aaee16..b09be6c 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,224 @@ 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 vcpu_id_by_port(vm_event_t *vm_event, int port)
 {
-    struct pollfd fd = { .fd = xenevtchn_fd(xce), .events = POLLIN | POLLERR };
-    int port;
-    int rc;
+    int i;
+
+    if ( port == vm_event->ring->port )
+        return 0;
+
+    if ( vm_event->channel )
+        for ( i = 0; i < vm_event->num_vcpus; i++ )
+            if ( vm_event->channel->ports[i] == port )
+                return i;
+
+    return -1;
+}
+
+static int xenaccess_wait_for_events(xenaccess_t *xenaccess,
+                                     int **_ports,
+                                     unsigned long ms)
+{
+    struct pollfd *fds;
+    vm_event_t *vm_event;
+    int rc, fd_count = 0, i = 0, found = 0;
+    int *ports = NULL;
+
+    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;
+            bool ring_event = i == (fd_count-1);
+            xenevtchn_handle *xce = ( ring_event ) ? 
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 ( ring_event )
+            {
+                if ( RING_HAS_UNCONSUMED_REQUESTS(&vm_event->ring->back_ring) )
+                    ports[found++] = port;
+
+                if ( xenevtchn_unmask(xce, port) )
+                {
+                    ERROR("Failed to unmask event channel port");
+                    rc = -1;
+                    goto cleanup;
+                }
+            }
+            else
+            {
+                int vcpu_id = vcpu_id_by_port(vm_event, port);
+                struct vm_event_slot *slot;
+
+                if ( vcpu_id < 0 )
+                {
+                    ERROR("Failed to get the vm_event_slot for port %d\n", 
port);
+                    rc = -1;
+                    goto cleanup;
+                }
+                slot = &((struct vm_event_slot 
*)vm_event->channel->buffer)[vcpu_id];
+
+                if ( slot->state == VM_EVENT_SLOT_STATE_SUBMIT )
+                    ports[found++] = port;
+                /* Unmask the port's event channel in case of a spurious 
interrupt */
+                else if ( xenevtchn_unmask(xce, port) )
+                {
+                    ERROR("Failed to unmask event channel port");
+                    rc = -1;
+                    goto cleanup;
+                }
+            }
         }
+    }
+    rc = found;
+    *_ports = ports;
 
-        rc = xenevtchn_unmask(xce, port);
-        if ( rc != 0 )
+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-- )
+        
xenaccess_evtchn_unbind_port(xenaccess->vm_event.channel->evtchn_ports[i],
+                                     
&xenaccess->vm_event.channel->xce_handles[i],
+                                     &xenaccess->vm_event.channel->ports[i]);
+    return rc;
+}
+
+static void xenaccess_evtchn_unbind(xenaccess_t *xenaccess)
+{
+    int i;
+
+    xenaccess_evtchn_unbind_port(xenaccess->vm_event.ring->evtchn_port,
+                                 &xenaccess->vm_event.ring->xce_handle,
+                                 &xenaccess->vm_event.ring->port);
+
+    for ( i = 0; i < xenaccess->vm_event.num_vcpus; i++ )
+        
xenaccess_evtchn_unbind_port(xenaccess->vm_event.channel->evtchn_ports[i],
+                                     
&xenaccess->vm_event.channel->xce_handles[i],
+                                     &xenaccess->vm_event.channel->ports[i]);
 }
 
 int xenaccess_teardown(xc_interface *xch, xenaccess_t *xenaccess)
@@ -136,8 +336,13 @@ 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 ( xenaccess->vm_event.channel->buffer )
+        munmap(xenaccess->vm_event.channel->buffer,
+               round_pgup(xenaccess->vm_event.num_vcpus * sizeof (struct 
vm_event_slot)) );
 
     if ( mem_access_enable )
     {
@@ -153,24 +358,8 @@ int xenaccess_teardown(xc_interface *xch, xenaccess_t 
*xenaccess)
     /* Unbind VIRQ */
     if ( evtchn_bind )
     {
-        rc = xenevtchn_unbind(xenaccess->vm_event.xce_handle,
-                              xenaccess->vm_event.port);
-        if ( rc != 0 )
-        {
-            ERROR("Error unbinding event port");
-            return rc;
-        }
-    }
-
-    /* Close event channel */
-    if ( evtchn_open )
-    {
-        rc = xenevtchn_close(xenaccess->vm_event.xce_handle);
-        if ( rc != 0 )
-        {
-            ERROR("Error closing event channel");
-            return rc;
-        }
+        xenaccess_evtchn_unbind(xenaccess);
+        evtchn_bind = false;
     }
 
     /* Close connection to Xen */
@@ -182,6 +371,16 @@ int xenaccess_teardown(xc_interface *xch, xenaccess_t 
*xenaccess)
     }
     xenaccess->xc_handle = NULL;
 
+    if (xenaccess->vm_event.channel)
+    {
+        free(xenaccess->vm_event.channel->evtchn_ports);
+        free(xenaccess->vm_event.channel->ports);
+        free(xenaccess->vm_event.channel->xce_handles);
+        free(xenaccess->vm_event.channel);
+    }
+
+    free(xenaccess->vm_event.ring);
+
     free(xenaccess);
 
     return 0;
@@ -191,6 +390,8 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t 
domain_id)
 {
     xenaccess_t *xenaccess = 0;
     xc_interface *xch;
+    xc_dominfo_t info;
+    void *handle;
     int rc;
 
     xch = xc_interface_open(NULL, NULL, 0);
@@ -201,8 +402,7 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t 
domain_id)
     *xch_r = xch;
 
     /* Allocate memory */
-    xenaccess = malloc(sizeof(xenaccess_t));
-    memset(xenaccess, 0, sizeof(xenaccess_t));
+    xenaccess = calloc(1, sizeof(xenaccess_t));
 
     /* Open connection to xen */
     xenaccess->xc_handle = xch;
@@ -210,12 +410,50 @@ 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 =
-            xc_monitor_enable(xenaccess->xc_handle,
-                              xenaccess->vm_event.domain_id,
-                              &xenaccess->vm_event.evtchn_port);
-    if ( xenaccess->vm_event.ring_page == NULL )
+    rc = xc_domain_getinfo(xch, domain_id, 1, &info);
+    if ( rc != 1 )
+    {
+        ERROR("xc_domain_getinfo failed. rc = %d\n", rc);
+        goto err;
+    }
+
+    xenaccess->vm_event.num_vcpus = info.max_vcpu_id + 1;
+
+    xenaccess->vm_event.ring = calloc(1, sizeof(struct vm_event_ring));
+    xenaccess->vm_event.ring->page_count = 1;
+
+    xenaccess->vm_event.channel = calloc(1, sizeof(struct vm_event_channel));
+    xenaccess->vm_event.channel->xce_handles = 
calloc(xenaccess->vm_event.num_vcpus,
+                                                      
sizeof(xenevtchn_handle*));
+    xenaccess->vm_event.channel->ports = calloc(xenaccess->vm_event.num_vcpus,
+                                                sizeof(int));
+    xenaccess->vm_event.channel->evtchn_ports = 
calloc(xenaccess->vm_event.num_vcpus,
+                                                       sizeof(uint32_t));
+
+    handle = xc_monitor_enable_ex(xenaccess->xc_handle,
+                                  xenaccess->vm_event.domain_id,
+                                  &xenaccess->vm_event.ring->buffer,
+                                  xenaccess->vm_event.ring->page_count,
+                                  &xenaccess->vm_event.ring->evtchn_port,
+                                  &xenaccess->vm_event.channel->buffer,
+                                  xenaccess->vm_event.channel->evtchn_ports,
+                                  xenaccess->vm_event.num_vcpus);
+
+    if ( handle == NULL && errno == EOPNOTSUPP )
+    {
+        free(xenaccess->vm_event.channel->xce_handles);
+        free(xenaccess->vm_event.channel->ports);
+        free(xenaccess->vm_event.channel->evtchn_ports);
+        free(xenaccess->vm_event.channel);
+        xenaccess->vm_event.channel = NULL;
+
+        handle = xc_monitor_enable(xenaccess->xc_handle,
+                                   xenaccess->vm_event.domain_id,
+                                   &xenaccess->vm_event.ring->evtchn_port);
+        xenaccess->vm_event.ring->buffer = handle;
+    }
+
+    if ( handle == NULL )
     {
         switch ( errno ) {
             case EBUSY:
@@ -230,40 +468,25 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t 
domain_id)
         }
         goto err;
     }
-    mem_access_enable = 1;
 
-    /* Open event channel */
-    xenaccess->vm_event.xce_handle = xenevtchn_open(NULL, 0);
-    if ( xenaccess->vm_event.xce_handle == NULL )
-    {
-        ERROR("Failed to open event channel");
-        goto err;
-    }
-    evtchn_open = 1;
+    /* Enable mem_access */
+    mem_access_enable = 1;
 
-    /* Bind event notification */
-    rc = xenevtchn_bind_interdomain(xenaccess->vm_event.xce_handle,
-                                    xenaccess->vm_event.domain_id,
-                                    xenaccess->vm_event.evtchn_port);
+    rc = xenaccess_evtchn_bind(xenaccess);
     if ( rc < 0 )
-    {
-        ERROR("Failed to bind event channel");
         goto err;
-    }
-    evtchn_bind = 1;
-    xenaccess->vm_event.port = rc;
 
-    /* Initialise ring */
-    SHARED_RING_INIT((vm_event_sring_t *)xenaccess->vm_event.ring_page);
-    BACK_RING_INIT(&xenaccess->vm_event.back_ring,
-                   (vm_event_sring_t *)xenaccess->vm_event.ring_page,
-                   XC_PAGE_SIZE);
+    evtchn_bind = true;
 
+    /* Initialise ring */
+    SHARED_RING_INIT((vm_event_sring_t *)xenaccess->vm_event.ring->buffer);
+    BACK_RING_INIT(&xenaccess->vm_event.ring->back_ring,
+                   (vm_event_sring_t *)xenaccess->vm_event.ring->buffer,
+                   XC_PAGE_SIZE * xenaccess->vm_event.ring->page_count);
     /* Get max_gpfn */
     rc = xc_domain_maximum_gpfn(xenaccess->xc_handle,
                                 xenaccess->vm_event.domain_id,
                                 &xenaccess->max_gpfn);
-
     if ( rc )
     {
         ERROR("Failed to get max gpfn");
@@ -275,11 +498,8 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t 
domain_id)
     return xenaccess;
 
  err:
-    rc = xenaccess_teardown(xch, xenaccess);
-    if ( rc )
-    {
+    if ( xenaccess_teardown(xch, xenaccess) )
         ERROR("Failed to teardown xenaccess structure!\n");
-    }
 
  err_iface:
     return NULL;
@@ -301,12 +521,10 @@ int control_singlestep(
 /*
  * Note that this function is not thread safe.
  */
-static void get_request(vm_event_t *vm_event, vm_event_request_t *req)
+static void get_ring_request(vm_event_back_ring_t *back_ring, 
vm_event_request_t *req)
 {
-    vm_event_back_ring_t *back_ring;
     RING_IDX req_cons;
 
-    back_ring = &vm_event->back_ring;
     req_cons = back_ring->req_cons;
 
     /* Copy request */
@@ -318,6 +536,62 @@ static void get_request(vm_event_t *vm_event, 
vm_event_request_t *req)
     back_ring->sring->req_event = req_cons + 1;
 }
 
+static bool get_request(vm_event_t *vm_event, vm_event_request_t *req,
+                        int *ports, int *index, int *next)
+{
+    int port;
+
+    *index = *next;
+
+    if ( *index < 0 )
+        return false;
+
+    port = ports[*index];
+
+    if ( port == vm_event->ring->port )
+    {
+        /* SKIP spurious event */
+        if ( !RING_HAS_UNCONSUMED_REQUESTS(&vm_event->ring->back_ring) )
+        {
+            ports[*index] = -1;
+            (*next)--;
+            return true;
+        }
+
+        get_ring_request(&vm_event->ring->back_ring, req);
+
+        /*
+         * The vm event ring contains unconsumed request.
+         * The "pending" port index is not be decremented and the subsequent
+         * call will return the next pending vm_event request from the ring.
+         */
+        if ( RING_HAS_UNCONSUMED_REQUESTS(&vm_event->ring->back_ring) )
+            return true;
+    }
+    else if (vm_event->channel)
+    {
+        int vcpu_id = vcpu_id_by_port(vm_event, port);
+
+        if (vcpu_id < 0)
+            ports[*index] = -1;
+        else
+        {
+            struct vm_event_slot *slot = &((struct vm_event_slot 
*)vm_event->channel->buffer)[vcpu_id];
+
+            if ( slot->state != VM_EVENT_SLOT_STATE_SUBMIT )
+                ports[*index] = -1;
+            else
+            {
+                memcpy(req, &slot->u.req, sizeof(*req));
+                if (xenevtchn_unmask(vm_event->channel->xce_handles[vcpu_id], 
port) )
+                    ports[*index] = -1;
+            }
+        }
+    }
+    (*next)--;
+    return true;
+}
+
 /*
  * X86 control register names
  */
@@ -339,12 +613,10 @@ static const char* get_x86_ctrl_reg_name(uint32_t index)
 /*
  * Note that this function is not thread safe.
  */
-static void put_response(vm_event_t *vm_event, vm_event_response_t *rsp)
+static void put_ring_response(vm_event_back_ring_t *back_ring, 
vm_event_response_t *rsp)
 {
-    vm_event_back_ring_t *back_ring;
     RING_IDX rsp_prod;
 
-    back_ring = &vm_event->back_ring;
     rsp_prod = back_ring->rsp_prod_pvt;
 
     /* Copy response */
@@ -356,6 +628,59 @@ static void put_response(vm_event_t *vm_event, 
vm_event_response_t *rsp)
     RING_PUSH_RESPONSES(back_ring);
 }
 
+static void put_response(vm_event_t *vm_event, vm_event_response_t *rsp, int 
port)
+{
+    if ( port == vm_event->ring->port )
+    {
+        /* Drop ring responses if the synchronous slotted channel is enabled */
+        if ( vm_event->channel )
+        {
+            ERROR("Cannot put response on async ring\n");
+            return;
+        }
+
+        put_ring_response(&vm_event->ring->back_ring, rsp);
+    }
+    else
+    {
+        int vcpu_id = vcpu_id_by_port(vm_event, port);
+        struct vm_event_slot *slot;
+
+        if ( vcpu_id < 0 )
+            return;
+
+        slot = &((struct vm_event_slot *)vm_event->channel->buffer)[vcpu_id];
+        memcpy(&slot->u.rsp, rsp, sizeof(*rsp));
+        slot->state = VM_EVENT_SLOT_STATE_FINISH;
+    }
+}
+
+static int xenaccess_notify(vm_event_t *vm_event, int port)
+{
+       xenevtchn_handle *xce;
+
+        if ( port == vm_event->ring->port )
+            xce = vm_event->ring->xce_handle;
+        else
+        {
+            int vcpu_id = vcpu_id_by_port(vm_event, port);
+
+            if ( vcpu_id < 0 )
+                return -1;
+
+            xce = vm_event->channel->xce_handles[vcpu_id];
+        }
+
+        /* Tell Xen page is ready */
+        if ( xenevtchn_notify(xce, port) != 0)
+        {
+            ERROR("Error resuming page");
+            return -1;
+        }
+
+    return 0;
+}
+
 void usage(char* progname)
 {
     fprintf(stderr, "Usage: %s [-m] <domain_id> write|exec", progname);
@@ -663,6 +988,8 @@ int main(int argc, char *argv[])
     /* Wait for access */
     for (;;)
     {
+        int *ports = NULL, current_index, next_index, req_count;
+
         if ( interrupted )
         {
             /* Unregister for every event */
@@ -697,25 +1024,35 @@ int main(int argc, char *argv[])
             shutting_down = 1;
         }
 
-        rc = xc_wait_for_event_or_timeout(xch, xenaccess->vm_event.xce_handle, 
100);
-        if ( rc < -1 )
+        rc = xenaccess_wait_for_events(xenaccess, &ports, 100);
+        if ( rc < 0 )
         {
-            ERROR("Error getting event");
             interrupted = -1;
             continue;
         }
-        else if ( rc != -1 )
+        else if ( rc == 0 )
+        {
+            if ( ! shutting_down )
+                continue;
+        }
+        else
         {
             DPRINTF("Got event from Xen\n");
         }
 
-        while ( RING_HAS_UNCONSUMED_REQUESTS(&xenaccess->vm_event.back_ring) )
+        req_count = rc;
+        current_index = req_count;
+        next_index = current_index;
+
+        while ( get_request(&xenaccess->vm_event, &req, ports, &current_index, 
&next_index) )
         {
-            get_request(&xenaccess->vm_event, &req);
+            if ( ports[current_index] < 0)
+                continue;
 
             if ( req.version != VM_EVENT_INTERFACE_VERSION )
             {
                 ERROR("Error: vm_event interface version mismatch!\n");
+                ports[current_index] = -1;
                 interrupted = -1;
                 continue;
             }
@@ -896,21 +1233,21 @@ int main(int argc, char *argv[])
             }
 
             /* Put the response on the ring */
-            put_response(&xenaccess->vm_event, &rsp);
-        }
+            if (req.flags & VM_EVENT_FLAG_VCPU_PAUSED)
+                put_response(&xenaccess->vm_event, &rsp, ports[current_index]);
 
-        /* Tell Xen page is ready */
-        rc = xenevtchn_notify(xenaccess->vm_event.xce_handle,
-                              xenaccess->vm_event.port);
-
-        if ( rc != 0 )
-        {
-            ERROR("Error resuming page");
-            interrupted = -1;
+            if ( current_index != next_index )
+                if ( xenaccess_notify(&xenaccess->vm_event, 
ports[current_index]) )
+                    interrupted = -1;
         }
 
+        free(ports);
+
         if ( shutting_down )
+        {
+            DPRINTF("Shutting down xenaccess\n");
             break;
+        }
     }
     DPRINTF("xenaccess shut down on signal %d\n", interrupted);
 
-- 
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®.