aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/vdso
diff options
context:
space:
mode:
authorRadim Krčmář <rkrcmar@redhat.com>2015-04-02 14:44:23 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2015-04-08 04:46:55 -0400
commit80f7fdb1c7f0f9266421f823964fd1962681f6ce (patch)
tree5046430395b6097984374f24d59f6616b34ae1ea /arch/x86/vdso
parent3180a7fcbc0ec7ed7cc85ed5015bdd7a8c2176e8 (diff)
x86: vdso: fix pvclock races with task migration
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. Cc: stable@vger.kernel.org Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> Fixes: 0a4e6be9ca17 ("x86: kvm: Revert "remove sched notifier for cross-cpu migrations"") Message-Id: <1428000263-11892-1-git-send-email-rkrcmar@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/vdso')
-rw-r--r--arch/x86/vdso/vclock_gettime.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index 30933760ee5f..40d2473836c9 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -99,21 +99,25 @@ static notrace cycle_t vread_pvclock(int *mode)
99 * __getcpu() calls (Gleb). 99 * __getcpu() calls (Gleb).
100 */ 100 */
101 101
102 pvti = get_pvti(cpu); 102 /* Make sure migrate_count will change if we leave the VCPU. */
103 do {
104 pvti = get_pvti(cpu);
105 migrate_count = pvti->migrate_count;
103 106
104 migrate_count = pvti->migrate_count; 107 cpu1 = cpu;
108 cpu = __getcpu() & VGETCPU_CPU_MASK;
109 } while (unlikely(cpu != cpu1));
105 110
106 version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags); 111 version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags);
107 112
108 /* 113 /*
109 * Test we're still on the cpu as well as the version. 114 * Test we're still on the cpu as well as the version.
110 * We could have been migrated just after the first 115 * - We must read TSC of pvti's VCPU.
111 * vgetcpu but before fetching the version, so we 116 * - KVM doesn't follow the versioning protocol, so data could
112 * wouldn't notice a version change. 117 * change before version if we left the VCPU.
113 */ 118 */
114 cpu1 = __getcpu() & VGETCPU_CPU_MASK; 119 smp_rmb();
115 } while (unlikely(cpu != cpu1 || 120 } while (unlikely((pvti->pvti.version & 1) ||
116 (pvti->pvti.version & 1) ||
117 pvti->pvti.version != version || 121 pvti->pvti.version != version ||
118 pvti->migrate_count != migrate_count)); 122 pvti->migrate_count != migrate_count));
119 123