diff options
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 8 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 8 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c | 9 | ||||
-rw-r--r-- | tools/libxc/xc_evtchn.c | 2 | ||||
-rw-r--r-- | tools/libxc/xenctrl.h | 4 | ||||
-rw-r--r-- | tools/python/xen/lowlevel/xc/xc.c | 10 | ||||
-rw-r--r-- | xen/common/event_channel.c | 18 | ||||
-rw-r--r-- | xen/include/public/event_channel.h | 10 |
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; |