[Devel,RHEL7,COMMIT] KVM: x86: fix maintaining of kvm_clock stability on guest CPU hotplug

Submitted by Konstantin Khorenko on March 24, 2017, 11:48 a.m.

Details

Message ID 201703241148.v2OBmK4U018272@finist_cl7.x64_64.work.ct
State New
Series "KVM: x86: fix maintaining of kvm_clock stability on guest CPU hotplug"
Headers show

Commit Message

Konstantin Khorenko March 24, 2017, 11:48 a.m.
The commit is pushed to "branch-rh7-3.10.0-514.10.2.vz7.29.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.10.2.vz7.29.6
------>
commit 0a53b011a2b8dfc059592dd36a59e42d34bf27e8
Author: Denis Plotnikov <dplotnikov@virtuozzo.com>
Date:   Fri Mar 24 15:48:20 2017 +0400

    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.
    
    https://jira.sw.ru/browse/PSBM-59784
    
    Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
    Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
---
 arch/x86/kvm/x86.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

Patch hide | download patch | download mbox

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index df4ac8d..81104d2 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1424,15 +1424,23 @@  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_exp - tsc_hz;
+		if ((data == 0) && msr->host_initiated) {
+			/*
+			* detection of vcpu initialization -- need to sync with other vCPUs
+			* 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_exp - tsc_hz;
+		}
 	}
 
 	/*