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

[Xen-devel] [PATCH] minios: Fix lost events



minios: Fix lost events

evtchn_bind_interdomain used to clear any already pending event before
binding a handler, because else the handler may be called before it is
ready. That however leads to missed events, which I had to workaround
for the HVM case.

This changes the semantics of bind_evtchn, and thus of all the
event channel binding functions (bind_virq, evtchn_alloc_unbound,
evtchn_bind_interdomain) into not unmasking the event itself, hence
letting the caller initialize properly before unmasking the port (e.g.
record the port number in an appropriate place).

Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>

diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/arch/ia64/time.c
--- a/extras/mini-os/arch/ia64/time.c   Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/arch/ia64/time.c   Mon Mar 17 19:23:10 2008 +0000
@@ -246,7 +246,7 @@ init_time(void)
 {
        uint64_t new;
        efi_time_t tm;
-       int err = 0;
+       evtchn_port_t port = 0;
 
        printk("Initialising time\n");
        calculate_frequencies();
@@ -267,11 +267,12 @@ init_time(void)
        } else
                printk("efi_get_time() failed\n");
 
-       err = bind_virq(VIRQ_ITC, timer_interrupt, NULL);
-       if (err == -1) {
-               printk("XEN timer request chn bind failed %i\n", err);
+       port = bind_virq(VIRQ_ITC, timer_interrupt, NULL);
+       if (port == -1) {
+               printk("XEN timer request chn bind failed %i\n", port);
                return;
        }
+        unmask_evtchn(port);
        itc_alt = ia64_get_itc();
        itc_at_boot = itc_alt;
        new = ia64_get_itc() + itm_val;
diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/arch/x86/time.c
--- a/extras/mini-os/arch/x86/time.c    Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/arch/x86/time.c    Mon Mar 17 19:23:10 2008 +0000
@@ -222,6 +222,8 @@ static void timer_handler(evtchn_port_t 
 
 void init_time(void)
 {
+    evtchn_port_t port;
     printk("Initialising timer interface\n");
-    bind_virq(VIRQ_TIMER, &timer_handler, NULL);
+    port = bind_virq(VIRQ_TIMER, &timer_handler, NULL);
+    unmask_evtchn(port);
 }
diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/blkfront.c
--- a/extras/mini-os/blkfront.c Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/blkfront.c Mon Mar 17 19:23:10 2008 +0000
@@ -43,7 +43,7 @@ struct blkfront_dev {
 
     struct blkif_front_ring ring;
     grant_ref_t ring_ref;
-    evtchn_port_t evtchn, local_port;
+    evtchn_port_t evtchn;
     blkif_vdev_t handle;
 
     char *nodename;
@@ -92,14 +92,9 @@ struct blkfront_dev *init_blkfront(char 
     dev = malloc(sizeof(*dev));
     dev->nodename = strdup(nodename);
 
-    evtchn_alloc_unbound_t op;
-    op.dom = DOMID_SELF;
     snprintf(path, sizeof(path), "%s/backend-id", nodename);
-    dev->dom = op.remote_dom = xenbus_read_integer(path); 
-    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
-    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
-    dev->local_port = bind_evtchn(op.port, blkfront_handler, dev);
-    dev->evtchn=op.port;
+    dev->dom = xenbus_read_integer(path); 
+    evtchn_alloc_unbound(dev->dom, blkfront_handler, dev, &dev->evtchn);
 
     s = (struct blkif_sring*) alloc_page();
     memset(s,0,PAGE_SIZE);
@@ -194,6 +189,7 @@ done:
         snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend);
         dev->flush = xenbus_read_integer(path);
     }
+    unmask_evtchn(dev->evtchn);
 
     printk("%u sectors of %u bytes\n", dev->sectors, dev->sector_size);
     printk("**************************\n");
@@ -219,7 +215,7 @@ void shutdown_blkfront(struct blkfront_d
     err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
     xenbus_wait_for_value(path,"6");
 
-    unbind_evtchn(dev->local_port);
+    unbind_evtchn(dev->evtchn);
 
     free(nodename);
     free(dev->backend);
diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/console/xencons_ring.c
--- a/extras/mini-os/console/xencons_ring.c     Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/console/xencons_ring.c     Mon Mar 17 19:23:10 2008 +0000
@@ -91,6 +91,7 @@ int xencons_ring_init(void)
                printk("XEN console request chn bind failed %i\n", err);
                return err;
        }
+        unmask_evtchn(start_info.console.domU.evtchn);
 
        /* In case we have in-flight data after save/restore... */
        notify_daemon();
diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/events.c
--- a/extras/mini-os/events.c   Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/events.c   Mon Mar 17 19:23:10 2008 +0000
@@ -86,9 +86,6 @@ evtchn_port_t bind_evtchn(evtchn_port_t 
        ev_actions[port].data = data;
        wmb();
        ev_actions[port].handler = handler;
-
-       /* Finally unmask the port */
-       unmask_evtchn(port);
 
        return port;
 }
@@ -191,8 +188,7 @@ int evtchn_bind_interdomain(domid_t pal,
     if (err)
                return err;
     set_bit(op.local_port,bound_ports);
-       evtchn_port_t port = op.local_port;
-    clear_evtchn(port);              /* Without, handler gets invoked now! */
+    evtchn_port_t port = op.local_port;
     *local_port = bind_evtchn(port, handler, data);
     return err;
 }
diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/fbfront.c
--- a/extras/mini-os/fbfront.c  Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/fbfront.c  Mon Mar 17 19:23:10 2008 +0000
@@ -26,7 +26,7 @@ struct kbdfront_dev {
     domid_t dom;
 
     struct xenkbd_page *page;
-    evtchn_port_t evtchn, local_port;
+    evtchn_port_t evtchn;
 
     char *nodename;
     char *backend;
@@ -68,14 +68,9 @@ struct kbdfront_dev *init_kbdfront(char 
     dev = malloc(sizeof(*dev));
     dev->nodename = strdup(nodename);
 
-    evtchn_alloc_unbound_t op;
-    op.dom = DOMID_SELF;
     snprintf(path, sizeof(path), "%s/backend-id", nodename);
-    dev->dom = op.remote_dom = xenbus_read_integer(path); 
-    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
-    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
-    dev->local_port = bind_evtchn(op.port, kbdfront_handler, dev);
-    dev->evtchn=op.port;
+    dev->dom = xenbus_read_integer(path); 
+    evtchn_alloc_unbound(dev->dom, kbdfront_handler, dev, &dev->evtchn);
 
     dev->page = s = (struct xenkbd_page*) alloc_page();
     memset(s,0,PAGE_SIZE);
@@ -151,6 +146,7 @@ done:
 
         err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected 
*/
     }
+    unmask_evtchn(dev->evtchn);
 
     printk("************************** KBDFRONT\n");
 
@@ -208,7 +204,7 @@ void shutdown_kbdfront(struct kbdfront_d
     err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
     xenbus_wait_for_value(path,"6");
 
-    unbind_evtchn(dev->local_port);
+    unbind_evtchn(dev->evtchn);
 
     free_pages(dev->page,0);
     free(nodename);
@@ -241,7 +237,7 @@ struct fbfront_dev {
     domid_t dom;
 
     struct xenfb_page *page;
-    evtchn_port_t evtchn, local_port;
+    evtchn_port_t evtchn;
 
     char *nodename;
     char *backend;
@@ -282,14 +278,9 @@ struct fbfront_dev *init_fbfront(char *n
     dev = malloc(sizeof(*dev));
     dev->nodename = strdup(nodename);
 
-    evtchn_alloc_unbound_t op;
-    op.dom = DOMID_SELF;
     snprintf(path, sizeof(path), "%s/backend-id", nodename);
-    dev->dom = op.remote_dom = xenbus_read_integer(path); 
-    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
-    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
-    dev->local_port = bind_evtchn(op.port, fbfront_handler, dev);
-    dev->evtchn=op.port;
+    dev->dom = xenbus_read_integer(path); 
+    evtchn_alloc_unbound(dev->dom, fbfront_handler, dev, &dev->evtchn);
 
     dev->page = s = (struct xenfb_page*) alloc_page();
     memset(s,0,PAGE_SIZE);
@@ -399,6 +390,7 @@ done:
 
         err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected 
*/
     }
+    unmask_evtchn(dev->evtchn);
 
     printk("************************** FBFRONT\n");
 
@@ -485,7 +477,7 @@ void shutdown_fbfront(struct fbfront_dev
     err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
     xenbus_wait_for_value(path,"6");
 
-    unbind_evtchn(dev->local_port);
+    unbind_evtchn(dev->evtchn);
 
     free_pages(dev->page,0);
     free(nodename);
diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/fs-front.c
--- a/extras/mini-os/fs-front.c Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/fs-front.c Mon Mar 17 19:23:10 2008 +0000
@@ -943,6 +943,7 @@ static int init_fs_import(struct fs_impo
                                 //ANY_CPU, 
                                 import, 
                                 &import->local_port));
+    unmask_evtchn(import->local_port);
 
     
     self_id = get_self_id(); 
diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/netfront.c
--- a/extras/mini-os/netfront.c Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/netfront.c Mon Mar 17 19:23:10 2008 +0000
@@ -48,7 +48,7 @@ struct netfront_dev {
     struct netif_rx_front_ring rx;
     grant_ref_t tx_ring_ref;
     grant_ref_t rx_ring_ref;
-    evtchn_port_t evtchn, local_port;
+    evtchn_port_t evtchn;
 
     char *nodename;
     char *backend;
@@ -301,19 +301,14 @@ struct netfront_dev *init_netfront(char 
         dev->rx_buffers[i].page = (char*)alloc_page();
     }
 
-    evtchn_alloc_unbound_t op;
-    op.dom = DOMID_SELF;
     snprintf(path, sizeof(path), "%s/backend-id", nodename);
-    dev->dom = op.remote_dom = xenbus_read_integer(path);
-    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
-    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
+    dev->dom = xenbus_read_integer(path);
 #ifdef HAVE_LIBC
     if (thenetif_rx == NETIF_SELECT_RX)
-       dev->local_port = bind_evtchn(op.port, netfront_select_handler, dev);
+        evtchn_alloc_unbound(dev->dom, netfront_select_handler, dev, 
&dev->evtchn);
     else
 #endif
-       dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
-    dev->evtchn=op.port;
+        evtchn_alloc_unbound(dev->dom, netfront_handler, dev, &dev->evtchn);
 
     txs = (struct netif_tx_sring*) alloc_page();
     rxs = (struct netif_rx_sring *) alloc_page();
@@ -388,9 +383,9 @@ done:
     msg = xenbus_read(XBT_NIL, path, &mac);
 
     if ((dev->backend == NULL) || (mac == NULL)) {
-        struct evtchn_close op = { dev->local_port };
+        struct evtchn_close op = { dev->evtchn };
         printk("%s: backend/mac failed\n", __func__);
-        unbind_evtchn(dev->local_port);
+        unbind_evtchn(dev->evtchn);
         HYPERVISOR_event_channel_op(EVTCHNOP_close, &op);
         return NULL;
     }
@@ -412,6 +407,7 @@ done:
     printk("**************************\n");
 
     init_rx_buffers(dev);
+    unmask_evtchn(dev->evtchn);
 
         /* Special conversion specifier 'hh' needed for __ia64__. Without
            this mini-os panics with 'Unaligned reference'. */
@@ -460,7 +456,7 @@ void shutdown_netfront(struct netfront_d
     err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
     xenbus_wait_for_value(path,"6");
 
-    unbind_evtchn(dev->local_port);
+    unbind_evtchn(dev->evtchn);
 
     free(nodename);
     free(dev->backend);
diff -r c149cedf76b9 -r d4b232bea2eb extras/mini-os/xenbus/xenbus.c
--- a/extras/mini-os/xenbus/xenbus.c    Tue Mar 11 17:47:01 2008 +0000
+++ b/extras/mini-os/xenbus/xenbus.c    Mon Mar 17 19:23:10 2008 +0000
@@ -257,6 +257,7 @@ void init_xenbus(void)
     err = bind_evtchn(start_info.store_evtchn,
                      xenbus_evtchn_handler,
               NULL);
+    unmask_evtchn(start_info.store_evtchn);
     DEBUG("xenbus on irq %d\n", err);
 }
 
diff -r c149cedf76b9 -r d4b232bea2eb tools/libxc/xc_minios.c
--- a/tools/libxc/xc_minios.c   Tue Mar 11 17:47:01 2008 +0000
+++ b/tools/libxc/xc_minios.c   Mon Mar 17 19:23:10 2008 +0000
@@ -165,14 +165,6 @@ static int port_alloc(int xce_handle) {
     return i;
 }
 
-static void poke_port(int xce_handle, evtchn_port_t port)
-{
-    shared_info_t *s = HYPERVISOR_shared_info;
-    printk("poking port %d\n", port);
-    synch_set_bit(port, &s->evtchn_pending[0]);
-    xc_evtchn_unmask(xce_handle, port);
-}
-
 static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void 
*data)
 {
     int xce_handle = (intptr_t) data;
@@ -211,6 +203,7 @@ evtchn_port_or_error_t xc_evtchn_bind_un
     }
     files[xce_handle].evtchn.ports[i].bound = 1;
     files[xce_handle].evtchn.ports[i].port = port;
+    unmask_evtchn(port);
     return port;
 }
 
@@ -235,9 +228,7 @@ evtchn_port_or_error_t xc_evtchn_bind_in
     }
     files[xce_handle].evtchn.ports[i].bound = 1;
     files[xce_handle].evtchn.ports[i].port = local_port;
-/* Poke port on start: HVM won't send an event for the very first request since
- * we were not ready yet */
-    poke_port(xce_handle, local_port);
+    unmask_evtchn(local_port);
     return local_port;
 }
 
@@ -275,6 +266,7 @@ evtchn_port_or_error_t xc_evtchn_bind_vi
     }
     files[xce_handle].evtchn.ports[i].bound = 1;
     files[xce_handle].evtchn.ports[i].port = port;
+    unmask_evtchn(port);
     return port;
 }
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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