aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/event_channel.c
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2010-11-19 13:43:24 +0000
committerKeir Fraser <keir@xen.org>2010-11-19 13:43:24 +0000
commit0b469cd6870899a52c41be1cb3c982976531d59d (patch)
treee80341800e6234bb7c2e81b8ce38dcfbc2e2b949 /xen/common/event_channel.c
parent26b1575bf3d4abd407724c0cc6a2365fd78e0b6d (diff)
downloadxen-0b469cd6870899a52c41be1cb3c982976531d59d.tar.gz
xen-0b469cd6870899a52c41be1cb3c982976531d59d.tar.bz2
xen-0b469cd6870899a52c41be1cb3c982976531d59d.zip
Interrupt remapping to PIRQs in HVM guests
This patch allows HVM guests to remap interrupts and MSIs into pirqs; once the mapping is in place the guest will receive the interrupt (or the MSI) as an event. The interrupt to be remapped can either be an interrupt of an emulated device or an interrupt of a passthrough device and we keep track of that. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Diffstat (limited to 'xen/common/event_channel.c')
-rw-r--r--xen/common/event_channel.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index f4a2c24d7a..52ec7fc215 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -331,7 +331,7 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
if ( (pirq < 0) || (pirq >= d->nr_pirqs) )
return -EINVAL;
- if ( !irq_access_permitted(d, pirq) )
+ if ( !is_hvm_domain(d) && !irq_access_permitted(d, pirq) )
return -EPERM;
spin_lock(&d->event_lock);
@@ -345,12 +345,15 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
chn = evtchn_from_port(d, port);
d->pirq_to_evtchn[pirq] = port;
- rc = pirq_guest_bind(v, pirq,
- !!(bind->flags & BIND_PIRQ__WILL_SHARE));
- if ( rc != 0 )
+ if ( !is_hvm_domain(d) )
{
- d->pirq_to_evtchn[pirq] = 0;
- goto out;
+ rc = pirq_guest_bind(
+ v, pirq, !!(bind->flags & BIND_PIRQ__WILL_SHARE));
+ if ( rc != 0 )
+ {
+ d->pirq_to_evtchn[pirq] = 0;
+ goto out;
+ }
}
chn->state = ECS_PIRQ;
@@ -403,7 +406,8 @@ static long __evtchn_close(struct domain *d1, int port1)
break;
case ECS_PIRQ:
- pirq_guest_unbind(d1, chn1->u.pirq.irq);
+ if ( !is_hvm_domain(d1) )
+ pirq_guest_unbind(d1, chn1->u.pirq.irq);
d1->pirq_to_evtchn[chn1->u.pirq.irq] = 0;
unlink_pirq_port(chn1, d1->vcpu[chn1->notify_vcpu_id]);
break;
@@ -662,10 +666,16 @@ int send_guest_pirq(struct domain *d, int pirq)
struct evtchn *chn;
/*
- * It should not be possible to race with __evtchn_close():
- * The caller of this function must synchronise with pirq_guest_unbind().
+ * PV guests: It should not be possible to race with __evtchn_close(). The
+ * caller of this function must synchronise with pirq_guest_unbind().
+ * HVM guests: Port is legitimately zero when the guest disables the
+ * emulated interrupt/evtchn.
*/
- ASSERT(port != 0);
+ if ( port == 0 )
+ {
+ BUG_ON(!is_hvm_domain(d));
+ return 0;
+ }
chn = evtchn_from_port(d, port);
return evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);