The pvclock_update_vm_gtod_copy() function always unconditionally updates ka->master_kernel_ns and ka->master_cycle_now whenever a KVM_REQ_MASTERCLOCK_UPDATE occurs. Unfortunately, each masterclock update increases the risk of kvm-clock drift. If pvclock_update_vm_gtod_copy() is not called from vcpu_enter_guest()-->kvm_update_masterclock(), we keep the existing workflow. The argument 'forced' is introduced to tell where it is from. Otherwise, we avoid updating the masterclock if it is already active and will remain active. In such cases, updating the masterclock data is not beneficial and can instead lead to kvm-clock drift. As a result, this patch minimizes the chance of unnecessary masterclock data updates to avoid kvm-clock drift. Cc: David Woodhouse Signed-off-by: Dongli Zhang --- arch/x86/kvm/x86.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0599949a7803..d2ce696abf55 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3108,12 +3108,15 @@ static bool kvm_get_walltime_and_clockread(struct timespec64 *ts, * */ -static void pvclock_update_vm_gtod_copy(struct kvm *kvm) +static void pvclock_update_vm_gtod_copy(struct kvm *kvm, bool forced) { #ifdef CONFIG_X86_64 struct kvm_arch *ka = &kvm->arch; int vclock_mode; bool host_tsc_clocksource, vcpus_matched; + bool use_master_clock; + u64 master_kernel_ns; + u64 master_cycle_now; lockdep_assert_held(&kvm->arch.tsc_write_lock); vcpus_matched = (ka->nr_vcpus_matched_tsc + 1 == @@ -3124,12 +3127,26 @@ static void pvclock_update_vm_gtod_copy(struct kvm *kvm) * to the guest. */ host_tsc_clocksource = kvm_get_time_and_clockread( - &ka->master_kernel_ns, - &ka->master_cycle_now); + &master_kernel_ns, + &master_cycle_now); + + use_master_clock = host_tsc_clocksource && vcpus_matched + && !ka->backwards_tsc_observed + && !ka->boot_vcpu_runs_old_kvmclock; + + /* + * Always update masterclock data unconditionally if not for + * KVM_REQ_MASTERCLOCK_UPDATE request. + * + * Otherwise, do not update masterclock data if it is already + * active and will remain active. + */ + if (forced || !(use_master_clock && ka->use_master_clock)) { + ka->master_kernel_ns = master_kernel_ns; + ka->master_cycle_now = master_cycle_now; + } - ka->use_master_clock = host_tsc_clocksource && vcpus_matched - && !ka->backwards_tsc_observed - && !ka->boot_vcpu_runs_old_kvmclock; + ka->use_master_clock = use_master_clock; if (ka->use_master_clock) atomic_set(&kvm_guest_has_master_clock, 1); @@ -3179,7 +3196,7 @@ static void kvm_update_masterclock(struct kvm *kvm) { kvm_hv_request_tsc_page_update(kvm); kvm_start_pvclock_update(kvm); - pvclock_update_vm_gtod_copy(kvm); + pvclock_update_vm_gtod_copy(kvm, false); kvm_end_pvclock_update(kvm); } @@ -7189,7 +7206,7 @@ static int kvm_vm_ioctl_set_clock(struct kvm *kvm, void __user *argp) kvm_hv_request_tsc_page_update(kvm); kvm_start_pvclock_update(kvm); - pvclock_update_vm_gtod_copy(kvm); + pvclock_update_vm_gtod_copy(kvm, true); /* * This pairs with kvm_guest_time_update(): when masterclock is @@ -9773,7 +9790,7 @@ static void kvm_hyperv_tsc_notifier(void) list_for_each_entry(kvm, &vm_list, vm_list) { __kvm_start_pvclock_update(kvm); - pvclock_update_vm_gtod_copy(kvm); + pvclock_update_vm_gtod_copy(kvm, true); kvm_end_pvclock_update(kvm); } @@ -13206,7 +13223,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.kvmclock_offset = -get_kvmclock_base_ns(); raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags); - pvclock_update_vm_gtod_copy(kvm); + pvclock_update_vm_gtod_copy(kvm, true); raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); kvm->arch.default_tsc_khz = max_tsc_khz ? : tsc_khz; -- 2.39.3