[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v7 09/36] KVM: x86: Use get_kvmclock() in kvm_get_wall_clock_epoch()



From: David Woodhouse <dwmw@xxxxxxxxxxxx>

Now that get_kvmclock() correctly handles TSC scaling and captures both
wallclock and kvmclock from the same TSC reading,
kvm_get_wall_clock_epoch() can simply call it instead of duplicating
the pvclock computation.

This eliminates the last instance of the "definition C" kvmclock
calculation — as described in commit 710b3a30f407 ("KVM: x86/xen: Do
not corrupt KVM clock in kvm_xen_shared_info_init()") — which computed
nanoseconds directly from the host TSC without accounting for guest
TSC scaling.

Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
---
 arch/x86/kvm/x86.c | 59 +++++++---------------------------------------
 1 file changed, 9 insertions(+), 50 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c00b1e19c3af..f7a9fb69e69d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1930,63 +1930,22 @@ int kvm_guest_time_update(struct kvm_vcpu *v)
  * wallclock and kvmclock times, and subtracting one from the other.
  *
  * Fall back to using their values at slightly different moments by
- * calling ktime_get_real_ns() and get_kvmclock_ns() separately.
+ * calling ktime_get_real_ns() and get_kvmclock() separately.
  */
 uint64_t kvm_get_wall_clock_epoch(struct kvm *kvm)
 {
-#ifdef CONFIG_X86_64
-       struct pvclock_vcpu_time_info hv_clock;
-       struct kvm_arch *ka = &kvm->arch;
-       unsigned long seq, local_tsc_khz;
-       struct timespec64 ts;
-       uint64_t host_tsc;
-
-       do {
-               seq = read_seqcount_begin(&ka->pvclock_sc);
-
-               local_tsc_khz = 0;
-               if (!ka->use_master_clock)
-                       break;
-
-               /*
-                * The TSC read and the call to get_cpu_tsc_khz() must happen
-                * on the same CPU.
-                */
-               get_cpu();
-
-               local_tsc_khz = get_cpu_tsc_khz();
-
-               if (local_tsc_khz &&
-                   !kvm_get_walltime_and_clockread(&ts, &host_tsc))
-                       local_tsc_khz = 0; /* Fall back to old method */
-
-               put_cpu();
-
-               /*
-                * These values must be snapshotted within the seqcount loop.
-                * After that, it's just mathematics which can happen on any
-                * CPU at any time.
-                */
-               hv_clock.tsc_timestamp = ka->master_cycle_now;
-               hv_clock.system_time = ka->master_kernel_ns + 
ka->kvmclock_offset;
+       struct kvm_clock_data data;
 
-       } while (read_seqcount_retry(&ka->pvclock_sc, seq));
+       get_kvmclock(kvm, &data);
 
        /*
-        * If the conditions were right, and obtaining the wallclock+TSC was
-        * successful, calculate the KVM clock at the corresponding time and
-        * subtract one from the other to get the guest's epoch in nanoseconds
-        * since 1970-01-01.
+        * If get_kvmclock() captured both wallclock and kvmclock from the
+        * same TSC reading, use them for a precise epoch calculation.
         */
-       if (local_tsc_khz) {
-               kvm_get_time_scale(NSEC_PER_SEC, local_tsc_khz * NSEC_PER_USEC,
-                                  &hv_clock.tsc_shift,
-                                  &hv_clock.tsc_to_system_mul);
-               return ts.tv_nsec + NSEC_PER_SEC * ts.tv_sec -
-                       __pvclock_read_cycles(&hv_clock, host_tsc);
-       }
-#endif
-       return ktime_get_real_ns() - get_kvmclock_ns(kvm);
+       if (data.flags & KVM_CLOCK_REALTIME)
+               return data.realtime - data.clock;
+
+       return ktime_get_real_ns() - data.clock;
 }
 
 /*
-- 
2.55.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.