From 13c5e5d26e45a64d6448e6d6cc253b4ace99797e Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Tue, 12 Mar 2013 15:27:31 +0000 Subject: [PATCH] xen/events: avoid race with raising an event in unmask_evtchn() In unmask_evtchn(), when the mask bit is cleared after testing for pending and the event becomes pending between the test and clear, then the upcall will not become pending and the event may be lost or delayed. Avoid this by always clearing the mask bit before checking for pending. This fixes a regression introduced in 3.7 by b5e579232d635b79a3da052964cb357ccda8d9ea (xen/events: fix unmask_evtchn for PV on HVM guests) which reordered the clear mask and check pending operations. Signed-off-by: David Vrabel Cc: stable@vger.kernel.org Cc: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/events.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index d17aa41a9041..4bdd0a50f575 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -403,11 +403,13 @@ static void unmask_evtchn(int port) if (unlikely((cpu != cpu_from_evtchn(port)))) do_hypercall = 1; - else + else { + sync_clear_bit(port, BM(&s->evtchn_mask[0])); evtchn_pending = sync_test_bit(port, BM(&s->evtchn_pending[0])); - if (unlikely(evtchn_pending && xen_hvm_domain())) - do_hypercall = 1; + 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 @@ -418,8 +420,6 @@ static void unmask_evtchn(int port) } else { struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); - sync_clear_bit(port, BM(&s->evtchn_mask[0])); - /* * The following is basically the equivalent of * 'hw_resend_irq'. Just like a real IO-APIC we 'lose -- 2.39.5