Commit ad9e5bf0 authored by Radim Krčmář's avatar Radim Krčmář Committed by Luis Henriques

x86: vdso: fix pvclock races with task migration

commit 80f7fdb1 upstream.

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.
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
Fixes: 0a4e6be9 ("x86: kvm: Revert "remove sched notifier for cross-cpu migrations"")
Message-Id: <1428000263-11892-1-git-send-email-rkrcmar@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent b4b79733
...@@ -99,21 +99,25 @@ static notrace cycle_t vread_pvclock(int *mode) ...@@ -99,21 +99,25 @@ static notrace cycle_t vread_pvclock(int *mode)
* __getcpu() calls (Gleb). * __getcpu() calls (Gleb).
*/ */
/* Make sure migrate_count will change if we leave the VCPU. */
do {
pvti = get_pvti(cpu); 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); version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags);
/* /*
* Test we're still on the cpu as well as the version. * Test we're still on the cpu as well as the version.
* We could have been migrated just after the first * - We must read TSC of pvti's VCPU.
* vgetcpu but before fetching the version, so we * - KVM doesn't follow the versioning protocol, so data could
* wouldn't notice a version change. * change before version if we left the VCPU.
*/ */
cpu1 = __getcpu() & VGETCPU_CPU_MASK; smp_rmb();
} while (unlikely(cpu != cpu1 || } while (unlikely((pvti->pvti.version & 1) ||
(pvti->pvti.version & 1) ||
pvti->pvti.version != version || pvti->pvti.version != version ||
pvti->migrate_count != migrate_count)); pvti->migrate_count != migrate_count));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment