From 9e48ccc7328975ce6ddcd2369f47ed1c834a557a Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 22 Aug 2012 17:20:11 +0100 Subject: [PATCH] --- yaml --- r: 329140 b: refs/heads/master c: b5e579232d635b79a3da052964cb357ccda8d9ea h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/xen/events.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 388472b67168..706bd53b9242 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5c13f8067745efc15f6ad0158b58d57c44104c25 +refs/heads/master: b5e579232d635b79a3da052964cb357ccda8d9ea diff --git a/trunk/drivers/xen/events.c b/trunk/drivers/xen/events.c index 7595581d032c..36bf17dc7bfc 100644 --- a/trunk/drivers/xen/events.c +++ b/trunk/drivers/xen/events.c @@ -373,11 +373,22 @@ static void unmask_evtchn(int port) { struct shared_info *s = HYPERVISOR_shared_info; unsigned int cpu = get_cpu(); + int do_hypercall = 0, evtchn_pending = 0; BUG_ON(!irqs_disabled()); - /* Slow path (hypercall) if this is a non-local port. */ - if (unlikely(cpu != cpu_from_evtchn(port))) { + if (unlikely((cpu != cpu_from_evtchn(port)))) + do_hypercall = 1; + else + evtchn_pending = sync_test_bit(port, &s->evtchn_pending[0]); + + if (unlikely(evtchn_pending && xen_hvm_domain())) + do_hypercall = 1; + + /* Slow path (hypercall) if this is a non-local port or if this is + * an hvm domain and an event is pending (hvm domains don't have + * their own implementation of irq_enable). */ + if (do_hypercall) { struct evtchn_unmask unmask = { .port = port }; (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); } else { @@ -390,7 +401,7 @@ static void unmask_evtchn(int port) * 'hw_resend_irq'. Just like a real IO-APIC we 'lose * the interrupt edge' if the channel is masked. */ - if (sync_test_bit(port, &s->evtchn_pending[0]) && + if (evtchn_pending && !sync_test_and_set_bit(port / BITS_PER_LONG, &vcpu_info->evtchn_pending_sel)) vcpu_info->evtchn_upcall_pending = 1;