summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw@amazon.co.uk>2026-08-26 14:32:52 -0700
committerSean Christopherson <seanjc@google.com>2026-09-11 11:46:18 -0700
commitc56419275caad2d99264b7c50b0701552ed3ef75 (patch)
tree87cab31731f3c40a013f7a1ddaa88b9b31a806bb
parentabdef42276d88417f6a0c1f9fae8190accc3bc38 (diff)
downloadlinux-next-c56419275caad2d99264b7c50b0701552ed3ef75.tar.gz
linux-next-c56419275caad2d99264b7c50b0701552ed3ef75.zip
KVM: x86: Use get_kvmclock() in kvm_get_wall_clock_epoch()
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 633d7652f80f ("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@amazon.co.uk> Link: https://patch.msgid.link/20260826213303.914988-13-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
-rw-r--r--arch/x86/kvm/x86.c59
1 files changed, 9 insertions, 50 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4567896b7cf7..e0e13235a69e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1941,63 +1941,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;
}
/*