diff mbox

[3.5.y.z,extended,stable] Patch "xen/events: mask events when changing their VCPU binding" has been added to staging queue

Message ID 1379705615-14881-1-git-send-email-luis.henriques@canonical.com
State New
Headers show

Commit Message

Luis Henriques Sept. 20, 2013, 7:33 p.m. UTC
This is a note to let you know that I have just added a patch titled

    xen/events: mask events when changing their VCPU binding

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.5.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Luis

------

From 591b619dee78e29f62a56a60b19e959c758cdc5e Mon Sep 17 00:00:00 2001
From: David Vrabel <david.vrabel@citrix.com>
Date: Thu, 15 Aug 2013 13:21:07 +0100
Subject: [PATCH] xen/events: mask events when changing their VCPU binding

commit 4704fe4f03a5ab27e3c36184af85d5000e0f8a48 upstream.

When a event is being bound to a VCPU there is a window between the
EVTCHNOP_bind_vpcu call and the adjustment of the local per-cpu masks
where an event may be lost.  The hypervisor upcalls the new VCPU but
the kernel thinks that event is still bound to the old VCPU and
ignores it.

There is even a problem when the event is being bound to the same VCPU
as there is a small window beween the clear_bit() and set_bit() calls
in bind_evtchn_to_cpu().  When scanning for pending events, the kernel
may read the bit when it is momentarily clear and ignore the event.

Avoid this by masking the event during the whole bind operation.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
[ luis: backported to 3.5:
  - removed the BM() cast (as per 3.2 backport) ]
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
---
 drivers/xen/events.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

--
1.8.3.2
diff mbox

Patch

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 025e98b..8a8cd6e 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -1431,8 +1431,10 @@  void rebind_evtchn_irq(int evtchn, int irq)
 /* Rebind an evtchn so that it gets delivered to a specific cpu */
 static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 {
+	struct shared_info *s = HYPERVISOR_shared_info;
 	struct evtchn_bind_vcpu bind_vcpu;
 	int evtchn = evtchn_from_irq(irq);
+	int masked;

 	if (!VALID_EVTCHN(evtchn))
 		return -1;
@@ -1449,6 +1451,12 @@  static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 	bind_vcpu.vcpu = tcpu;

 	/*
+	 * Mask the event while changing the VCPU binding to prevent
+	 * it being delivered on an unexpected VCPU.
+	 */
+	masked = sync_test_and_set_bit(evtchn, s->evtchn_mask);
+
+	/*
 	 * If this fails, it usually just indicates that we're dealing with a
 	 * virq or IPI channel, which don't actually need to be rebound. Ignore
 	 * it, but don't do the xenlinux-level rebind in that case.
@@ -1456,6 +1464,9 @@  static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
 		bind_evtchn_to_cpu(evtchn, tcpu);

+	if (!masked)
+		unmask_evtchn(evtchn);
+
 	return 0;
 }