@@ -381,11 +381,16 @@ static void double_evtchn_unlock(struct evtchn *lchn, struct evtchn *rchn)
evtchn_write_unlock(rchn);
}
-static int evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
+/*
+ * If lport is zero get the next free port and allocate. If port is non-zero
+ * allocate the specified lport.
+ */
+int evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind, struct domain *ld,
+ evtchn_port_t lport)
{
struct evtchn *lchn, *rchn;
- struct domain *ld = current->domain, *rd;
- int lport, rc;
+ struct domain *rd;
+ int rc;
evtchn_port_t rport = bind->remote_port;
domid_t rdom = bind->remote_dom;
@@ -405,8 +410,11 @@ static int evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
write_lock(&ld->event_lock);
}
- if ( (lport = get_free_port(ld)) < 0 )
- ERROR_EXIT(lport);
+ lport = rc = evtchn_get_port(ld, lport);
+ if ( rc < 0 )
+ ERROR_EXIT(rc);
+ rc = 0;
+
lchn = evtchn_from_port(ld, lport);
rchn = _evtchn_from_port(rd, rport);
@@ -1239,7 +1247,7 @@ long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
struct evtchn_bind_interdomain bind_interdomain;
if ( copy_from_guest(&bind_interdomain, arg, 1) != 0 )
return -EFAULT;
- rc = evtchn_bind_interdomain(&bind_interdomain);
+ rc = evtchn_bind_interdomain(&bind_interdomain, current->domain, 0);
if ( !rc && __copy_to_guest(arg, &bind_interdomain, 1) )
rc = -EFAULT; /* Cleaning up here would be a mess! */
break;
@@ -75,6 +75,11 @@ int evtchn_allocate_port(struct domain *d, unsigned int port);
int __must_check evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc,
evtchn_port_t port);
+/* Bind an event channel port to interdomain */
+int __must_check evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind,
+ struct domain *ld,
+ evtchn_port_t port);
+
/* Unmask a local event-channel port. */
int evtchn_unmask(unsigned int port);