aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c8
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c8
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c9
-rw-r--r--tools/libxc/xc_evtchn.c2
-rw-r--r--tools/libxc/xenctrl.h4
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c10
-rw-r--r--xen/common/event_channel.c18
-rw-r--r--xen/include/public/event_channel.h10
8 files changed, 49 insertions, 20 deletions
diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
index 78222c92f5..00caac5d95 100644
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
@@ -485,7 +485,7 @@ static void watch_for_status(struct xenbus_watch *watch, const char *node)
static int setup_blkring(struct xenbus_device *dev, struct blkfront_info *info)
{
blkif_sring_t *sring;
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ evtchn_op_t op;
int err;
info->ring_ref = GRANT_INVALID_REF;
@@ -508,7 +508,9 @@ static int setup_blkring(struct xenbus_device *dev, struct blkfront_info *info)
}
info->ring_ref = err;
- op.u.alloc_unbound.dom = info->backend_id;
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+ op.u.alloc_unbound.remote_dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
gnttab_end_foreign_access(info->ring_ref, 0);
@@ -518,7 +520,9 @@ static int setup_blkring(struct xenbus_device *dev, struct blkfront_info *info)
xenbus_dev_error(dev, err, "allocating event channel");
return err;
}
+
blkif_connect(info, op.u.alloc_unbound.port);
+
return 0;
}
diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
index 5a5dac453f..7bd156625b 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
@@ -972,7 +972,7 @@ static void watch_for_status(struct xenbus_watch *watch, const char *node)
static int setup_device(struct xenbus_device *dev, struct netfront_info *info)
{
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ evtchn_op_t op;
int err;
info->tx_ring_ref = GRANT_INVALID_REF;
@@ -1010,13 +1010,17 @@ static int setup_device(struct xenbus_device *dev, struct netfront_info *info)
}
info->rx_ring_ref = err;
- op.u.alloc_unbound.dom = info->backend_id;
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+ op.u.alloc_unbound.remote_dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
xenbus_dev_error(dev, err, "allocating event channel");
goto out;
}
+
connect_device(info, op.u.alloc_unbound.port);
+
return 0;
out:
diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
index 8fc6a4b501..55c44f95aa 100644
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
@@ -244,8 +244,7 @@ static int setup_tpmring(struct xenbus_device *dev,
{
tpmif_tx_interface_t *sring;
struct tpm_private *tp = &my_private;
-
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ evtchn_op_t op;
int err;
sring = (void *)__get_free_page(GFP_KERNEL);
@@ -269,7 +268,9 @@ static int setup_tpmring(struct xenbus_device *dev,
}
info->ring_ref = err;
- op.u.alloc_unbound.dom = backend_id;
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+ op.u.alloc_unbound.remote_dom = backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
gnttab_end_foreign_access(info->ring_ref, 0);
@@ -278,7 +279,9 @@ static int setup_tpmring(struct xenbus_device *dev,
xenbus_dev_error(dev, err, "allocating event channel");
return err;
}
+
tpmif_connect(op.u.alloc_unbound.port, backend_id);
+
return 0;
}
diff --git a/tools/libxc/xc_evtchn.c b/tools/libxc/xc_evtchn.c
index f7698d3541..3bdacf36a3 100644
--- a/tools/libxc/xc_evtchn.c
+++ b/tools/libxc/xc_evtchn.c
@@ -33,6 +33,7 @@ static int do_evtchn_op(int xc_handle, evtchn_op_t *op)
int xc_evtchn_alloc_unbound(int xc_handle,
+ u32 remote_dom,
u32 dom,
int *port)
{
@@ -40,6 +41,7 @@ int xc_evtchn_alloc_unbound(int xc_handle,
int rc;
op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.remote_dom = (domid_t)remote_dom;
op.u.alloc_unbound.dom = (domid_t)dom;
op.u.alloc_unbound.port = (port != NULL) ? *port : 0;
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 2fe9bee750..3e74c62fa0 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -306,13 +306,15 @@ typedef evtchn_status_t xc_evtchn_status_t;
* well-known port within a domain to receive events on.
*
* @parm xc_handle a handle to an open hypervisor interface
- * @parm dom the ID of the domain. This maybe DOMID_SELF
+ * @parm remote_dom the ID of the domain who will later bind
+ * @parm dom the ID of the local domain (the 'allocatee')
* @parm port a pointer to a port. This is an in/out parameter. If *port is
* 0, then a new port will be assigned, if port is > 0 then that
* port is allocated if the port is unallocated.
* @return 0 on success, -1 on failure
*/
int xc_evtchn_alloc_unbound(int xc_handle,
+ u32 remote_dom,
u32 dom,
int *port);
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index d096b7bb96..7ff5b40ca9 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -432,16 +432,16 @@ static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self,
{
XcObject *xc = (XcObject *)self;
- u32 dom;
+ u32 dom = DOMID_SELF, remote_dom;
int port = 0;
- static char *kwd_list[] = { "dom", "port", NULL };
+ static char *kwd_list[] = { "remote_dom", "dom", "port", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
- &dom, &port) )
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
+ &remote_dom, &dom, &port) )
return NULL;
- if ( xc_evtchn_alloc_unbound(xc->xc_handle, dom, &port) != 0 )
+ if ( xc_evtchn_alloc_unbound(xc->xc_handle, remote_dom, dom, &port) != 0 )
return PyErr_SetFromErrno(xc_error);
return PyInt_FromLong(port);
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 8c413097ba..eea5ee1633 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -63,10 +63,19 @@ static int get_free_port(struct domain *d)
static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
{
struct evtchn *chn;
- struct domain *d = current->domain;
+ struct domain *d;
int port = alloc->port;
+ domid_t dom = alloc->dom;
long rc = 0;
+ 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;
+
spin_lock(&d->evtchn_lock);
/* Obtain, or ensure that we already have, a valid <port>. */
@@ -84,11 +93,11 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
{
case ECS_FREE:
chn->state = ECS_UNBOUND;
- chn->u.unbound.remote_domid = alloc->dom;
+ chn->u.unbound.remote_domid = alloc->remote_dom;
break;
case ECS_UNBOUND:
- if ( chn->u.unbound.remote_domid != alloc->dom )
+ if ( chn->u.unbound.remote_domid != alloc->remote_dom )
ERROR_EXIT(-EINVAL);
break;
@@ -99,7 +108,10 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
out:
spin_unlock(&d->evtchn_lock);
+ put_domain(d);
+
alloc->port = port;
+
return rc;
}
diff --git a/xen/include/public/event_channel.h b/xen/include/public/event_channel.h
index 443be607f8..37efd85af3 100644
--- a/xen/include/public/event_channel.h
+++ b/xen/include/public/event_channel.h
@@ -10,14 +10,16 @@
#define __XEN_PUBLIC_EVENT_CHANNEL_H__
/*
- * EVTCHNOP_alloc_unbound: Prepare a local port for binding to <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 <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.
+ * NOTES:
+ * 1. If the caller is unprivileged then <dom> must be DOMID_SELF.
*/
#define EVTCHNOP_alloc_unbound 6
typedef struct evtchn_alloc_unbound {
/* IN parameters */
- domid_t dom;
+ domid_t dom, remote_dom;
/* IN/OUT parameters */
u32 port;
} evtchn_alloc_unbound_t;