ia64/xen-unstable

changeset 17236:ea5ee63548e4

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@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 18 11:29:18 2008 +0000 (2008-03-18)
parents b543b4b759ba
children d0a538659726
files extras/mini-os/arch/ia64/time.c extras/mini-os/arch/x86/time.c extras/mini-os/blkfront.c extras/mini-os/console/xencons_ring.c extras/mini-os/events.c extras/mini-os/fbfront.c extras/mini-os/fs-front.c extras/mini-os/netfront.c extras/mini-os/xenbus/xenbus.c tools/libxc/xc_minios.c
line diff
     1.1 --- a/extras/mini-os/arch/ia64/time.c	Tue Mar 18 11:28:14 2008 +0000
     1.2 +++ b/extras/mini-os/arch/ia64/time.c	Tue Mar 18 11:29:18 2008 +0000
     1.3 @@ -246,7 +246,7 @@ init_time(void)
     1.4  {
     1.5  	uint64_t new;
     1.6  	efi_time_t tm;
     1.7 -	int err = 0;
     1.8 +	evtchn_port_t port = 0;
     1.9  
    1.10  	printk("Initialising time\n");
    1.11  	calculate_frequencies();
    1.12 @@ -267,11 +267,12 @@ init_time(void)
    1.13  	} else
    1.14  		printk("efi_get_time() failed\n");
    1.15  
    1.16 -	err = bind_virq(VIRQ_ITC, timer_interrupt, NULL);
    1.17 -	if (err == -1) {
    1.18 -		printk("XEN timer request chn bind failed %i\n", err);
    1.19 +	port = bind_virq(VIRQ_ITC, timer_interrupt, NULL);
    1.20 +	if (port == -1) {
    1.21 +		printk("XEN timer request chn bind failed %i\n", port);
    1.22  		return;
    1.23  	}
    1.24 +        unmask_evtchn(port);
    1.25  	itc_alt = ia64_get_itc();
    1.26  	itc_at_boot = itc_alt;
    1.27  	new = ia64_get_itc() + itm_val;
     2.1 --- a/extras/mini-os/arch/x86/time.c	Tue Mar 18 11:28:14 2008 +0000
     2.2 +++ b/extras/mini-os/arch/x86/time.c	Tue Mar 18 11:29:18 2008 +0000
     2.3 @@ -222,6 +222,8 @@ static void timer_handler(evtchn_port_t 
     2.4  
     2.5  void init_time(void)
     2.6  {
     2.7 +    evtchn_port_t port;
     2.8      printk("Initialising timer interface\n");
     2.9 -    bind_virq(VIRQ_TIMER, &timer_handler, NULL);
    2.10 +    port = bind_virq(VIRQ_TIMER, &timer_handler, NULL);
    2.11 +    unmask_evtchn(port);
    2.12  }
     3.1 --- a/extras/mini-os/blkfront.c	Tue Mar 18 11:28:14 2008 +0000
     3.2 +++ b/extras/mini-os/blkfront.c	Tue Mar 18 11:29:18 2008 +0000
     3.3 @@ -43,7 +43,7 @@ struct blkfront_dev {
     3.4  
     3.5      struct blkif_front_ring ring;
     3.6      grant_ref_t ring_ref;
     3.7 -    evtchn_port_t evtchn, local_port;
     3.8 +    evtchn_port_t evtchn;
     3.9      blkif_vdev_t handle;
    3.10  
    3.11      char *nodename;
    3.12 @@ -92,14 +92,9 @@ struct blkfront_dev *init_blkfront(char 
    3.13      dev = malloc(sizeof(*dev));
    3.14      dev->nodename = strdup(nodename);
    3.15  
    3.16 -    evtchn_alloc_unbound_t op;
    3.17 -    op.dom = DOMID_SELF;
    3.18      snprintf(path, sizeof(path), "%s/backend-id", nodename);
    3.19 -    dev->dom = op.remote_dom = xenbus_read_integer(path); 
    3.20 -    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
    3.21 -    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
    3.22 -    dev->local_port = bind_evtchn(op.port, blkfront_handler, dev);
    3.23 -    dev->evtchn=op.port;
    3.24 +    dev->dom = xenbus_read_integer(path); 
    3.25 +    evtchn_alloc_unbound(dev->dom, blkfront_handler, dev, &dev->evtchn);
    3.26  
    3.27      s = (struct blkif_sring*) alloc_page();
    3.28      memset(s,0,PAGE_SIZE);
    3.29 @@ -194,6 +189,7 @@ done:
    3.30          snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend);
    3.31          dev->flush = xenbus_read_integer(path);
    3.32      }
    3.33 +    unmask_evtchn(dev->evtchn);
    3.34  
    3.35      printk("%u sectors of %u bytes\n", dev->sectors, dev->sector_size);
    3.36      printk("**************************\n");
    3.37 @@ -219,7 +215,7 @@ void shutdown_blkfront(struct blkfront_d
    3.38      err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
    3.39      xenbus_wait_for_value(path,"6");
    3.40  
    3.41 -    unbind_evtchn(dev->local_port);
    3.42 +    unbind_evtchn(dev->evtchn);
    3.43  
    3.44      free(nodename);
    3.45      free(dev->backend);
     4.1 --- a/extras/mini-os/console/xencons_ring.c	Tue Mar 18 11:28:14 2008 +0000
     4.2 +++ b/extras/mini-os/console/xencons_ring.c	Tue Mar 18 11:29:18 2008 +0000
     4.3 @@ -86,6 +86,7 @@ int xencons_ring_init(void)
     4.4  		printk("XEN console request chn bind failed %i\n", err);
     4.5  		return err;
     4.6  	}
     4.7 +        unmask_evtchn(start_info.console.domU.evtchn);
     4.8  
     4.9  	/* In case we have in-flight data after save/restore... */
    4.10  	notify_daemon();
     5.1 --- a/extras/mini-os/events.c	Tue Mar 18 11:28:14 2008 +0000
     5.2 +++ b/extras/mini-os/events.c	Tue Mar 18 11:29:18 2008 +0000
     5.3 @@ -87,9 +87,6 @@ evtchn_port_t bind_evtchn(evtchn_port_t 
     5.4  	wmb();
     5.5  	ev_actions[port].handler = handler;
     5.6  
     5.7 -	/* Finally unmask the port */
     5.8 -	unmask_evtchn(port);
     5.9 -
    5.10  	return port;
    5.11  }
    5.12  
    5.13 @@ -191,8 +188,7 @@ int evtchn_bind_interdomain(domid_t pal,
    5.14      if (err)
    5.15  		return err;
    5.16      set_bit(op.local_port,bound_ports);
    5.17 -	evtchn_port_t port = op.local_port;
    5.18 -    clear_evtchn(port);	      /* Without, handler gets invoked now! */
    5.19 +    evtchn_port_t port = op.local_port;
    5.20      *local_port = bind_evtchn(port, handler, data);
    5.21      return err;
    5.22  }
     6.1 --- a/extras/mini-os/fbfront.c	Tue Mar 18 11:28:14 2008 +0000
     6.2 +++ b/extras/mini-os/fbfront.c	Tue Mar 18 11:29:18 2008 +0000
     6.3 @@ -26,7 +26,7 @@ struct kbdfront_dev {
     6.4      domid_t dom;
     6.5  
     6.6      struct xenkbd_page *page;
     6.7 -    evtchn_port_t evtchn, local_port;
     6.8 +    evtchn_port_t evtchn;
     6.9  
    6.10      char *nodename;
    6.11      char *backend;
    6.12 @@ -68,14 +68,9 @@ struct kbdfront_dev *init_kbdfront(char 
    6.13      dev = malloc(sizeof(*dev));
    6.14      dev->nodename = strdup(nodename);
    6.15  
    6.16 -    evtchn_alloc_unbound_t op;
    6.17 -    op.dom = DOMID_SELF;
    6.18      snprintf(path, sizeof(path), "%s/backend-id", nodename);
    6.19 -    dev->dom = op.remote_dom = xenbus_read_integer(path); 
    6.20 -    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
    6.21 -    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
    6.22 -    dev->local_port = bind_evtchn(op.port, kbdfront_handler, dev);
    6.23 -    dev->evtchn=op.port;
    6.24 +    dev->dom = xenbus_read_integer(path); 
    6.25 +    evtchn_alloc_unbound(dev->dom, kbdfront_handler, dev, &dev->evtchn);
    6.26  
    6.27      dev->page = s = (struct xenkbd_page*) alloc_page();
    6.28      memset(s,0,PAGE_SIZE);
    6.29 @@ -151,6 +146,7 @@ done:
    6.30  
    6.31          err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
    6.32      }
    6.33 +    unmask_evtchn(dev->evtchn);
    6.34  
    6.35      printk("************************** KBDFRONT\n");
    6.36  
    6.37 @@ -208,7 +204,7 @@ void shutdown_kbdfront(struct kbdfront_d
    6.38      err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
    6.39      xenbus_wait_for_value(path,"6");
    6.40  
    6.41 -    unbind_evtchn(dev->local_port);
    6.42 +    unbind_evtchn(dev->evtchn);
    6.43  
    6.44      free_pages(dev->page,0);
    6.45      free(nodename);
    6.46 @@ -241,7 +237,7 @@ struct fbfront_dev {
    6.47      domid_t dom;
    6.48  
    6.49      struct xenfb_page *page;
    6.50 -    evtchn_port_t evtchn, local_port;
    6.51 +    evtchn_port_t evtchn;
    6.52  
    6.53      char *nodename;
    6.54      char *backend;
    6.55 @@ -281,14 +277,9 @@ struct fbfront_dev *init_fbfront(char *n
    6.56      dev = malloc(sizeof(*dev));
    6.57      dev->nodename = strdup(nodename);
    6.58  
    6.59 -    evtchn_alloc_unbound_t op;
    6.60 -    op.dom = DOMID_SELF;
    6.61      snprintf(path, sizeof(path), "%s/backend-id", nodename);
    6.62 -    dev->dom = op.remote_dom = xenbus_read_integer(path); 
    6.63 -    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
    6.64 -    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
    6.65 -    dev->local_port = bind_evtchn(op.port, fbfront_handler, dev);
    6.66 -    dev->evtchn=op.port;
    6.67 +    dev->dom = xenbus_read_integer(path); 
    6.68 +    evtchn_alloc_unbound(dev->dom, fbfront_handler, dev, &dev->evtchn);
    6.69  
    6.70      dev->page = s = (struct xenfb_page*) alloc_page();
    6.71      memset(s,0,PAGE_SIZE);
    6.72 @@ -397,6 +388,7 @@ done:
    6.73  
    6.74          err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
    6.75      }
    6.76 +    unmask_evtchn(dev->evtchn);
    6.77  
    6.78      printk("************************** FBFRONT\n");
    6.79  
    6.80 @@ -462,7 +454,7 @@ void shutdown_fbfront(struct fbfront_dev
    6.81      err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
    6.82      xenbus_wait_for_value(path,"6");
    6.83  
    6.84 -    unbind_evtchn(dev->local_port);
    6.85 +    unbind_evtchn(dev->evtchn);
    6.86  
    6.87      free_pages(dev->page,0);
    6.88      free(nodename);
     7.1 --- a/extras/mini-os/fs-front.c	Tue Mar 18 11:28:14 2008 +0000
     7.2 +++ b/extras/mini-os/fs-front.c	Tue Mar 18 11:29:18 2008 +0000
     7.3 @@ -943,6 +943,7 @@ static int init_fs_import(struct fs_impo
     7.4                                  //ANY_CPU, 
     7.5                                  import, 
     7.6                                  &import->local_port));
     7.7 +    unmask_evtchn(import->local_port);
     7.8  
     7.9      
    7.10      self_id = get_self_id(); 
     8.1 --- a/extras/mini-os/netfront.c	Tue Mar 18 11:28:14 2008 +0000
     8.2 +++ b/extras/mini-os/netfront.c	Tue Mar 18 11:29:18 2008 +0000
     8.3 @@ -48,7 +48,7 @@ struct netfront_dev {
     8.4      struct netif_rx_front_ring rx;
     8.5      grant_ref_t tx_ring_ref;
     8.6      grant_ref_t rx_ring_ref;
     8.7 -    evtchn_port_t evtchn, local_port;
     8.8 +    evtchn_port_t evtchn;
     8.9  
    8.10      char *nodename;
    8.11      char *backend;
    8.12 @@ -301,19 +301,14 @@ struct netfront_dev *init_netfront(char 
    8.13          dev->rx_buffers[i].page = (char*)alloc_page();
    8.14      }
    8.15  
    8.16 -    evtchn_alloc_unbound_t op;
    8.17 -    op.dom = DOMID_SELF;
    8.18      snprintf(path, sizeof(path), "%s/backend-id", nodename);
    8.19 -    dev->dom = op.remote_dom = xenbus_read_integer(path);
    8.20 -    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
    8.21 -    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
    8.22 +    dev->dom = xenbus_read_integer(path);
    8.23  #ifdef HAVE_LIBC
    8.24      if (thenetif_rx == NETIF_SELECT_RX)
    8.25 -	dev->local_port = bind_evtchn(op.port, netfront_select_handler, dev);
    8.26 +        evtchn_alloc_unbound(dev->dom, netfront_select_handler, dev, &dev->evtchn);
    8.27      else
    8.28  #endif
    8.29 -	dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
    8.30 -    dev->evtchn=op.port;
    8.31 +        evtchn_alloc_unbound(dev->dom, netfront_handler, dev, &dev->evtchn);
    8.32  
    8.33      txs = (struct netif_tx_sring*) alloc_page();
    8.34      rxs = (struct netif_rx_sring *) alloc_page();
    8.35 @@ -388,9 +383,9 @@ done:
    8.36      msg = xenbus_read(XBT_NIL, path, &mac);
    8.37  
    8.38      if ((dev->backend == NULL) || (mac == NULL)) {
    8.39 -        struct evtchn_close op = { dev->local_port };
    8.40 +        struct evtchn_close op = { dev->evtchn };
    8.41          printk("%s: backend/mac failed\n", __func__);
    8.42 -        unbind_evtchn(dev->local_port);
    8.43 +        unbind_evtchn(dev->evtchn);
    8.44          HYPERVISOR_event_channel_op(EVTCHNOP_close, &op);
    8.45          return NULL;
    8.46      }
    8.47 @@ -412,6 +407,7 @@ done:
    8.48      printk("**************************\n");
    8.49  
    8.50      init_rx_buffers(dev);
    8.51 +    unmask_evtchn(dev->evtchn);
    8.52  
    8.53          /* Special conversion specifier 'hh' needed for __ia64__. Without
    8.54             this mini-os panics with 'Unaligned reference'. */
    8.55 @@ -460,7 +456,7 @@ void shutdown_netfront(struct netfront_d
    8.56      err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
    8.57      xenbus_wait_for_value(path,"6");
    8.58  
    8.59 -    unbind_evtchn(dev->local_port);
    8.60 +    unbind_evtchn(dev->evtchn);
    8.61  
    8.62      free(nodename);
    8.63      free(dev->backend);
     9.1 --- a/extras/mini-os/xenbus/xenbus.c	Tue Mar 18 11:28:14 2008 +0000
     9.2 +++ b/extras/mini-os/xenbus/xenbus.c	Tue Mar 18 11:29:18 2008 +0000
     9.3 @@ -257,6 +257,7 @@ void init_xenbus(void)
     9.4      err = bind_evtchn(start_info.store_evtchn,
     9.5  		      xenbus_evtchn_handler,
     9.6                NULL);
     9.7 +    unmask_evtchn(start_info.store_evtchn);
     9.8      DEBUG("xenbus on irq %d\n", err);
     9.9  }
    9.10  
    10.1 --- a/tools/libxc/xc_minios.c	Tue Mar 18 11:28:14 2008 +0000
    10.2 +++ b/tools/libxc/xc_minios.c	Tue Mar 18 11:29:18 2008 +0000
    10.3 @@ -165,14 +165,6 @@ static int port_alloc(int xce_handle) {
    10.4      return i;
    10.5  }
    10.6  
    10.7 -static void poke_port(int xce_handle, evtchn_port_t port)
    10.8 -{
    10.9 -    shared_info_t *s = HYPERVISOR_shared_info;
   10.10 -    printk("poking port %d\n", port);
   10.11 -    synch_set_bit(port, &s->evtchn_pending[0]);
   10.12 -    xc_evtchn_unmask(xce_handle, port);
   10.13 -}
   10.14 -
   10.15  static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
   10.16  {
   10.17      int xce_handle = (intptr_t) data;
   10.18 @@ -211,6 +203,7 @@ evtchn_port_or_error_t xc_evtchn_bind_un
   10.19      }
   10.20      files[xce_handle].evtchn.ports[i].bound = 1;
   10.21      files[xce_handle].evtchn.ports[i].port = port;
   10.22 +    unmask_evtchn(port);
   10.23      return port;
   10.24  }
   10.25  
   10.26 @@ -235,9 +228,7 @@ evtchn_port_or_error_t xc_evtchn_bind_in
   10.27      }
   10.28      files[xce_handle].evtchn.ports[i].bound = 1;
   10.29      files[xce_handle].evtchn.ports[i].port = local_port;
   10.30 -/* Poke port on start: HVM won't send an event for the very first request since
   10.31 - * we were not ready yet */
   10.32 -    poke_port(xce_handle, local_port);
   10.33 +    unmask_evtchn(local_port);
   10.34      return local_port;
   10.35  }
   10.36  
   10.37 @@ -275,6 +266,7 @@ evtchn_port_or_error_t xc_evtchn_bind_vi
   10.38      }
   10.39      files[xce_handle].evtchn.ports[i].bound = 1;
   10.40      files[xce_handle].evtchn.ports[i].port = port;
   10.41 +    unmask_evtchn(port);
   10.42      return port;
   10.43  }
   10.44