Skip to contentSkip to conversation

FAILED: patch "[PATCH] x86: vdso: fix pvclock races with task migration" failed to apply to 3.19-stable tree

PATCH [email protected] 1 participant 1 message Apr 29, 2015

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 3.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

Quoted 1 line

From 80f7fdb1c7f0f9266421f823964fd1962681f6ce Mon Sep 17 00:00:00 2001

From: =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= <[email protected]>
Date: Thu, 2 Apr 2015 20:44:23 +0200
Subject: [PATCH] x86: vdso: fix pvclock races with task migration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If we were migrated right after __getcpu, but before reading the migration_count, we wouldn't notice that we read TSC of a different VCPU, nor that KVM's bug made pvti invalid, as only migration_count on source VCPU is increased.

Change vdso instead of updating migration_count on destination.

Fixes 0a4e6be9ca17 ("x86: kvm: Revert "remove sched notifier for cross-cpu migrations"")

Message-Id: <[email protected]>

arch/x86/vdso/vclock_gettime.c +12 -8
index 30933760ee5f..40d2473836c9 100644
@@ -99,21 +99,25 @@ static notrace cycle_t vread_pvclock(int *mode)
 		 * __getcpu() calls (Gleb).
 		 */
 
-		pvti = get_pvti(cpu);
+		/* Make sure migrate_count will change if we leave the VCPU. */
+		do {
+			pvti = get_pvti(cpu);
+			migrate_count = pvti->migrate_count;
 
-		migrate_count = pvti->migrate_count;
+			cpu1 = cpu;
+			cpu = __getcpu() & VGETCPU_CPU_MASK;
+		} while (unlikely(cpu != cpu1));
 
 		version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags);
 
 		/*
 		 * Test we're still on the cpu as well as the version.
-		 * We could have been migrated just after the first
-		 * vgetcpu but before fetching the version, so we
-		 * wouldn't notice a version change.
+		 * - We must read TSC of pvti's VCPU.
+		 * - KVM doesn't follow the versioning protocol, so data could
+		 *   change before version if we left the VCPU.
 		 */
-		cpu1 = __getcpu() & VGETCPU_CPU_MASK;
-	} while (unlikely(cpu != cpu1 ||
-			  (pvti->pvti.version & 1) ||
+		smp_rmb();
+	} while (unlikely((pvti->pvti.version & 1) ||
 			  pvti->pvti.version != version ||
 			  pvti->migrate_count != migrate_count));