From: Sean Christopherson <[email protected]> Sent: Wednesday, July 1, 2026 
12:32 PM
> 
> Pass in a PV clock's save/restore helpers when configuring sched_clock
> instead of relying on each PV clock to manually set the save/restore hooks.
> In addition to bringing sanity to the code, this will allow gracefully
> "rejecting" a PV sched_clock, e.g. when running as a CoCo guest that has
> access to a "secure" TSC.
> 
> No functional change intended.
> 
> Reviewed-by: David Woodhouse <[email protected]>
> Signed-off-by: Sean Christopherson <[email protected]>

For the Hyper-V changes,

Reviewed-by: Michael Kelley <[email protected]>

> ---
>  arch/x86/include/asm/timer.h       | 9 ++++++---
>  arch/x86/kernel/cpu/vmware.c       | 8 +++-----
>  arch/x86/kernel/kvmclock.c         | 6 +++---
>  arch/x86/kernel/tsc.c              | 5 ++++-
>  arch/x86/xen/time.c                | 5 ++---
>  drivers/clocksource/hyperv_timer.c | 6 ++----
>  6 files changed, 20 insertions(+), 19 deletions(-)
> 
> diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
> index fe41d40a9ae6..e97cd1ae03d1 100644
> --- a/arch/x86/include/asm/timer.h
> +++ b/arch/x86/include/asm/timer.h
> @@ -14,11 +14,14 @@ extern int no_timer_check;
>  extern bool using_native_sched_clock(void);
> 
>  #ifdef CONFIG_PARAVIRT
> -void __paravirt_set_sched_clock(u64 (*func)(void), bool stable);
> +void __paravirt_set_sched_clock(u64 (*func)(void), bool stable,
> +                             void (*save)(void), void (*restore)(void));
> 
> -static inline void paravirt_set_sched_clock(u64 (*func)(void))
> +static inline void paravirt_set_sched_clock(u64 (*func)(void),
> +                                         void (*save)(void),
> +                                         void (*restore)(void))
>  {
> -     __paravirt_set_sched_clock(func, true);
> +     __paravirt_set_sched_clock(func, true, save, restore);
>  }
>  #endif
> 
> diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
> index 5c1ccaf4a25e..232255279a6e 100644
> --- a/arch/x86/kernel/cpu/vmware.c
> +++ b/arch/x86/kernel/cpu/vmware.c
> @@ -347,11 +347,9 @@ static void __init vmware_paravirt_ops_setup(void)
> 
>       vmware_cyc2ns_setup();
> 
> -     if (vmw_sched_clock) {
> -             paravirt_set_sched_clock(vmware_sched_clock);
> -             x86_platform.save_sched_clock_state = x86_init_noop;
> -             x86_platform.restore_sched_clock_state = x86_init_noop;
> -     }
> +     if (vmw_sched_clock)
> +             paravirt_set_sched_clock(vmware_sched_clock,
> +                                      x86_init_noop, x86_init_noop);
> 
>       if (vmware_is_stealclock_available()) {
>               has_steal_clock = true;
> diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
> index 07e875738c39..5b9955343199 100644
> --- a/arch/x86/kernel/kvmclock.c
> +++ b/arch/x86/kernel/kvmclock.c
> @@ -158,7 +158,9 @@ static void kvm_restore_sched_clock_state(void)
>  static inline void kvm_sched_clock_init(bool stable)
>  {
>       kvm_sched_clock_offset = kvm_clock_read();
> -     __paravirt_set_sched_clock(kvm_sched_clock_read, stable);
> +     __paravirt_set_sched_clock(kvm_sched_clock_read, stable,
> +                                kvm_save_sched_clock_state,
> +                                kvm_restore_sched_clock_state);
> 
>       pr_info("kvm-clock: using sched offset of %llu cycles",
>               kvm_sched_clock_offset);
> @@ -367,8 +369,6 @@ void __init kvmclock_init(bool prefer_tsc)
>  #ifdef CONFIG_SMP
>       x86_cpuinit.early_percpu_clock_init = kvm_setup_secondary_clock;
>  #endif
> -     x86_platform.save_sched_clock_state = kvm_save_sched_clock_state;
> -     x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state;
>       kvm_get_preset_lpj();
> 
>       /*
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index 7473dcab4775..83353d643150 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -280,12 +280,15 @@ bool using_native_sched_clock(void)
>       return static_call_query(pv_sched_clock) == native_sched_clock;
>  }
> 
> -void __paravirt_set_sched_clock(u64 (*func)(void), bool stable)
> +void __paravirt_set_sched_clock(u64 (*func)(void), bool stable,
> +                             void (*save)(void), void (*restore)(void))
>  {
>       if (!stable)
>               clear_sched_clock_stable();
> 
>       static_call_update(pv_sched_clock, func);
> +     x86_platform.save_sched_clock_state = save;
> +     x86_platform.restore_sched_clock_state = restore;
>  }
>  #else
>  u64 sched_clock_noinstr(void) __attribute__((alias("native_sched_clock")));
> diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
> index 477441752f40..8cd8bfaf1320 100644
> --- a/arch/x86/xen/time.c
> +++ b/arch/x86/xen/time.c
> @@ -566,13 +566,12 @@ static void __init xen_init_time_common(void)
>  {
>       xen_sched_clock_offset = xen_clocksource_read();
>       static_call_update(pv_steal_clock, xen_steal_clock);
> -     paravirt_set_sched_clock(xen_sched_clock);
> +
>       /*
>        * Xen has paravirtualized suspend/resume and so doesn't use the common
>        * x86 sched_clock save/restore hooks.
>        */
> -     x86_platform.save_sched_clock_state = x86_init_noop;
> -     x86_platform.restore_sched_clock_state = x86_init_noop;
> +     paravirt_set_sched_clock(xen_sched_clock, x86_init_noop, x86_init_noop);
> 
>       x86_init.hyper.get_tsc_khz = xen_tsc_khz;
>       x86_platform.get_wallclock = xen_get_wallclock;
> diff --git a/drivers/clocksource/hyperv_timer.c 
> b/drivers/clocksource/hyperv_timer.c
> index 220668207d19..8ee7a9de0f4f 100644
> --- a/drivers/clocksource/hyperv_timer.c
> +++ b/drivers/clocksource/hyperv_timer.c
> @@ -570,10 +570,8 @@ static void hv_restore_sched_clock_state(void)
>  static __always_inline void hv_setup_sched_clock(void *sched_clock)
>  {
>       /* We're on x86/x64 *and* using PV ops */
> -     paravirt_set_sched_clock(sched_clock);
> -
> -     x86_platform.save_sched_clock_state = hv_save_sched_clock_state;
> -     x86_platform.restore_sched_clock_state = hv_restore_sched_clock_state;
> +     paravirt_set_sched_clock(sched_clock, hv_save_sched_clock_state,
> +                              hv_restore_sched_clock_state);
>  }
>  #else /* !CONFIG_GENERIC_SCHED_CLOCK && !CONFIG_PARAVIRT */
>  static __always_inline void hv_setup_sched_clock(void *sched_clock) {}
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
> 


Reply via email to