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
|