From mboxrd@z Thu Jan 1 00:00:00 1970 From: Denis Plotnikov Subject: [PATCH v2 2/2] KVM: x86: fix maintaining of kvm_clock stability on guest CPU hotplug Date: Fri, 7 Apr 2017 12:09:53 +0300 Message-ID: <1491556193-56543-3-git-send-email-dplotnikov@virtuozzo.com> References: <1491556193-56543-1-git-send-email-dplotnikov@virtuozzo.com> Mime-Version: 1.0 Content-Type: text/plain Cc: , , To: , , , Return-path: Received: from mail-he1eur01on0129.outbound.protection.outlook.com ([104.47.0.129]:4117 "EHLO EUR01-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755120AbdDGJKR (ORCPT ); Fri, 7 Apr 2017 05:10:17 -0400 In-Reply-To: <1491556193-56543-1-git-send-email-dplotnikov@virtuozzo.com> Sender: kvm-owner@vger.kernel.org List-ID: 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 Reviewed-by: Roman Kagan --- arch/x86/kvm/x86.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c59e38f..cf67091 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1455,16 +1455,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; + } } /* -- 1.8.3.1