From c24536b636f23e4d3202968fcad129d979881e2c Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 23 Jun 2011 11:32:43 +0100 Subject: replace d->nr_pirqs sized arrays with radix tree With this it is questionable whether retaining struct domain's nr_pirqs is actually necessary - the value now only serves for bounds checking, and this boundary could easily be nr_irqs. Note that ia64, the build of which is broken currently anyway, is only being partially fixed up. v2: adjustments for split setup/teardown of translation data v3: re-sync with radix tree implementation changes Signed-off-by: Jan Beulich --- xen/common/event_channel.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'xen/common/event_channel.c') diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 558fbb1256..631bbede22 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -325,6 +325,7 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind) struct evtchn *chn; struct domain *d = current->domain; struct vcpu *v = d->vcpu[0]; + struct pirq *info; int port, pirq = bind->pirq; long rc; @@ -336,7 +337,7 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind) spin_lock(&d->event_lock); - if ( d->pirq_to_evtchn[pirq] != 0 ) + if ( pirq_to_evtchn(d, pirq) != 0 ) ERROR_EXIT(-EEXIST); if ( (port = get_free_port(d)) < 0 ) @@ -344,14 +345,18 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind) chn = evtchn_from_port(d, port); - d->pirq_to_evtchn[pirq] = port; + info = pirq_get_info(d, pirq); + if ( !info ) + ERROR_EXIT(-ENOMEM); + info->evtchn = port; rc = (!is_hvm_domain(d) - ? pirq_guest_bind( - v, pirq, !!(bind->flags & BIND_PIRQ__WILL_SHARE)) + ? pirq_guest_bind(v, info, + !!(bind->flags & BIND_PIRQ__WILL_SHARE)) : 0); if ( rc != 0 ) { - d->pirq_to_evtchn[pirq] = 0; + info->evtchn = 0; + pirq_cleanup_check(info, d); goto out; } @@ -404,12 +409,18 @@ static long __evtchn_close(struct domain *d1, int port1) case ECS_UNBOUND: break; - case ECS_PIRQ: + case ECS_PIRQ: { + struct pirq *pirq = pirq_info(d1, chn1->u.pirq.irq); + + if ( !pirq ) + break; if ( !is_hvm_domain(d1) ) - pirq_guest_unbind(d1, chn1->u.pirq.irq); - d1->pirq_to_evtchn[chn1->u.pirq.irq] = 0; + pirq_guest_unbind(d1, pirq); + pirq->evtchn = 0; + pirq_cleanup_check(pirq, d1); unlink_pirq_port(chn1, d1->vcpu[chn1->notify_vcpu_id]); break; + } case ECS_VIRQ: for_each_vcpu ( d1, v ) @@ -659,9 +670,9 @@ void send_guest_global_virq(struct domain *d, int virq) spin_unlock_irqrestore(&v->virq_lock, flags); } -int send_guest_pirq(struct domain *d, int pirq) +int send_guest_pirq(struct domain *d, const struct pirq *pirq) { - int port = d->pirq_to_evtchn[pirq]; + int port; struct evtchn *chn; /* @@ -670,7 +681,7 @@ int send_guest_pirq(struct domain *d, int pirq) * HVM guests: Port is legitimately zero when the guest disables the * emulated interrupt/evtchn. */ - if ( port == 0 ) + if ( pirq == NULL || (port = pirq->evtchn) == 0 ) { BUG_ON(!is_hvm_domain(d)); return 0; @@ -812,13 +823,10 @@ int evtchn_unmask(unsigned int port) struct domain *d = current->domain; struct vcpu *v; - spin_lock(&d->event_lock); + ASSERT(spin_is_locked(&d->event_lock)); if ( unlikely(!port_is_valid(d, port)) ) - { - spin_unlock(&d->event_lock); return -EINVAL; - } v = d->vcpu[evtchn_from_port(d, port)->notify_vcpu_id]; @@ -834,8 +842,6 @@ int evtchn_unmask(unsigned int port) vcpu_mark_events_pending(v); } - spin_unlock(&d->event_lock); - return 0; } @@ -960,7 +966,9 @@ long do_event_channel_op(int cmd, XEN_GUEST_HANDLE(void) arg) struct evtchn_unmask unmask; if ( copy_from_guest(&unmask, arg, 1) != 0 ) return -EFAULT; + spin_lock(¤t->domain->event_lock); rc = evtchn_unmask(unmask.port); + spin_unlock(¤t->domain->event_lock); break; } -- cgit v1.2.3