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

