ia64/xen-unstable

changeset 7250:37bea65ed6ca

Big simplification of the Xen event-channel interface.
EVTCHNOP_bind_interdomain in particular is much simpler.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Oct 07 10:57:13 2005 +0100 (2005-10-07)
parents 48df3efaf61c
children ddb803b6308b a6420243710d
files linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c linux-2.6-xen-sparse/drivers/xen/blkback/interface.c linux-2.6-xen-sparse/drivers/xen/blktap/interface.c linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c linux-2.6-xen-sparse/drivers/xen/netback/interface.c linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c linux-2.6-xen-sparse/include/asm-xen/evtchn.h tools/ioemu/vl.c tools/python/xen/lowlevel/xc/xc.c tools/python/xen/xend/XendDomainInfo.py xen/common/event_channel.c xen/include/public/event_channel.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c	Fri Oct 07 00:21:00 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c	Fri Oct 07 10:57:13 2005 +0100
     1.3 @@ -219,7 +219,6 @@ void unbind_virq_from_irq(int virq)
     1.4  	spin_lock(&irq_mapping_update_lock);
     1.5  
     1.6  	if (--irq_bindcount[irq] == 0) {
     1.7 -		op.u.close.dom  = DOMID_SELF;
     1.8  		op.u.close.port = evtchn;
     1.9  		BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
    1.10  
    1.11 @@ -283,7 +282,6 @@ void unbind_ipi_from_irq(int ipi)
    1.12  	spin_lock(&irq_mapping_update_lock);
    1.13  
    1.14  	if (--irq_bindcount[irq] == 0) {
    1.15 -		op.u.close.dom  = DOMID_SELF;
    1.16  		op.u.close.port = evtchn;
    1.17  		BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
    1.18  
    1.19 @@ -326,7 +324,6 @@ void unbind_evtchn_from_irq(unsigned int
    1.20  	spin_lock(&irq_mapping_update_lock);
    1.21  
    1.22  	if ((--irq_bindcount[irq] == 0) && (evtchn != -1)) {
    1.23 -		op.u.close.dom  = DOMID_SELF;
    1.24  		op.u.close.port = evtchn;
    1.25  		BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
    1.26  
    1.27 @@ -513,7 +510,10 @@ static inline void pirq_query_unmask(int
    1.28  static unsigned int startup_pirq(unsigned int irq)
    1.29  {
    1.30  	evtchn_op_t op = { .cmd = EVTCHNOP_bind_pirq };
    1.31 -	int evtchn;
    1.32 +	int evtchn = irq_to_evtchn[irq];
    1.33 +
    1.34 +	if (VALID_EVTCHN(evtchn))
    1.35 +		goto out;
    1.36  
    1.37  	op.u.bind_pirq.pirq  = irq;
    1.38  	/* NB. We are happy to share unless we are probing. */
    1.39 @@ -532,6 +532,7 @@ static unsigned int startup_pirq(unsigne
    1.40  	evtchn_to_irq[evtchn] = irq;
    1.41  	irq_to_evtchn[irq]    = evtchn;
    1.42  
    1.43 + out:
    1.44  	unmask_evtchn(evtchn);
    1.45  	pirq_unmask_notify(irq_to_pirq(irq));
    1.46  
    1.47 @@ -548,7 +549,6 @@ static void shutdown_pirq(unsigned int i
    1.48  
    1.49  	mask_evtchn(evtchn);
    1.50  
    1.51 -	op.u.close.dom  = DOMID_SELF;
    1.52  	op.u.close.port = evtchn;
    1.53  	BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
    1.54  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c	Fri Oct 07 00:21:00 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c	Fri Oct 07 10:57:13 2005 +0100
     2.3 @@ -71,10 +71,8 @@ int blkif_map(blkif_t *blkif, unsigned l
     2.4  	int err;
     2.5  	evtchn_op_t op = {
     2.6  		.cmd = EVTCHNOP_bind_interdomain,
     2.7 -		.u.bind_interdomain.dom1 = DOMID_SELF,
     2.8 -		.u.bind_interdomain.dom2 = blkif->domid,
     2.9 -		.u.bind_interdomain.port1 = 0,
    2.10 -		.u.bind_interdomain.port2 = evtchn };
    2.11 +		.u.bind_interdomain.remote_dom = blkif->domid,
    2.12 +		.u.bind_interdomain.remote_port = evtchn };
    2.13  
    2.14  	if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
    2.15  		return -ENOMEM;
    2.16 @@ -92,7 +90,7 @@ int blkif_map(blkif_t *blkif, unsigned l
    2.17  		return err;
    2.18  	}
    2.19  
    2.20 -	blkif->evtchn = op.u.bind_interdomain.port1;
    2.21 +	blkif->evtchn = op.u.bind_interdomain.local_port;
    2.22  
    2.23  	sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
    2.24  	SHARED_RING_INIT(sring);
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c	Fri Oct 07 00:21:00 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c	Fri Oct 07 10:57:13 2005 +0100
     3.3 @@ -71,10 +71,8 @@ int blkif_map(blkif_t *blkif, unsigned l
     3.4  	int err;
     3.5  	evtchn_op_t op = {
     3.6  		.cmd = EVTCHNOP_bind_interdomain,
     3.7 -		.u.bind_interdomain.dom1 = DOMID_SELF,
     3.8 -		.u.bind_interdomain.dom2 = blkif->domid,
     3.9 -		.u.bind_interdomain.port1 = 0,
    3.10 -		.u.bind_interdomain.port2 = evtchn };
    3.11 +		.u.bind_interdomain.remote_dom  = blkif->domid,
    3.12 +		.u.bind_interdomain.remote_port = evtchn };
    3.13  
    3.14  	if ((blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
    3.15  		return -ENOMEM;
    3.16 @@ -92,7 +90,7 @@ int blkif_map(blkif_t *blkif, unsigned l
    3.17  		return err;
    3.18  	}
    3.19  
    3.20 -	blkif->evtchn = op.u.bind_interdomain.port1;
    3.21 +	blkif->evtchn = op.u.bind_interdomain.local_port;
    3.22  
    3.23  	sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
    3.24  	SHARED_RING_INIT(sring);
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c	Fri Oct 07 00:21:00 2005 +0100
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c	Fri Oct 07 10:57:13 2005 +0100
     4.3 @@ -223,7 +223,7 @@ static int evtchn_ioctl(struct inode *in
     4.4  		if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
     4.5  			break;
     4.6  
     4.7 -		op.cmd              = EVTCHNOP_bind_virq;
     4.8 +		op.cmd = EVTCHNOP_bind_virq;
     4.9  		op.u.bind_virq.virq = bind.virq;
    4.10  		op.u.bind_virq.vcpu = 0;
    4.11  		rc = HYPERVISOR_event_channel_op(&op);
    4.12 @@ -243,16 +243,14 @@ static int evtchn_ioctl(struct inode *in
    4.13  		if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
    4.14  			break;
    4.15  
    4.16 -		op.cmd                      = EVTCHNOP_bind_interdomain;
    4.17 -		op.u.bind_interdomain.dom1  = DOMID_SELF;
    4.18 -		op.u.bind_interdomain.dom2  = bind.remote_domain;
    4.19 -		op.u.bind_interdomain.port1 = 0;
    4.20 -		op.u.bind_interdomain.port2 = bind.remote_port;
    4.21 +		op.cmd = EVTCHNOP_bind_interdomain;
    4.22 +		op.u.bind_interdomain.remote_dom  = bind.remote_domain;
    4.23 +		op.u.bind_interdomain.remote_port = bind.remote_port;
    4.24  		rc = HYPERVISOR_event_channel_op(&op);
    4.25  		if (rc != 0)
    4.26  			break;
    4.27  
    4.28 -		rc = op.u.bind_interdomain.port1;
    4.29 +		rc = op.u.bind_interdomain.local_port;
    4.30  		port_user[rc] = u;
    4.31  		unmask_evtchn(rc);
    4.32  		break;
    4.33 @@ -265,7 +263,7 @@ static int evtchn_ioctl(struct inode *in
    4.34  		if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
    4.35  			break;
    4.36  
    4.37 -		op.cmd                        = EVTCHNOP_alloc_unbound;
    4.38 +		op.cmd = EVTCHNOP_alloc_unbound;
    4.39  		op.u.alloc_unbound.dom        = DOMID_SELF;
    4.40  		op.u.alloc_unbound.remote_dom = bind.remote_domain;
    4.41  		rc = HYPERVISOR_event_channel_op(&op);
    4.42 @@ -292,6 +290,11 @@ static int evtchn_ioctl(struct inode *in
    4.43  		} else {
    4.44  			port_user[unbind.port] = NULL;
    4.45  			mask_evtchn(unbind.port);
    4.46 +
    4.47 +			op.cmd = EVTCHNOP_close;
    4.48 +			op.u.close.port = unbind.port;
    4.49 +			BUG_ON(HYPERVISOR_event_channel_op(&op));
    4.50 +
    4.51  			rc = 0;
    4.52  		}
    4.53  		break;
    4.54 @@ -390,8 +393,7 @@ static int evtchn_release(struct inode *
    4.55  		port_user[i] = NULL;
    4.56  		mask_evtchn(i);
    4.57  
    4.58 -		op.cmd          = EVTCHNOP_close;
    4.59 -		op.u.close.dom  = DOMID_SELF;
    4.60 +		op.cmd = EVTCHNOP_close;
    4.61  		op.u.close.port = i;
    4.62  		BUG_ON(HYPERVISOR_event_channel_op(&op));
    4.63  	}
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Fri Oct 07 00:21:00 2005 +0100
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Fri Oct 07 10:57:13 2005 +0100
     5.3 @@ -180,10 +180,8 @@ int netif_map(netif_t *netif, unsigned l
     5.4  	int err;
     5.5  	evtchn_op_t op = {
     5.6  		.cmd = EVTCHNOP_bind_interdomain,
     5.7 -		.u.bind_interdomain.dom1 = DOMID_SELF,
     5.8 -		.u.bind_interdomain.dom2 = netif->domid,
     5.9 -		.u.bind_interdomain.port1 = 0,
    5.10 -		.u.bind_interdomain.port2 = evtchn };
    5.11 +		.u.bind_interdomain.remote_dom = netif->domid,
    5.12 +		.u.bind_interdomain.remote_port = evtchn };
    5.13  
    5.14  	netif->comms_area = alloc_vm_area(2*PAGE_SIZE);
    5.15  	if (netif->comms_area == NULL)
    5.16 @@ -202,7 +200,7 @@ int netif_map(netif_t *netif, unsigned l
    5.17  		return err;
    5.18  	}
    5.19  
    5.20 -	netif->evtchn = op.u.bind_interdomain.port1;
    5.21 +	netif->evtchn = op.u.bind_interdomain.local_port;
    5.22  
    5.23  	netif->irq = bind_evtchn_to_irqhandler(
    5.24  		netif->evtchn, netif_be_int, 0, netif->dev->name, netif);
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c	Fri Oct 07 00:21:00 2005 +0100
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c	Fri Oct 07 10:57:13 2005 +0100
     6.3 @@ -120,10 +120,8 @@ tpmif_map(tpmif_t *tpmif, unsigned long 
     6.4  	int err;
     6.5  	evtchn_op_t op = {
     6.6  		.cmd = EVTCHNOP_bind_interdomain,
     6.7 -		.u.bind_interdomain.dom1 = DOMID_SELF,
     6.8 -		.u.bind_interdomain.dom2 = tpmif->domid,
     6.9 -		.u.bind_interdomain.port1 = 0,
    6.10 -		.u.bind_interdomain.port2 = evtchn };
    6.11 +		.u.bind_interdomain.remote_dom = tpmif->domid,
    6.12 +		.u.bind_interdomain.remote_port = evtchn };
    6.13  
    6.14  	if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
    6.15  		return -ENOMEM;
    6.16 @@ -141,7 +139,7 @@ tpmif_map(tpmif_t *tpmif, unsigned long 
    6.17  		return err;
    6.18  	}
    6.19  
    6.20 -	tpmif->evtchn = op.u.bind_interdomain.port1;
    6.21 +	tpmif->evtchn = op.u.bind_interdomain.local_port;
    6.22  
    6.23  	tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr;
    6.24  
     7.1 --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h	Fri Oct 07 00:21:00 2005 +0100
     7.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h	Fri Oct 07 10:57:13 2005 +0100
     7.3 @@ -123,9 +123,9 @@ static inline void clear_evtchn(int port
     7.4  
     7.5  static inline void notify_remote_via_evtchn(int port)
     7.6  {
     7.7 -	evtchn_op_t op = {
     7.8 -		.cmd = EVTCHNOP_send,
     7.9 -		.u.send.local_port = port };
    7.10 +	evtchn_op_t op;
    7.11 +	op.cmd         = EVTCHNOP_send,
    7.12 +	op.u.send.port = port;
    7.13  	(void)HYPERVISOR_event_channel_op(&op);
    7.14  }
    7.15  
     8.1 --- a/tools/ioemu/vl.c	Fri Oct 07 00:21:00 2005 +0100
     8.2 +++ b/tools/ioemu/vl.c	Fri Oct 07 10:57:13 2005 +0100
     8.3 @@ -2806,7 +2806,7 @@ int main(int argc, char **argv)
     8.4  
     8.5              case QEMU_OPTION_p:
     8.6                  {
     8.7 -                  extern short ioreq_remote_port;
     8.8 +                  extern u16 ioreq_remote_port;
     8.9                    ioreq_remote_port = atoi(optarg);
    8.10                    printf("port: %d\n", ioreq_remote_port);
    8.11                  }
     9.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Fri Oct 07 00:21:00 2005 +0100
     9.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Fri Oct 07 10:57:13 2005 +0100
     9.3 @@ -432,13 +432,13 @@ static PyObject *pyxc_evtchn_alloc_unbou
     9.4  {
     9.5      XcObject *xc = (XcObject *)self;
     9.6  
     9.7 -    u32 dom = DOMID_SELF, remote_dom;
     9.8 +    u32 dom, remote_dom;
     9.9      int port;
    9.10  
    9.11 -    static char *kwd_list[] = { "remote_dom", "dom", NULL };
    9.12 +    static char *kwd_list[] = { "dom", "remote_dom", NULL };
    9.13  
    9.14 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
    9.15 -                                      &remote_dom, &dom) )
    9.16 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
    9.17 +                                      &dom, &remote_dom) )
    9.18          return NULL;
    9.19  
    9.20      if ( (port = xc_evtchn_alloc_unbound(xc->xc_handle, dom, remote_dom)) < 0 )
    9.21 @@ -943,8 +943,9 @@ static PyMethodDef pyxc_methods[] = {
    9.22      { "evtchn_alloc_unbound", 
    9.23        (PyCFunction)pyxc_evtchn_alloc_unbound,
    9.24        METH_VARARGS | METH_KEYWORDS, "\n"
    9.25 -      "Allocate an unbound local port that will await a remote connection.\n"
    9.26 -      " dom [int]: Remote domain to accept connections from.\n\n"
    9.27 +      "Allocate an unbound port that will await a remote connection.\n"
    9.28 +      " dom        [int]: Domain whose port space to allocate from.\n"
    9.29 +      " remote_dom [int]: Remote domain to accept connections from.\n\n"
    9.30        "Returns: [int] Unbound event-channel port.\n" },
    9.31  
    9.32      { "evtchn_status", 
    10.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Fri Oct 07 00:21:00 2005 +0100
    10.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Oct 07 10:57:13 2005 +0100
    10.3 @@ -197,6 +197,7 @@ def recreate(xeninfo):
    10.4          log.info("Recreating domain %d with new UUID %s.", domid, uuid)
    10.5  
    10.6          vm = XendDomainInfo(uuid, xeninfo, domid, True)
    10.7 +        vm.removeDom()
    10.8          vm.storeVmDetails()
    10.9          vm.storeDomDetails()
   10.10  
    11.1 --- a/xen/common/event_channel.c	Fri Oct 07 00:21:00 2005 +0100
    11.2 +++ b/xen/common/event_channel.c	Fri Oct 07 10:57:13 2005 +0100
    11.3 @@ -70,7 +70,7 @@ static long evtchn_alloc_unbound(evtchn_
    11.4  {
    11.5      struct evtchn *chn;
    11.6      struct domain *d;
    11.7 -    int            port = alloc->port;
    11.8 +    int            port;
    11.9      domid_t        dom = alloc->dom;
   11.10      long           rc = 0;
   11.11  
   11.12 @@ -84,176 +84,80 @@ static long evtchn_alloc_unbound(evtchn_
   11.13  
   11.14      spin_lock(&d->evtchn_lock);
   11.15  
   11.16 -    /* Obtain, or ensure that we already have, a valid <port>. */
   11.17 -    if ( port == 0 )
   11.18 -    {
   11.19 -        if ( (port = get_free_port(d)) < 0 )
   11.20 -            ERROR_EXIT(port);
   11.21 -    }
   11.22 -    else if ( !port_is_valid(d, port) )
   11.23 -        ERROR_EXIT(-EINVAL);
   11.24 +    if ( (port = get_free_port(d)) < 0 )
   11.25 +        ERROR_EXIT(port);
   11.26      chn = evtchn_from_port(d, port);
   11.27  
   11.28 -    /* Validate channel's current state. */
   11.29 -    switch ( chn->state )
   11.30 -    {
   11.31 -    case ECS_FREE:
   11.32 -        chn->state = ECS_UNBOUND;
   11.33 -        chn->u.unbound.remote_domid = alloc->remote_dom;
   11.34 -        break;
   11.35 +    chn->state = ECS_UNBOUND;
   11.36 +    chn->u.unbound.remote_domid = alloc->remote_dom;
   11.37  
   11.38 -    case ECS_UNBOUND:
   11.39 -        if ( chn->u.unbound.remote_domid != alloc->remote_dom )
   11.40 -            ERROR_EXIT(-EINVAL);
   11.41 -        break;
   11.42 -
   11.43 -    default:
   11.44 -        ERROR_EXIT(-EINVAL);
   11.45 -    }
   11.46 +    alloc->port = port;
   11.47  
   11.48   out:
   11.49      spin_unlock(&d->evtchn_lock);
   11.50  
   11.51      put_domain(d);
   11.52  
   11.53 -    alloc->port = port;
   11.54 -
   11.55      return rc;
   11.56  }
   11.57  
   11.58  
   11.59  static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
   11.60  {
   11.61 -    struct evtchn *chn1, *chn2;
   11.62 -    struct domain *d1, *d2;
   11.63 -    int            port1 = bind->port1, port2 = bind->port2;
   11.64 -    domid_t        dom1 = bind->dom1, dom2 = bind->dom2;
   11.65 +    struct evtchn *lchn, *rchn;
   11.66 +    struct domain *ld = current->domain, *rd;
   11.67 +    int            lport, rport = bind->remote_port;
   11.68      long           rc = 0;
   11.69  
   11.70 -    if ( !IS_PRIV(current->domain) && (dom1 != DOMID_SELF) )
   11.71 -        return -EPERM;
   11.72 -
   11.73 -    if ( dom1 == DOMID_SELF )
   11.74 -        dom1 = current->domain->domain_id;
   11.75 -    if ( dom2 == DOMID_SELF )
   11.76 -        dom2 = current->domain->domain_id;
   11.77 -
   11.78 -    if ( ((d1 = find_domain_by_id(dom1)) == NULL) ||
   11.79 -         ((d2 = find_domain_by_id(dom2)) == NULL) )
   11.80 -    {
   11.81 -        if ( d1 != NULL )
   11.82 -            put_domain(d1);
   11.83 +    if ( (rd = find_domain_by_id(bind->remote_dom)) == NULL )
   11.84          return -ESRCH;
   11.85 -    }
   11.86  
   11.87      /* Avoid deadlock by first acquiring lock of domain with smaller id. */
   11.88 -    if ( d1 < d2 )
   11.89 +    if ( ld < rd )
   11.90      {
   11.91 -        spin_lock(&d1->evtchn_lock);
   11.92 -        spin_lock(&d2->evtchn_lock);
   11.93 +        spin_lock(&ld->evtchn_lock);
   11.94 +        spin_lock(&rd->evtchn_lock);
   11.95      }
   11.96      else
   11.97      {
   11.98 -        if ( d1 != d2 )
   11.99 -            spin_lock(&d2->evtchn_lock);
  11.100 -        spin_lock(&d1->evtchn_lock);
  11.101 +        if ( ld != rd )
  11.102 +            spin_lock(&rd->evtchn_lock);
  11.103 +        spin_lock(&ld->evtchn_lock);
  11.104      }
  11.105  
  11.106 -    /* Obtain, or ensure that we already have, a valid <port1>. */
  11.107 -    if ( port1 == 0 )
  11.108 -    {
  11.109 -        if ( (port1 = get_free_port(d1)) < 0 )
  11.110 -            ERROR_EXIT(port1);
  11.111 -    }
  11.112 -    else if ( !port_is_valid(d1, port1) )
  11.113 -        ERROR_EXIT(-EINVAL);
  11.114 -    chn1 = evtchn_from_port(d1, port1);
  11.115 -
  11.116 -    /* Obtain, or ensure that we already have, a valid <port2>. */
  11.117 -    if ( port2 == 0 )
  11.118 -    {
  11.119 -        /* Make port1 non-free while we allocate port2 (in case dom1==dom2). */
  11.120 -        u16 state = chn1->state;
  11.121 -        chn1->state = ECS_INTERDOMAIN;
  11.122 -        port2 = get_free_port(d2);
  11.123 -        chn1->state = state;
  11.124 -        if ( port2 < 0 )
  11.125 -            ERROR_EXIT(port2);
  11.126 -    }
  11.127 -    else if ( !port_is_valid(d2, port2) )
  11.128 -        ERROR_EXIT(-EINVAL);
  11.129 -    chn2 = evtchn_from_port(d2, port2);
  11.130 -
  11.131 -    /* Validate <dom1,port1>'s current state. */
  11.132 -    switch ( chn1->state )
  11.133 -    {
  11.134 -    case ECS_FREE:
  11.135 -        break;
  11.136 -
  11.137 -    case ECS_UNBOUND:
  11.138 -        if ( chn1->u.unbound.remote_domid != dom2 )
  11.139 -            ERROR_EXIT(-EINVAL);
  11.140 -        break;
  11.141 +    if ( (lport = get_free_port(ld)) < 0 )
  11.142 +        ERROR_EXIT(lport);
  11.143 +    lchn = evtchn_from_port(ld, lport);
  11.144  
  11.145 -    case ECS_INTERDOMAIN:
  11.146 -        if ( chn1->u.interdomain.remote_dom != d2 )
  11.147 -            ERROR_EXIT(-EINVAL);
  11.148 -        if ( (chn1->u.interdomain.remote_port != port2) && (bind->port2 != 0) )
  11.149 -            ERROR_EXIT(-EINVAL);
  11.150 -        port2 = chn1->u.interdomain.remote_port;
  11.151 -        goto out;
  11.152 -
  11.153 -    default:
  11.154 +    if ( !port_is_valid(rd, rport) )
  11.155          ERROR_EXIT(-EINVAL);
  11.156 -    }
  11.157 +    rchn = evtchn_from_port(rd, rport);
  11.158 +    if ( (rchn->state != ECS_UNBOUND) ||
  11.159 +         (rchn->u.unbound.remote_domid != ld->domain_id) )
  11.160 +        ERROR_EXIT(-EINVAL);
  11.161  
  11.162 -    /* Validate <dom2,port2>'s current state. */
  11.163 -    switch ( chn2->state )
  11.164 -    {
  11.165 -    case ECS_FREE:
  11.166 -        if ( !IS_PRIV(current->domain) && (dom2 != DOMID_SELF) )
  11.167 -            ERROR_EXIT(-EPERM);
  11.168 -        break;
  11.169 -
  11.170 -    case ECS_UNBOUND:
  11.171 -        if ( chn2->u.unbound.remote_domid != dom1 )
  11.172 -            ERROR_EXIT(-EINVAL);
  11.173 -        break;
  11.174 -
  11.175 -    case ECS_INTERDOMAIN:
  11.176 -        if ( chn2->u.interdomain.remote_dom != d1 )
  11.177 -            ERROR_EXIT(-EINVAL);
  11.178 -        if ( (chn2->u.interdomain.remote_port != port1) && (bind->port1 != 0) )
  11.179 -            ERROR_EXIT(-EINVAL);
  11.180 -        port1 = chn2->u.interdomain.remote_port;
  11.181 -        goto out;
  11.182 -
  11.183 -    default:
  11.184 -        ERROR_EXIT(-EINVAL);
  11.185 -    }
  11.186 +    lchn->u.interdomain.remote_dom  = rd;
  11.187 +    lchn->u.interdomain.remote_port = (u16)rport;
  11.188 +    lchn->state                     = ECS_INTERDOMAIN;
  11.189 +    
  11.190 +    rchn->u.interdomain.remote_dom  = ld;
  11.191 +    rchn->u.interdomain.remote_port = (u16)lport;
  11.192 +    rchn->state                     = ECS_INTERDOMAIN;
  11.193  
  11.194      /*
  11.195 -     * Everything checked out okay -- bind <dom1,port1> to <dom2,port2>.
  11.196 +     * We may have lost notifications on the remote unbound port. Fix that up
  11.197 +     * here by conservatively always setting a notification on the local port.
  11.198       */
  11.199 +    evtchn_set_pending(ld->vcpu[lchn->notify_vcpu_id], lport);
  11.200  
  11.201 -    chn1->u.interdomain.remote_dom  = d2;
  11.202 -    chn1->u.interdomain.remote_port = (u16)port2;
  11.203 -    chn1->state                     = ECS_INTERDOMAIN;
  11.204 -    
  11.205 -    chn2->u.interdomain.remote_dom  = d1;
  11.206 -    chn2->u.interdomain.remote_port = (u16)port1;
  11.207 -    chn2->state                     = ECS_INTERDOMAIN;
  11.208 +    bind->local_port = lport;
  11.209  
  11.210   out:
  11.211 -    spin_unlock(&d1->evtchn_lock);
  11.212 -    if ( d1 != d2 )
  11.213 -        spin_unlock(&d2->evtchn_lock);
  11.214 +    spin_unlock(&ld->evtchn_lock);
  11.215 +    if ( ld != rd )
  11.216 +        spin_unlock(&rd->evtchn_lock);
  11.217      
  11.218 -    put_domain(d1);
  11.219 -    put_domain(d2);
  11.220 -
  11.221 -    bind->port1 = port1;
  11.222 -    bind->port2 = port2;
  11.223 +    put_domain(rd);
  11.224  
  11.225      return rc;
  11.226  }
  11.227 @@ -264,39 +168,34 @@ static long evtchn_bind_virq(evtchn_bind
  11.228      struct evtchn *chn;
  11.229      struct vcpu   *v;
  11.230      struct domain *d = current->domain;
  11.231 -    int            port, virq = bind->virq;
  11.232 +    int            port, virq = bind->virq, vcpu = bind->vcpu;
  11.233 +    long           rc = 0;
  11.234  
  11.235      if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) )
  11.236          return -EINVAL;
  11.237  
  11.238 -    if ( (v = d->vcpu[bind->vcpu]) == NULL )
  11.239 +    if ( (vcpu >= ARRAY_SIZE(d->vcpu)) || ((v = d->vcpu[vcpu]) == NULL) )
  11.240          return -ENOENT;
  11.241  
  11.242      spin_lock(&d->evtchn_lock);
  11.243  
  11.244 -    /*
  11.245 -     * Port 0 is the fallback port for VIRQs that haven't been explicitly
  11.246 -     * bound yet.
  11.247 -     */
  11.248 -    if ( ((port = v->virq_to_evtchn[virq]) != 0) ||
  11.249 -         ((port = get_free_port(d)) < 0) )
  11.250 -        goto out;
  11.251 +    if ( v->virq_to_evtchn[virq] != 0 )
  11.252 +        ERROR_EXIT(-EEXIST);
  11.253 +
  11.254 +    if ( (port = get_free_port(d)) < 0 )
  11.255 +        ERROR_EXIT(port);
  11.256  
  11.257      chn = evtchn_from_port(d, port);
  11.258      chn->state          = ECS_VIRQ;
  11.259 -    chn->notify_vcpu_id = v->vcpu_id;
  11.260 +    chn->notify_vcpu_id = vcpu;
  11.261      chn->u.virq         = virq;
  11.262  
  11.263 -    v->virq_to_evtchn[virq] = port;
  11.264 +    v->virq_to_evtchn[virq] = bind->port = port;
  11.265  
  11.266   out:
  11.267      spin_unlock(&d->evtchn_lock);
  11.268  
  11.269 -    if ( port < 0 )
  11.270 -        return port;
  11.271 -
  11.272 -    bind->port = port;
  11.273 -    return 0;
  11.274 +    return rc;
  11.275  }
  11.276  
  11.277  
  11.278 @@ -304,27 +203,27 @@ static long evtchn_bind_ipi(evtchn_bind_
  11.279  {
  11.280      struct evtchn *chn;
  11.281      struct domain *d = current->domain;
  11.282 -    int            port;
  11.283 +    int            port, vcpu = bind->vcpu;
  11.284 +    long           rc = 0;
  11.285  
  11.286 -    if ( d->vcpu[bind->vcpu] == NULL )
  11.287 +    if ( (vcpu >= ARRAY_SIZE(d->vcpu)) || (d->vcpu[vcpu] == NULL) )
  11.288          return -ENOENT;
  11.289  
  11.290      spin_lock(&d->evtchn_lock);
  11.291  
  11.292 -    if ( (port = get_free_port(d)) >= 0 )
  11.293 -    {
  11.294 -        chn = evtchn_from_port(d, port);
  11.295 -        chn->state          = ECS_IPI;
  11.296 -        chn->notify_vcpu_id = bind->vcpu;
  11.297 -    }
  11.298 +    if ( (port = get_free_port(d)) < 0 )
  11.299 +        ERROR_EXIT(port);
  11.300  
  11.301 +    chn = evtchn_from_port(d, port);
  11.302 +    chn->state          = ECS_IPI;
  11.303 +    chn->notify_vcpu_id = vcpu;
  11.304 +
  11.305 +    bind->port = port;
  11.306 +
  11.307 + out:
  11.308      spin_unlock(&d->evtchn_lock);
  11.309  
  11.310 -    if ( port < 0 )
  11.311 -        return port;
  11.312 -
  11.313 -    bind->port = port;
  11.314 -    return 0;
  11.315 +    return rc;
  11.316  }
  11.317  
  11.318  
  11.319 @@ -332,16 +231,19 @@ static long evtchn_bind_pirq(evtchn_bind
  11.320  {
  11.321      struct evtchn *chn;
  11.322      struct domain *d = current->domain;
  11.323 -    int            port, rc, pirq = bind->pirq;
  11.324 +    int            port, pirq = bind->pirq;
  11.325 +    long           rc;
  11.326  
  11.327      if ( pirq >= ARRAY_SIZE(d->pirq_to_evtchn) )
  11.328          return -EINVAL;
  11.329  
  11.330      spin_lock(&d->evtchn_lock);
  11.331  
  11.332 -    if ( ((rc = port = d->pirq_to_evtchn[pirq]) != 0) ||
  11.333 -         ((rc = port = get_free_port(d)) < 0) )
  11.334 -        goto out;
  11.335 +    if ( d->pirq_to_evtchn[pirq] != 0 )
  11.336 +        ERROR_EXIT(-EEXIST);
  11.337 +
  11.338 +    if ( (port = get_free_port(d)) < 0 )
  11.339 +        ERROR_EXIT(port);
  11.340  
  11.341      chn = evtchn_from_port(d, port);
  11.342  
  11.343 @@ -357,14 +259,12 @@ static long evtchn_bind_pirq(evtchn_bind
  11.344      chn->state  = ECS_PIRQ;
  11.345      chn->u.pirq = pirq;
  11.346  
  11.347 +    bind->port = port;
  11.348 +
  11.349   out:
  11.350      spin_unlock(&d->evtchn_lock);
  11.351  
  11.352 -    if ( rc < 0 )
  11.353 -        return rc;
  11.354 -
  11.355 -    bind->port = port;
  11.356 -    return 0;
  11.357 +    return rc;
  11.358  }
  11.359  
  11.360  
  11.361 @@ -478,22 +378,7 @@ static long __evtchn_close(struct domain
  11.362  
  11.363  static long evtchn_close(evtchn_close_t *close)
  11.364  {
  11.365 -    struct domain *d;
  11.366 -    long           rc;
  11.367 -    domid_t        dom = close->dom;
  11.368 -
  11.369 -    if ( dom == DOMID_SELF )
  11.370 -        dom = current->domain->domain_id;
  11.371 -    else if ( !IS_PRIV(current->domain) )
  11.372 -        return -EPERM;
  11.373 -
  11.374 -    if ( (d = find_domain_by_id(dom)) == NULL )
  11.375 -        return -ESRCH;
  11.376 -
  11.377 -    rc = __evtchn_close(d, close->port);
  11.378 -
  11.379 -    put_domain(d);
  11.380 -    return rc;
  11.381 +    return __evtchn_close(current->domain, close->port);
  11.382  }
  11.383  
  11.384  
  11.385 @@ -523,6 +408,9 @@ long evtchn_send(int lport)
  11.386      case ECS_IPI:
  11.387          evtchn_set_pending(ld->vcpu[lchn->notify_vcpu_id], lport);
  11.388          break;
  11.389 +    case ECS_UNBOUND:
  11.390 +        /* silently drop the notification */
  11.391 +        break;
  11.392      default:
  11.393          ret = -EINVAL;
  11.394      }
  11.395 @@ -611,9 +499,8 @@ static long evtchn_bind_vcpu(evtchn_bind
  11.396      struct evtchn *chn;
  11.397      long           rc = 0;
  11.398  
  11.399 -    if ( (vcpu >= MAX_VIRT_CPUS) || (d->vcpu[vcpu] == NULL) ) {
  11.400 -        return -EINVAL;
  11.401 -    }
  11.402 +    if ( (vcpu >= ARRAY_SIZE(d->vcpu)) || (d->vcpu[vcpu] == NULL) )
  11.403 +        return -ENOENT;
  11.404  
  11.405      spin_lock(&d->evtchn_lock);
  11.406  
  11.407 @@ -689,7 +576,7 @@ long do_event_channel_op(evtchn_op_t *uo
  11.408          break;
  11.409  
  11.410      case EVTCHNOP_send:
  11.411 -        rc = evtchn_send(op.u.send.local_port);
  11.412 +        rc = evtchn_send(op.u.send.port);
  11.413          break;
  11.414  
  11.415      case EVTCHNOP_status:
    12.1 --- a/xen/include/public/event_channel.h	Fri Oct 07 00:21:00 2005 +0100
    12.2 +++ b/xen/include/public/event_channel.h	Fri Oct 07 10:57:13 2005 +0100
    12.3 @@ -10,9 +10,9 @@
    12.4  #define __XEN_PUBLIC_EVENT_CHANNEL_H__
    12.5  
    12.6  /*
    12.7 - * EVTCHNOP_alloc_unbound: Allocate a port in <dom> for later binding to
    12.8 - * <remote_dom>. <port> may be wildcarded by setting to zero, in which case a
    12.9 - * fresh port will be allocated, and the field filled in on return.
   12.10 + * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
   12.11 + * accepting interdomain bindings from domain <remote_dom>. A fresh port
   12.12 + * is allocated in <dom> and returned as <port>.
   12.13   * NOTES:
   12.14   *  1. If the caller is unprivileged then <dom> must be DOMID_SELF.
   12.15   */
   12.16 @@ -20,36 +20,24 @@
   12.17  typedef struct evtchn_alloc_unbound {
   12.18      /* IN parameters */
   12.19      domid_t dom, remote_dom;
   12.20 -    /* IN/OUT parameters */
   12.21 +    /* OUT parameters */
   12.22      u32     port;
   12.23  } evtchn_alloc_unbound_t;
   12.24  
   12.25  /*
   12.26   * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
   12.27 - * <dom1> and <dom2>. Either <port1> or <port2> may be wildcarded by setting to
   12.28 - * zero. On successful return both <port1> and <port2> are filled in and
   12.29 - * <dom1,port1> is fully bound to <dom2,port2>.
   12.30 - * 
   12.31 - * NOTES:
   12.32 - *  1. A wildcarded port is allocated from the relevant domain's free list
   12.33 - *     (i.e., some port that was previously EVTCHNSTAT_closed). However, if the
   12.34 - *     remote port pair is already fully bound then a port is not allocated,
   12.35 - *     and instead the existing local port is returned to the caller.
   12.36 - *  2. If the caller is unprivileged then <dom1> must be DOMID_SELF.
   12.37 - *  3. If the caller is unprivileged and <dom2,port2> is EVTCHNSTAT_closed
   12.38 - *     then <dom2> must be DOMID_SELF.
   12.39 - *  4. If either port is already bound then it must be bound to the other
   12.40 - *     specified domain and port (if not wildcarded).
   12.41 - *  5. If either port is awaiting binding (EVTCHNSTAT_unbound) then it must
   12.42 - *     be awaiting binding to the other domain, and the other port pair must
   12.43 - *     be closed or unbound.
   12.44 + * the calling domain and <remote_dom>. <remote_dom,remote_port> must identify
   12.45 + * a port that is unbound and marked as accepting bindings from the calling
   12.46 + * domain. A fresh port is allocated in the calling domain and returned as
   12.47 + * <local_port>.
   12.48   */
   12.49  #define EVTCHNOP_bind_interdomain 0
   12.50  typedef struct evtchn_bind_interdomain {
   12.51      /* IN parameters. */
   12.52 -    domid_t dom1, dom2;
   12.53 -    /* IN/OUT parameters. */
   12.54 -    u32     port1, port2;
   12.55 +    domid_t remote_dom;
   12.56 +    u32     remote_port;
   12.57 +    /* OUT parameters. */
   12.58 +    u32     local_port;
   12.59  } evtchn_bind_interdomain_t;
   12.60  
   12.61  /*
   12.62 @@ -99,31 +87,24 @@ typedef struct evtchn_bind_ipi {
   12.63  } evtchn_bind_ipi_t;
   12.64  
   12.65  /*
   12.66 - * EVTCHNOP_close: Close the communication channel which has an endpoint at
   12.67 - * <dom, port>. If the channel is interdomain then the remote end is placed in
   12.68 - * the unbound state (EVTCHNSTAT_unbound), awaiting a new connection.
   12.69 - * NOTES:
   12.70 - *  1. <dom> may be specified as DOMID_SELF.
   12.71 - *  2. Only a sufficiently-privileged domain may close an event channel
   12.72 - *     for which <dom> is not DOMID_SELF.
   12.73 + * EVTCHNOP_close: Close a local event channel <port>. If the channel is
   12.74 + * interdomain then the remote end is placed in the unbound state
   12.75 + * (EVTCHNSTAT_unbound), awaiting a new connection.
   12.76   */
   12.77  #define EVTCHNOP_close            3
   12.78  typedef struct evtchn_close {
   12.79      /* IN parameters. */
   12.80 -    domid_t dom;
   12.81 -    u32     port;
   12.82 -    /* No OUT parameters. */
   12.83 +    u32 port;
   12.84  } evtchn_close_t;
   12.85  
   12.86  /*
   12.87   * EVTCHNOP_send: Send an event to the remote end of the channel whose local
   12.88 - * endpoint is <DOMID_SELF, local_port>.
   12.89 + * endpoint is <port>.
   12.90   */
   12.91  #define EVTCHNOP_send             4
   12.92  typedef struct evtchn_send {
   12.93      /* IN parameters. */
   12.94 -    u32     local_port;
   12.95 -    /* No OUT parameters. */
   12.96 +    u32 port;
   12.97  } evtchn_send_t;
   12.98  
   12.99  /*