From: David Woodhouse <[email protected]>

Replace the KVM-private vgettsc()/do_kvmclock_base()/do_monotonic()/
do_realtime() timekeeping reimplementation with calls to the generic
ktime_get_snapshot_id() interface.

The snapshot provides both the system time and the raw_cycles (TSC)
atomically paired. When raw_cycles is zero, the clocksource could not
provide a raw hardware counter value, which is equivalent to the
previous vgettsc() returning VDSO_CLOCKMODE_NONE.

For kvm_get_time_and_clockread(), the kvmclock base time is
CLOCK_MONOTONIC_RAW + offs_boot. The snapshot provides the raw time
atomically paired with the TSC; offs_boot is added separately as it
only changes at suspend/resume boundaries.

This is a step towards eliminating the pvclock_gtod_data private copy
of timekeeping state and the associated notifier callback.

Signed-off-by: David Woodhouse <[email protected]>
Assisted-by: Kiro:claude-opus-4.6-1m
---
 arch/x86/kvm/x86.c | 50 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 39 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c9e17e01f82d..e6f740f95ff9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -35,6 +35,7 @@
 #include "smm.h"
 
 #include <linux/clocksource.h>
+#include <linux/timekeeping.h>
 #include <linux/interrupt.h>
 #include <linux/kvm.h>
 #include <linux/fs.h>
@@ -3137,14 +3138,34 @@ static int do_realtime(struct timespec64 *ts, u64 
*tsc_timestamp)
  * reports the TSC value from which it do so. Returns true if host is
  * using TSC based clocksource.
  */
+static bool kvm_snapshot_has_tsc(struct system_time_snapshot *snap,
+                               u64 *tsc_timestamp)
+{
+       if (snap->cs_id == CSID_X86_TSC) {
+               *tsc_timestamp = snap->cycles;
+               return true;
+       }
+
+       if (snap->raw_csid == CSID_X86_TSC && snap->raw_cycles) {
+               *tsc_timestamp = snap->raw_cycles;
+               return true;
+       }
+
+       return false;
+}
+
 static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *tsc_timestamp)
 {
-       /* checked again under seqlock below */
-       if (!gtod_is_based_on_tsc(pvclock_gtod_data.clock.vclock_mode))
+       struct system_time_snapshot snap;
+
+       if (!ktime_get_snapshot_id(&snap, CLOCK_MONOTONIC_RAW))
+               return false;
+       if (!kvm_snapshot_has_tsc(&snap, tsc_timestamp))
                return false;
 
-       return gtod_is_based_on_tsc(do_kvmclock_base(kernel_ns,
-                                                    tsc_timestamp));
+       *kernel_ns = ktime_to_ns(snap.sys) +
+                    ktime_to_ns(ktime_mono_to_any(0, TK_OFFS_BOOT));
+       return true;
 }
 
 /*
@@ -3153,12 +3174,15 @@ static bool kvm_get_time_and_clockread(s64 *kernel_ns, 
u64 *tsc_timestamp)
  */
 bool kvm_get_monotonic_and_clockread(s64 *kernel_ns, u64 *tsc_timestamp)
 {
-       /* checked again under seqlock below */
-       if (!gtod_is_based_on_tsc(pvclock_gtod_data.clock.vclock_mode))
+       struct system_time_snapshot snap;
+
+       if (!ktime_get_snapshot_id(&snap, CLOCK_MONOTONIC))
+               return false;
+       if (!kvm_snapshot_has_tsc(&snap, tsc_timestamp))
                return false;
 
-       return gtod_is_based_on_tsc(do_monotonic(kernel_ns,
-                                                tsc_timestamp));
+       *kernel_ns = ktime_to_ns(snap.sys);
+       return true;
 }
 
 /*
@@ -3171,11 +3195,15 @@ bool kvm_get_monotonic_and_clockread(s64 *kernel_ns, 
u64 *tsc_timestamp)
 static bool kvm_get_walltime_and_clockread(struct timespec64 *ts,
                                           u64 *tsc_timestamp)
 {
-       /* checked again under seqlock below */
-       if (!gtod_is_based_on_tsc(pvclock_gtod_data.clock.vclock_mode))
+       struct system_time_snapshot snap;
+
+       if (!ktime_get_snapshot_id(&snap, CLOCK_REALTIME))
+               return false;
+       if (!kvm_snapshot_has_tsc(&snap, tsc_timestamp))
                return false;
 
-       return gtod_is_based_on_tsc(do_realtime(ts, tsc_timestamp));
+       *ts = ktime_to_timespec64(snap.sys);
+       return true;
 }
 #endif
 
-- 
2.54.0


Reply via email to