The Time Stamp Counter (TSC) value register can be set to an absolute value using the KVM_SET_MSRS ioctl, which calls kvm_synchronize_tsc() internally. Since this is a per-vCPU register, and vCPUs are often managed by separate threads, setting a uniform TSC value across all vCPUs is challenging: After live migration, for example, the TSC value may need to be adjusted to account for the migration downtime. Ideally, we would want each vCPU to be adjusted by the same offset; but if we compute the offset centrally, the TSC value may become out of date due to scheduling delays by the time that each vCPU thread gets around to issuing KVM_SET_MSRS. In preparation for the next patch, this change adds an optional, KVM clock based time reference argument to kvm_synchronize_tsc(). This argument, if present, is understood to mean "the TSC value being written was valid at this corresponding KVM clock time point". kvm_synchronize_tsc() will then use this clock reference to adjust the TSC value being written for any delays that have been incurred since the provided TSC value was valid. Co-developed-by: David Woodhouse <dwmw@xxxxxxxxxxxx> Signed-off-by: Simon Veith <sveith@xxxxxxxxx> --- arch/x86/kvm/x86.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1910e1e78b15..a44d083f1bf9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2629,7 +2629,7 @@ static void __kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 offset, u64 tsc, kvm_track_tsc_matching(vcpu); } -static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data) +static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data, u64 *kvm_ns) { struct kvm *kvm = vcpu->kvm; u64 offset, ns, elapsed; @@ -2638,12 +2638,24 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data) bool synchronizing = false; raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags); - offset = kvm_compute_l1_tsc_offset(vcpu, data); ns = get_kvmclock_base_ns(); + + if (kvm_ns) { + /* + * We have been provided a KVM clock reference time point at + * which this TSC value was correct. + * Use this time point to compensate for any delays that were + * incurred since that TSC value was valid. + */ + s64 delta_ns = ns + vcpu->kvm->arch.kvmclock_offset - *kvm_ns; + data += nsec_to_cycles(vcpu, (u64)delta_ns); + } + + offset = kvm_compute_l1_tsc_offset(vcpu, data); elapsed = ns - kvm->arch.last_tsc_nsec; if (vcpu->arch.virtual_tsc_khz) { - if (data == 0) { + if (data == 0 && !kvm_ns) { /* * detection of vcpu initialization -- need to sync * with other vCPUs. This particularly helps to keep @@ -3581,7 +3593,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) break; case MSR_IA32_TSC: if (msr_info->host_initiated) { - kvm_synchronize_tsc(vcpu, data); + kvm_synchronize_tsc(vcpu, data, NULL); } else { u64 adj = kvm_compute_l1_tsc_offset(vcpu, data) - vcpu->arch.l1_tsc_offset; adjust_tsc_offset_guest(vcpu, adj); @@ -11392,7 +11404,7 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) if (mutex_lock_killable(&vcpu->mutex)) return; vcpu_load(vcpu); - kvm_synchronize_tsc(vcpu, 0); + kvm_synchronize_tsc(vcpu, 0, NULL); vcpu_put(vcpu); /* poll control enabled by default */ -- 2.25.1 Amazon Development Center Germany GmbH Krausenstr. 38 10117 Berlin Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B Sitz: Berlin Ust-ID: DE 289 237 879