diff options
author | Denis Plotnikov <dplotnikov@virtuozzo.com> | 2017-04-07 12:09:53 +0300 |
---|---|---|
committer | Radim Krčmář <rkrcmar@redhat.com> | 2017-04-12 21:17:15 +0300 |
commit | bd8fab39cd4fe429f161dfc86bf64993d5c17320 (patch) | |
tree | c27b16f5159a12a84b68730747ae3d4ac3a0ae47 /arch/x86/kvm | |
parent | c5e8ec8e9beffb9481dba27ab5048c03c8585d7d (diff) | |
download | linux-bd8fab39cd4fe429f161dfc86bf64993d5c17320.tar.xz |
KVM: x86: fix maintaining of kvm_clock stability on guest CPU hotplug
VCPU TSC synchronization is perfromed in kvm_write_tsc() when the TSC
value being set is within 1 second from the expected, as obtained by
extrapolating of the TSC in already synchronized VCPUs.
This is naturally achieved on all VCPUs at VM start and resume;
however on VCPU hotplug it is not: the newly added VCPU is created
with TSC == 0 while others are well ahead.
To compensate for that, consider host-initiated kvm_write_tsc() with
TSC == 0 a special case requiring synchronization regardless of the
current TSC on other VCPUs.
Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/x86.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 422f803fa365..2e4a47275061 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1454,16 +1454,25 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) elapsed = ns - kvm->arch.last_tsc_nsec; if (vcpu->arch.virtual_tsc_khz) { - u64 tsc_exp = kvm->arch.last_tsc_write + - nsec_to_cycles(vcpu, elapsed); - u64 tsc_hz = vcpu->arch.virtual_tsc_khz * 1000LL; - /* - * Special case: TSC write with a small delta (1 second) - * of virtual cycle time against real time is - * interpreted as an attempt to synchronize the CPU. - */ - synchronizing = data < tsc_exp + tsc_hz && - data + tsc_hz > tsc_exp; + if (data == 0 && msr->host_initiated) { + /* + * detection of vcpu initialization -- need to sync + * with other vCPUs. This particularly helps to keep + * kvm_clock stable after CPU hotplug + */ + synchronizing = true; + } else { + u64 tsc_exp = kvm->arch.last_tsc_write + + nsec_to_cycles(vcpu, elapsed); + u64 tsc_hz = vcpu->arch.virtual_tsc_khz * 1000LL; + /* + * Special case: TSC write with a small delta (1 second) + * of virtual cycle time against real time is + * interpreted as an attempt to synchronize the CPU. + */ + synchronizing = data < tsc_exp + tsc_hz && + data + tsc_hz > tsc_exp; + } } /* |