diff mbox

[v2,1/2] kvm: x86: Fix racy event propagation in kmv timer

Message ID 4A2E657D.5090405@siemens.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Kiszka June 9, 2009, 1:37 p.m. UTC
v2 as requested in private discussion: Broken into two pieces, and the
second one will not change the original semantic.

-------------->

Minor issue that likely had no practical relevance: The kvm timer
function so far incremented the pending counter and then may reset it
again to 1 in case reinjection was disabled. This opened a small racy
window with the corresponding VCPU loop that may have happened to run on
another (real) CPU and already consumed the value.

Fix it by skipping the incrementation in case pending is already > 0.
This opens a different race windows, but may only rarely cause lost
events in case we do not care about them anyway (!reinject).

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 arch/x86/kvm/timer.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Marcelo Tosatti June 9, 2009, 1:59 p.m. UTC | #1
On Tue, Jun 09, 2009 at 03:37:01PM +0200, Jan Kiszka wrote:
> v2 as requested in private discussion: Broken into two pieces, and the
> second one will not change the original semantic.
> 
> -------------->
> 
> Minor issue that likely had no practical relevance: The kvm timer
> function so far incremented the pending counter and then may reset it
> again to 1 in case reinjection was disabled. This opened a small racy
> window with the corresponding VCPU loop that may have happened to run on
> another (real) CPU and already consumed the value.
> 
> Fix it by skipping the incrementation in case pending is already > 0.
> This opens a different race windows, but may only rarely cause lost
> events in case we do not care about them anyway (!reinject).
> 
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>

ACK both, thanks.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avi Kivity June 14, 2009, 11:18 a.m. UTC | #2
Marcelo Tosatti wrote:
> On Tue, Jun 09, 2009 at 03:37:01PM +0200, Jan Kiszka wrote:
>   
>> v2 as requested in private discussion: Broken into two pieces, and the
>> second one will not change the original semantic.
>>
>> -------------->
>>
>> Minor issue that likely had no practical relevance: The kvm timer
>> function so far incremented the pending counter and then may reset it
>> again to 1 in case reinjection was disabled. This opened a small racy
>> window with the corresponding VCPU loop that may have happened to run on
>> another (real) CPU and already consumed the value.
>>
>> Fix it by skipping the incrementation in case pending is already > 0.
>> This opens a different race windows, but may only rarely cause lost
>> events in case we do not care about them anyway (!reinject).
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>>     
>
> ACK both, thanks.
>   

And applied both, thanks.
diff mbox

Patch

diff --git a/arch/x86/kvm/timer.c b/arch/x86/kvm/timer.c
index 86dbac0..36054e9 100644
--- a/arch/x86/kvm/timer.c
+++ b/arch/x86/kvm/timer.c
@@ -9,12 +9,16 @@  static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
 	int restart_timer = 0;
 	wait_queue_head_t *q = &vcpu->wq;
 
-	/* FIXME: this code should not know anything about vcpus */
-	if (!atomic_inc_and_test(&ktimer->pending))
-		set_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
-
-	if (!ktimer->reinject)
-		atomic_set(&ktimer->pending, 1);
+	/*
+	 * There is a race window between reading and incrementing, but we do
+	 * not care about potentially loosing timer events in the !reinject
+	 * case anyway.
+	 */
+	if (ktimer->reinject || !atomic_read(&ktimer->pending)) {
+		/* FIXME: this code should not know anything about vcpus */
+		if (!atomic_inc_and_test(&ktimer->pending))
+			set_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
+	}
 
 	if (waitqueue_active(q))
 		wake_up_interruptible(q);