diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 53777f8..067365b 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -51,6 +51,8 @@ #define consumer_is_xen(e) (!!(e)->xen_consumer) +static long __evtchn_close(struct domain *d, int port); + /* * The function alloc_unbound_xen_event_channel() allows an arbitrary * notifier function to be specified. However, very few unique functions @@ -161,18 +163,18 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc) { struct evtchn *chn; struct domain *d; - int port; + evtchn_port_t port; domid_t dom = alloc->dom; - long rc; + int rc; rc = rcu_lock_target_domain_by_id(dom, &d); if ( rc ) return rc; - spin_lock(&d->event_lock); + rc = evtchn_alloc_unbound_domain(d, &port); + if ( rc ) + ERROR_EXIT_DOM(rc, d); - if ( (port = get_free_port(d)) < 0 ) - ERROR_EXIT_DOM(port, d); chn = evtchn_from_port(d, port); rc = xsm_evtchn_unbound(d, chn, alloc->remote_dom); @@ -186,12 +188,31 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc) alloc->port = port; out: - spin_unlock(&d->event_lock); rcu_unlock_domain(d); return rc; } +int evtchn_alloc_unbound_domain(struct domain *d, evtchn_port_t *port) +{ + struct evtchn *chn; + int free_port = 0; + + spin_lock(&d->event_lock); + + if ( (free_port = get_free_port(d)) < 0 ) + goto out; + chn = evtchn_from_port(d, free_port); + chn->state = ECS_UNBOUND; + chn->u.unbound.remote_domid = DOMID_INVALID; + *port = free_port; + /* Everything is fine, returns 0 */ + free_port = 0; + + out: + spin_unlock(&d->event_lock); + return free_port; +} static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind) { diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index 71c3e92..d89b0c1 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -69,6 +69,8 @@ int guest_enabled_event(struct vcpu *v, uint32_t virq); /* Notify remote end of a Xen-attached event channel.*/ void notify_via_xen_event_channel(struct domain *ld, int lport); +int evtchn_alloc_unbound_domain(struct domain *d, evtchn_port_t *port); + /* Internal event channel object accessors */ #define bucket_from_port(d,p) \ ((d)->evtchn[(p)/EVTCHNS_PER_BUCKET])