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

[Xen-changelog] Big simplification of the Xen event-channel interface.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 37bea65ed6ca2faff4bf5f1b281b6cdc9df3522d
# Parent  48df3efaf61c2cf98dc87ab1b70bd505f0096a6a
Big simplification of the Xen event-channel interface.
EVTCHNOP_bind_interdomain in particular is much simpler.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 48df3efaf61c -r 37bea65ed6ca 
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Thu Oct  6 23:21:00 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Fri Oct  7 09:57:13 2005
@@ -219,7 +219,6 @@
        spin_lock(&irq_mapping_update_lock);
 
        if (--irq_bindcount[irq] == 0) {
-               op.u.close.dom  = DOMID_SELF;
                op.u.close.port = evtchn;
                BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
 
@@ -283,7 +282,6 @@
        spin_lock(&irq_mapping_update_lock);
 
        if (--irq_bindcount[irq] == 0) {
-               op.u.close.dom  = DOMID_SELF;
                op.u.close.port = evtchn;
                BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
 
@@ -326,7 +324,6 @@
        spin_lock(&irq_mapping_update_lock);
 
        if ((--irq_bindcount[irq] == 0) && (evtchn != -1)) {
-               op.u.close.dom  = DOMID_SELF;
                op.u.close.port = evtchn;
                BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
 
@@ -513,7 +510,10 @@
 static unsigned int startup_pirq(unsigned int irq)
 {
        evtchn_op_t op = { .cmd = EVTCHNOP_bind_pirq };
-       int evtchn;
+       int evtchn = irq_to_evtchn[irq];
+
+       if (VALID_EVTCHN(evtchn))
+               goto out;
 
        op.u.bind_pirq.pirq  = irq;
        /* NB. We are happy to share unless we are probing. */
@@ -532,6 +532,7 @@
        evtchn_to_irq[evtchn] = irq;
        irq_to_evtchn[irq]    = evtchn;
 
+ out:
        unmask_evtchn(evtchn);
        pirq_unmask_notify(irq_to_pirq(irq));
 
@@ -548,7 +549,6 @@
 
        mask_evtchn(evtchn);
 
-       op.u.close.dom  = DOMID_SELF;
        op.u.close.port = evtchn;
        BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
 
diff -r 48df3efaf61c -r 37bea65ed6ca 
linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c      Thu Oct  6 
23:21:00 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c      Fri Oct  7 
09:57:13 2005
@@ -71,10 +71,8 @@
        int err;
        evtchn_op_t op = {
                .cmd = EVTCHNOP_bind_interdomain,
-               .u.bind_interdomain.dom1 = DOMID_SELF,
-               .u.bind_interdomain.dom2 = blkif->domid,
-               .u.bind_interdomain.port1 = 0,
-               .u.bind_interdomain.port2 = evtchn };
+               .u.bind_interdomain.remote_dom = blkif->domid,
+               .u.bind_interdomain.remote_port = evtchn };
 
        if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
                return -ENOMEM;
@@ -92,7 +90,7 @@
                return err;
        }
 
-       blkif->evtchn = op.u.bind_interdomain.port1;
+       blkif->evtchn = op.u.bind_interdomain.local_port;
 
        sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
        SHARED_RING_INIT(sring);
diff -r 48df3efaf61c -r 37bea65ed6ca 
linux-2.6-xen-sparse/drivers/xen/blktap/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c       Thu Oct  6 
23:21:00 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c       Fri Oct  7 
09:57:13 2005
@@ -71,10 +71,8 @@
        int err;
        evtchn_op_t op = {
                .cmd = EVTCHNOP_bind_interdomain,
-               .u.bind_interdomain.dom1 = DOMID_SELF,
-               .u.bind_interdomain.dom2 = blkif->domid,
-               .u.bind_interdomain.port1 = 0,
-               .u.bind_interdomain.port2 = evtchn };
+               .u.bind_interdomain.remote_dom  = blkif->domid,
+               .u.bind_interdomain.remote_port = evtchn };
 
        if ((blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
                return -ENOMEM;
@@ -92,7 +90,7 @@
                return err;
        }
 
-       blkif->evtchn = op.u.bind_interdomain.port1;
+       blkif->evtchn = op.u.bind_interdomain.local_port;
 
        sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
        SHARED_RING_INIT(sring);
diff -r 48df3efaf61c -r 37bea65ed6ca 
linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c  Thu Oct  6 23:21:00 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c  Fri Oct  7 09:57:13 2005
@@ -223,7 +223,7 @@
                if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
                        break;
 
-               op.cmd              = EVTCHNOP_bind_virq;
+               op.cmd = EVTCHNOP_bind_virq;
                op.u.bind_virq.virq = bind.virq;
                op.u.bind_virq.vcpu = 0;
                rc = HYPERVISOR_event_channel_op(&op);
@@ -243,16 +243,14 @@
                if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
                        break;
 
-               op.cmd                      = EVTCHNOP_bind_interdomain;
-               op.u.bind_interdomain.dom1  = DOMID_SELF;
-               op.u.bind_interdomain.dom2  = bind.remote_domain;
-               op.u.bind_interdomain.port1 = 0;
-               op.u.bind_interdomain.port2 = bind.remote_port;
+               op.cmd = EVTCHNOP_bind_interdomain;
+               op.u.bind_interdomain.remote_dom  = bind.remote_domain;
+               op.u.bind_interdomain.remote_port = bind.remote_port;
                rc = HYPERVISOR_event_channel_op(&op);
                if (rc != 0)
                        break;
 
-               rc = op.u.bind_interdomain.port1;
+               rc = op.u.bind_interdomain.local_port;
                port_user[rc] = u;
                unmask_evtchn(rc);
                break;
@@ -265,7 +263,7 @@
                if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
                        break;
 
-               op.cmd                        = EVTCHNOP_alloc_unbound;
+               op.cmd = EVTCHNOP_alloc_unbound;
                op.u.alloc_unbound.dom        = DOMID_SELF;
                op.u.alloc_unbound.remote_dom = bind.remote_domain;
                rc = HYPERVISOR_event_channel_op(&op);
@@ -292,6 +290,11 @@
                } else {
                        port_user[unbind.port] = NULL;
                        mask_evtchn(unbind.port);
+
+                       op.cmd = EVTCHNOP_close;
+                       op.u.close.port = unbind.port;
+                       BUG_ON(HYPERVISOR_event_channel_op(&op));
+
                        rc = 0;
                }
                break;
@@ -390,8 +393,7 @@
                port_user[i] = NULL;
                mask_evtchn(i);
 
-               op.cmd          = EVTCHNOP_close;
-               op.u.close.dom  = DOMID_SELF;
+               op.cmd = EVTCHNOP_close;
                op.u.close.port = i;
                BUG_ON(HYPERVISOR_event_channel_op(&op));
        }
diff -r 48df3efaf61c -r 37bea65ed6ca 
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c      Thu Oct  6 
23:21:00 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c      Fri Oct  7 
09:57:13 2005
@@ -180,10 +180,8 @@
        int err;
        evtchn_op_t op = {
                .cmd = EVTCHNOP_bind_interdomain,
-               .u.bind_interdomain.dom1 = DOMID_SELF,
-               .u.bind_interdomain.dom2 = netif->domid,
-               .u.bind_interdomain.port1 = 0,
-               .u.bind_interdomain.port2 = evtchn };
+               .u.bind_interdomain.remote_dom = netif->domid,
+               .u.bind_interdomain.remote_port = evtchn };
 
        netif->comms_area = alloc_vm_area(2*PAGE_SIZE);
        if (netif->comms_area == NULL)
@@ -202,7 +200,7 @@
                return err;
        }
 
-       netif->evtchn = op.u.bind_interdomain.port1;
+       netif->evtchn = op.u.bind_interdomain.local_port;
 
        netif->irq = bind_evtchn_to_irqhandler(
                netif->evtchn, netif_be_int, 0, netif->dev->name, netif);
diff -r 48df3efaf61c -r 37bea65ed6ca 
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c      Thu Oct  6 
23:21:00 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c      Fri Oct  7 
09:57:13 2005
@@ -120,10 +120,8 @@
        int err;
        evtchn_op_t op = {
                .cmd = EVTCHNOP_bind_interdomain,
-               .u.bind_interdomain.dom1 = DOMID_SELF,
-               .u.bind_interdomain.dom2 = tpmif->domid,
-               .u.bind_interdomain.port1 = 0,
-               .u.bind_interdomain.port2 = evtchn };
+               .u.bind_interdomain.remote_dom = tpmif->domid,
+               .u.bind_interdomain.remote_port = evtchn };
 
        if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
                return -ENOMEM;
@@ -141,7 +139,7 @@
                return err;
        }
 
-       tpmif->evtchn = op.u.bind_interdomain.port1;
+       tpmif->evtchn = op.u.bind_interdomain.local_port;
 
        tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr;
 
diff -r 48df3efaf61c -r 37bea65ed6ca 
linux-2.6-xen-sparse/include/asm-xen/evtchn.h
--- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h     Thu Oct  6 23:21:00 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h     Fri Oct  7 09:57:13 2005
@@ -123,9 +123,9 @@
 
 static inline void notify_remote_via_evtchn(int port)
 {
-       evtchn_op_t op = {
-               .cmd = EVTCHNOP_send,
-               .u.send.local_port = port };
+       evtchn_op_t op;
+       op.cmd         = EVTCHNOP_send,
+       op.u.send.port = port;
        (void)HYPERVISOR_event_channel_op(&op);
 }
 
diff -r 48df3efaf61c -r 37bea65ed6ca tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Thu Oct  6 23:21:00 2005
+++ b/tools/ioemu/vl.c  Fri Oct  7 09:57:13 2005
@@ -2806,7 +2806,7 @@
 
             case QEMU_OPTION_p:
                 {
-                  extern short ioreq_remote_port;
+                  extern u16 ioreq_remote_port;
                   ioreq_remote_port = atoi(optarg);
                   printf("port: %d\n", ioreq_remote_port);
                 }
diff -r 48df3efaf61c -r 37bea65ed6ca tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Oct  6 23:21:00 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct  7 09:57:13 2005
@@ -432,13 +432,13 @@
 {
     XcObject *xc = (XcObject *)self;
 
-    u32 dom = DOMID_SELF, remote_dom;
+    u32 dom, remote_dom;
     int port;
 
-    static char *kwd_list[] = { "remote_dom", "dom", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
-                                      &remote_dom, &dom) )
+    static char *kwd_list[] = { "dom", "remote_dom", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
+                                      &dom, &remote_dom) )
         return NULL;
 
     if ( (port = xc_evtchn_alloc_unbound(xc->xc_handle, dom, remote_dom)) < 0 )
@@ -943,8 +943,9 @@
     { "evtchn_alloc_unbound", 
       (PyCFunction)pyxc_evtchn_alloc_unbound,
       METH_VARARGS | METH_KEYWORDS, "\n"
-      "Allocate an unbound local port that will await a remote connection.\n"
-      " dom [int]: Remote domain to accept connections from.\n\n"
+      "Allocate an unbound port that will await a remote connection.\n"
+      " dom        [int]: Domain whose port space to allocate from.\n"
+      " remote_dom [int]: Remote domain to accept connections from.\n\n"
       "Returns: [int] Unbound event-channel port.\n" },
 
     { "evtchn_status", 
diff -r 48df3efaf61c -r 37bea65ed6ca tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Oct  6 23:21:00 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Fri Oct  7 09:57:13 2005
@@ -197,6 +197,7 @@
         log.info("Recreating domain %d with new UUID %s.", domid, uuid)
 
         vm = XendDomainInfo(uuid, xeninfo, domid, True)
+        vm.removeDom()
         vm.storeVmDetails()
         vm.storeDomDetails()
 
diff -r 48df3efaf61c -r 37bea65ed6ca xen/common/event_channel.c
--- a/xen/common/event_channel.c        Thu Oct  6 23:21:00 2005
+++ b/xen/common/event_channel.c        Fri Oct  7 09:57:13 2005
@@ -70,7 +70,7 @@
 {
     struct evtchn *chn;
     struct domain *d;
-    int            port = alloc->port;
+    int            port;
     domid_t        dom = alloc->dom;
     long           rc = 0;
 
@@ -84,176 +84,80 @@
 
     spin_lock(&d->evtchn_lock);
 
-    /* Obtain, or ensure that we already have, a valid <port>. */
-    if ( port == 0 )
-    {
-        if ( (port = get_free_port(d)) < 0 )
-            ERROR_EXIT(port);
-    }
-    else if ( !port_is_valid(d, port) )
+    if ( (port = get_free_port(d)) < 0 )
+        ERROR_EXIT(port);
+    chn = evtchn_from_port(d, port);
+
+    chn->state = ECS_UNBOUND;
+    chn->u.unbound.remote_domid = alloc->remote_dom;
+
+    alloc->port = port;
+
+ out:
+    spin_unlock(&d->evtchn_lock);
+
+    put_domain(d);
+
+    return rc;
+}
+
+
+static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
+{
+    struct evtchn *lchn, *rchn;
+    struct domain *ld = current->domain, *rd;
+    int            lport, rport = bind->remote_port;
+    long           rc = 0;
+
+    if ( (rd = find_domain_by_id(bind->remote_dom)) == NULL )
+        return -ESRCH;
+
+    /* Avoid deadlock by first acquiring lock of domain with smaller id. */
+    if ( ld < rd )
+    {
+        spin_lock(&ld->evtchn_lock);
+        spin_lock(&rd->evtchn_lock);
+    }
+    else
+    {
+        if ( ld != rd )
+            spin_lock(&rd->evtchn_lock);
+        spin_lock(&ld->evtchn_lock);
+    }
+
+    if ( (lport = get_free_port(ld)) < 0 )
+        ERROR_EXIT(lport);
+    lchn = evtchn_from_port(ld, lport);
+
+    if ( !port_is_valid(rd, rport) )
         ERROR_EXIT(-EINVAL);
-    chn = evtchn_from_port(d, port);
-
-    /* Validate channel's current state. */
-    switch ( chn->state )
-    {
-    case ECS_FREE:
-        chn->state = ECS_UNBOUND;
-        chn->u.unbound.remote_domid = alloc->remote_dom;
-        break;
-
-    case ECS_UNBOUND:
-        if ( chn->u.unbound.remote_domid != alloc->remote_dom )
-            ERROR_EXIT(-EINVAL);
-        break;
-
-    default:
+    rchn = evtchn_from_port(rd, rport);
+    if ( (rchn->state != ECS_UNBOUND) ||
+         (rchn->u.unbound.remote_domid != ld->domain_id) )
         ERROR_EXIT(-EINVAL);
-    }
-
- out:
-    spin_unlock(&d->evtchn_lock);
-
-    put_domain(d);
-
-    alloc->port = port;
-
-    return rc;
-}
-
-
-static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
-{
-    struct evtchn *chn1, *chn2;
-    struct domain *d1, *d2;
-    int            port1 = bind->port1, port2 = bind->port2;
-    domid_t        dom1 = bind->dom1, dom2 = bind->dom2;
-    long           rc = 0;
-
-    if ( !IS_PRIV(current->domain) && (dom1 != DOMID_SELF) )
-        return -EPERM;
-
-    if ( dom1 == DOMID_SELF )
-        dom1 = current->domain->domain_id;
-    if ( dom2 == DOMID_SELF )
-        dom2 = current->domain->domain_id;
-
-    if ( ((d1 = find_domain_by_id(dom1)) == NULL) ||
-         ((d2 = find_domain_by_id(dom2)) == NULL) )
-    {
-        if ( d1 != NULL )
-            put_domain(d1);
-        return -ESRCH;
-    }
-
-    /* Avoid deadlock by first acquiring lock of domain with smaller id. */
-    if ( d1 < d2 )
-    {
-        spin_lock(&d1->evtchn_lock);
-        spin_lock(&d2->evtchn_lock);
-    }
-    else
-    {
-        if ( d1 != d2 )
-            spin_lock(&d2->evtchn_lock);
-        spin_lock(&d1->evtchn_lock);
-    }
-
-    /* Obtain, or ensure that we already have, a valid <port1>. */
-    if ( port1 == 0 )
-    {
-        if ( (port1 = get_free_port(d1)) < 0 )
-            ERROR_EXIT(port1);
-    }
-    else if ( !port_is_valid(d1, port1) )
-        ERROR_EXIT(-EINVAL);
-    chn1 = evtchn_from_port(d1, port1);
-
-    /* Obtain, or ensure that we already have, a valid <port2>. */
-    if ( port2 == 0 )
-    {
-        /* Make port1 non-free while we allocate port2 (in case dom1==dom2). */
-        u16 state = chn1->state;
-        chn1->state = ECS_INTERDOMAIN;
-        port2 = get_free_port(d2);
-        chn1->state = state;
-        if ( port2 < 0 )
-            ERROR_EXIT(port2);
-    }
-    else if ( !port_is_valid(d2, port2) )
-        ERROR_EXIT(-EINVAL);
-    chn2 = evtchn_from_port(d2, port2);
-
-    /* Validate <dom1,port1>'s current state. */
-    switch ( chn1->state )
-    {
-    case ECS_FREE:
-        break;
-
-    case ECS_UNBOUND:
-        if ( chn1->u.unbound.remote_domid != dom2 )
-            ERROR_EXIT(-EINVAL);
-        break;
-
-    case ECS_INTERDOMAIN:
-        if ( chn1->u.interdomain.remote_dom != d2 )
-            ERROR_EXIT(-EINVAL);
-        if ( (chn1->u.interdomain.remote_port != port2) && (bind->port2 != 0) )
-            ERROR_EXIT(-EINVAL);
-        port2 = chn1->u.interdomain.remote_port;
-        goto out;
-
-    default:
-        ERROR_EXIT(-EINVAL);
-    }
-
-    /* Validate <dom2,port2>'s current state. */
-    switch ( chn2->state )
-    {
-    case ECS_FREE:
-        if ( !IS_PRIV(current->domain) && (dom2 != DOMID_SELF) )
-            ERROR_EXIT(-EPERM);
-        break;
-
-    case ECS_UNBOUND:
-        if ( chn2->u.unbound.remote_domid != dom1 )
-            ERROR_EXIT(-EINVAL);
-        break;
-
-    case ECS_INTERDOMAIN:
-        if ( chn2->u.interdomain.remote_dom != d1 )
-            ERROR_EXIT(-EINVAL);
-        if ( (chn2->u.interdomain.remote_port != port1) && (bind->port1 != 0) )
-            ERROR_EXIT(-EINVAL);
-        port1 = chn2->u.interdomain.remote_port;
-        goto out;
-
-    default:
-        ERROR_EXIT(-EINVAL);
-    }
+
+    lchn->u.interdomain.remote_dom  = rd;
+    lchn->u.interdomain.remote_port = (u16)rport;
+    lchn->state                     = ECS_INTERDOMAIN;
+    
+    rchn->u.interdomain.remote_dom  = ld;
+    rchn->u.interdomain.remote_port = (u16)lport;
+    rchn->state                     = ECS_INTERDOMAIN;
 
     /*
-     * Everything checked out okay -- bind <dom1,port1> to <dom2,port2>.
+     * We may have lost notifications on the remote unbound port. Fix that up
+     * here by conservatively always setting a notification on the local port.
      */
-
-    chn1->u.interdomain.remote_dom  = d2;
-    chn1->u.interdomain.remote_port = (u16)port2;
-    chn1->state                     = ECS_INTERDOMAIN;
+    evtchn_set_pending(ld->vcpu[lchn->notify_vcpu_id], lport);
+
+    bind->local_port = lport;
+
+ out:
+    spin_unlock(&ld->evtchn_lock);
+    if ( ld != rd )
+        spin_unlock(&rd->evtchn_lock);
     
-    chn2->u.interdomain.remote_dom  = d1;
-    chn2->u.interdomain.remote_port = (u16)port1;
-    chn2->state                     = ECS_INTERDOMAIN;
-
- out:
-    spin_unlock(&d1->evtchn_lock);
-    if ( d1 != d2 )
-        spin_unlock(&d2->evtchn_lock);
-    
-    put_domain(d1);
-    put_domain(d2);
-
-    bind->port1 = port1;
-    bind->port2 = port2;
+    put_domain(rd);
 
     return rc;
 }
@@ -264,39 +168,34 @@
     struct evtchn *chn;
     struct vcpu   *v;
     struct domain *d = current->domain;
-    int            port, virq = bind->virq;
+    int            port, virq = bind->virq, vcpu = bind->vcpu;
+    long           rc = 0;
 
     if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) )
         return -EINVAL;
 
-    if ( (v = d->vcpu[bind->vcpu]) == NULL )
+    if ( (vcpu >= ARRAY_SIZE(d->vcpu)) || ((v = d->vcpu[vcpu]) == NULL) )
         return -ENOENT;
 
     spin_lock(&d->evtchn_lock);
 
-    /*
-     * Port 0 is the fallback port for VIRQs that haven't been explicitly
-     * bound yet.
-     */
-    if ( ((port = v->virq_to_evtchn[virq]) != 0) ||
-         ((port = get_free_port(d)) < 0) )
-        goto out;
+    if ( v->virq_to_evtchn[virq] != 0 )
+        ERROR_EXIT(-EEXIST);
+
+    if ( (port = get_free_port(d)) < 0 )
+        ERROR_EXIT(port);
 
     chn = evtchn_from_port(d, port);
     chn->state          = ECS_VIRQ;
-    chn->notify_vcpu_id = v->vcpu_id;
+    chn->notify_vcpu_id = vcpu;
     chn->u.virq         = virq;
 
-    v->virq_to_evtchn[virq] = port;
+    v->virq_to_evtchn[virq] = bind->port = port;
 
  out:
     spin_unlock(&d->evtchn_lock);
 
-    if ( port < 0 )
-        return port;
-
-    bind->port = port;
-    return 0;
+    return rc;
 }
 
 
@@ -304,27 +203,27 @@
 {
     struct evtchn *chn;
     struct domain *d = current->domain;
-    int            port;
-
-    if ( d->vcpu[bind->vcpu] == NULL )
+    int            port, vcpu = bind->vcpu;
+    long           rc = 0;
+
+    if ( (vcpu >= ARRAY_SIZE(d->vcpu)) || (d->vcpu[vcpu] == NULL) )
         return -ENOENT;
 
     spin_lock(&d->evtchn_lock);
 
-    if ( (port = get_free_port(d)) >= 0 )
-    {
-        chn = evtchn_from_port(d, port);
-        chn->state          = ECS_IPI;
-        chn->notify_vcpu_id = bind->vcpu;
-    }
-
+    if ( (port = get_free_port(d)) < 0 )
+        ERROR_EXIT(port);
+
+    chn = evtchn_from_port(d, port);
+    chn->state          = ECS_IPI;
+    chn->notify_vcpu_id = vcpu;
+
+    bind->port = port;
+
+ out:
     spin_unlock(&d->evtchn_lock);
 
-    if ( port < 0 )
-        return port;
-
-    bind->port = port;
-    return 0;
+    return rc;
 }
 
 
@@ -332,16 +231,19 @@
 {
     struct evtchn *chn;
     struct domain *d = current->domain;
-    int            port, rc, pirq = bind->pirq;
+    int            port, pirq = bind->pirq;
+    long           rc;
 
     if ( pirq >= ARRAY_SIZE(d->pirq_to_evtchn) )
         return -EINVAL;
 
     spin_lock(&d->evtchn_lock);
 
-    if ( ((rc = port = d->pirq_to_evtchn[pirq]) != 0) ||
-         ((rc = port = get_free_port(d)) < 0) )
-        goto out;
+    if ( d->pirq_to_evtchn[pirq] != 0 )
+        ERROR_EXIT(-EEXIST);
+
+    if ( (port = get_free_port(d)) < 0 )
+        ERROR_EXIT(port);
 
     chn = evtchn_from_port(d, port);
 
@@ -357,14 +259,12 @@
     chn->state  = ECS_PIRQ;
     chn->u.pirq = pirq;
 
+    bind->port = port;
+
  out:
     spin_unlock(&d->evtchn_lock);
 
-    if ( rc < 0 )
-        return rc;
-
-    bind->port = port;
-    return 0;
+    return rc;
 }
 
 
@@ -478,22 +378,7 @@
 
 static long evtchn_close(evtchn_close_t *close)
 {
-    struct domain *d;
-    long           rc;
-    domid_t        dom = close->dom;
-
-    if ( dom == DOMID_SELF )
-        dom = current->domain->domain_id;
-    else if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
-    if ( (d = find_domain_by_id(dom)) == NULL )
-        return -ESRCH;
-
-    rc = __evtchn_close(d, close->port);
-
-    put_domain(d);
-    return rc;
+    return __evtchn_close(current->domain, close->port);
 }
 
 
@@ -523,6 +408,9 @@
     case ECS_IPI:
         evtchn_set_pending(ld->vcpu[lchn->notify_vcpu_id], lport);
         break;
+    case ECS_UNBOUND:
+        /* silently drop the notification */
+        break;
     default:
         ret = -EINVAL;
     }
@@ -611,9 +499,8 @@
     struct evtchn *chn;
     long           rc = 0;
 
-    if ( (vcpu >= MAX_VIRT_CPUS) || (d->vcpu[vcpu] == NULL) ) {
-        return -EINVAL;
-    }
+    if ( (vcpu >= ARRAY_SIZE(d->vcpu)) || (d->vcpu[vcpu] == NULL) )
+        return -ENOENT;
 
     spin_lock(&d->evtchn_lock);
 
@@ -689,7 +576,7 @@
         break;
 
     case EVTCHNOP_send:
-        rc = evtchn_send(op.u.send.local_port);
+        rc = evtchn_send(op.u.send.port);
         break;
 
     case EVTCHNOP_status:
diff -r 48df3efaf61c -r 37bea65ed6ca xen/include/public/event_channel.h
--- a/xen/include/public/event_channel.h        Thu Oct  6 23:21:00 2005
+++ b/xen/include/public/event_channel.h        Fri Oct  7 09:57:13 2005
@@ -10,9 +10,9 @@
 #define __XEN_PUBLIC_EVENT_CHANNEL_H__
 
 /*
- * EVTCHNOP_alloc_unbound: Allocate a port in <dom> for later binding to
- * <remote_dom>. <port> may be wildcarded by setting to zero, in which case a
- * fresh port will be allocated, and the field filled in on return.
+ * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
+ * accepting interdomain bindings from domain <remote_dom>. A fresh port
+ * is allocated in <dom> and returned as <port>.
  * NOTES:
  *  1. If the caller is unprivileged then <dom> must be DOMID_SELF.
  */
@@ -20,36 +20,24 @@
 typedef struct evtchn_alloc_unbound {
     /* IN parameters */
     domid_t dom, remote_dom;
-    /* IN/OUT parameters */
+    /* OUT parameters */
     u32     port;
 } evtchn_alloc_unbound_t;
 
 /*
  * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
- * <dom1> and <dom2>. Either <port1> or <port2> may be wildcarded by setting to
- * zero. On successful return both <port1> and <port2> are filled in and
- * <dom1,port1> is fully bound to <dom2,port2>.
- * 
- * NOTES:
- *  1. A wildcarded port is allocated from the relevant domain's free list
- *     (i.e., some port that was previously EVTCHNSTAT_closed). However, if the
- *     remote port pair is already fully bound then a port is not allocated,
- *     and instead the existing local port is returned to the caller.
- *  2. If the caller is unprivileged then <dom1> must be DOMID_SELF.
- *  3. If the caller is unprivileged and <dom2,port2> is EVTCHNSTAT_closed
- *     then <dom2> must be DOMID_SELF.
- *  4. If either port is already bound then it must be bound to the other
- *     specified domain and port (if not wildcarded).
- *  5. If either port is awaiting binding (EVTCHNSTAT_unbound) then it must
- *     be awaiting binding to the other domain, and the other port pair must
- *     be closed or unbound.
+ * the calling domain and <remote_dom>. <remote_dom,remote_port> must identify
+ * a port that is unbound and marked as accepting bindings from the calling
+ * domain. A fresh port is allocated in the calling domain and returned as
+ * <local_port>.
  */
 #define EVTCHNOP_bind_interdomain 0
 typedef struct evtchn_bind_interdomain {
     /* IN parameters. */
-    domid_t dom1, dom2;
-    /* IN/OUT parameters. */
-    u32     port1, port2;
+    domid_t remote_dom;
+    u32     remote_port;
+    /* OUT parameters. */
+    u32     local_port;
 } evtchn_bind_interdomain_t;
 
 /*
@@ -99,31 +87,24 @@
 } evtchn_bind_ipi_t;
 
 /*
- * EVTCHNOP_close: Close the communication channel which has an endpoint at
- * <dom, port>. If the channel is interdomain then the remote end is placed in
- * the unbound state (EVTCHNSTAT_unbound), awaiting a new connection.
- * NOTES:
- *  1. <dom> may be specified as DOMID_SELF.
- *  2. Only a sufficiently-privileged domain may close an event channel
- *     for which <dom> is not DOMID_SELF.
+ * EVTCHNOP_close: Close a local event channel <port>. If the channel is
+ * interdomain then the remote end is placed in the unbound state
+ * (EVTCHNSTAT_unbound), awaiting a new connection.
  */
 #define EVTCHNOP_close            3
 typedef struct evtchn_close {
     /* IN parameters. */
-    domid_t dom;
-    u32     port;
-    /* No OUT parameters. */
+    u32 port;
 } evtchn_close_t;
 
 /*
  * EVTCHNOP_send: Send an event to the remote end of the channel whose local
- * endpoint is <DOMID_SELF, local_port>.
+ * endpoint is <port>.
  */
 #define EVTCHNOP_send             4
 typedef struct evtchn_send {
     /* IN parameters. */
-    u32     local_port;
-    /* No OUT parameters. */
+    u32 port;
 } evtchn_send_t;
 
 /*

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


 


Rackspace

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