]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
x86/kvmclock: Implement read_snapshot() for kvmclock clocksource
authorDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 4 Jun 2026 09:35:17 +0000 (10:35 +0100)
committerThomas Gleixner <tglx@kernel.org>
Fri, 5 Jun 2026 12:25:03 +0000 (14:25 +0200)
Implement the read_snapshot() callback for the kvmclock clocksource.  This
returns the kvmclock nanosecond value (for timekeeping) while also
providing the raw TSC value that was used to compute it.

The TSC is read inside the pvclock seqlock-protected region, ensuring the
raw TSC and derived kvmclock value are atomically paired.

This enables ktime_get_snapshot_id() to provide the raw TSC to consumers
like the vmclock PTP driver, which currently has to do a separate call to
get_cycles() to obtain a value at *approximately* the same time, to feed
through the vmclock calculation.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Assisted-by: Kiro:claude-opus-4.6-1m
Link: https://patch.msgid.link/20260604095755.64849-3-dwmw2@infradead.org
arch/x86/kernel/kvmclock.c

index b5991d53fc0ea941a69c288521ec2f8aacfe871b..cb3d0ca1fa225acd1dfd447f4ee60271973501df 100644 (file)
@@ -87,6 +87,27 @@ static u64 kvm_clock_get_cycles(struct clocksource *cs)
        return kvm_clock_read();
 }
 
+static u64 kvm_clock_get_cycles_snapshot(struct clocksource *cs,
+                                        struct clocksource_hw_snapshot *chs)
+{
+       struct pvclock_vcpu_time_info *src;
+       unsigned version;
+       u64 ret, tsc;
+
+       preempt_disable_notrace();
+       src = this_cpu_pvti();
+       do {
+               version = pvclock_read_begin(src);
+               tsc = rdtsc_ordered();
+               ret = __pvclock_read_cycles(src, tsc);
+       } while (pvclock_read_retry(src, version));
+       preempt_enable_notrace();
+
+       chs->hw_cycles = tsc;
+       chs->hw_csid = CSID_X86_TSC;
+       return ret;
+}
+
 static noinstr u64 kvm_sched_clock_read(void)
 {
        return pvclock_clocksource_read_nowd(this_cpu_pvti()) - kvm_sched_clock_offset;
@@ -156,13 +177,14 @@ static int kvm_cs_enable(struct clocksource *cs)
 }
 
 static struct clocksource kvm_clock = {
-       .name   = "kvm-clock",
-       .read   = kvm_clock_get_cycles,
-       .rating = 400,
-       .mask   = CLOCKSOURCE_MASK(64),
-       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
-       .id     = CSID_X86_KVM_CLK,
-       .enable = kvm_cs_enable,
+       .name           = "kvm-clock",
+       .read           = kvm_clock_get_cycles,
+       .read_snapshot  = kvm_clock_get_cycles_snapshot,
+       .rating         = 400,
+       .mask           = CLOCKSOURCE_MASK(64),
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .id             = CSID_X86_KVM_CLK,
+       .enable         = kvm_cs_enable,
 };
 
 static void kvm_register_clock(char *txt)