Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers: hv: Decouple Hyper-V clock/timer code from VMbus drivers

Hyper-V clock/timer code in hyperv_timer.c is mostly independent from
other VMbus drivers, but building for ARM64 without hyperv_timer.c
shows some remaining entanglements. A default implementation of
hv_read_reference_counter can just read a Hyper-V synthetic register
and be independent of hyperv_timer.c, so move this code out and into
hv_common.c. Then it can be used by the timesync driver even if
hyperv_timer.c isn't built on a particular architecture. If
hyperv_timer.c *is* built, it can override with a faster implementation.

Also provide stubs for stimer functions called by the VMbus driver when
hyperv_timer.c isn't built.

No functional changes.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/1626220906-22629-1-git-send-email-mikelley@microsoft.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>

authored by

Michael Kelley and committed by
Wei Liu
31e5e646 5f92b45c

+25 -10
-3
drivers/clocksource/hyperv_timer.c
··· 361 361 * Hyper-V and 32-bit x86. The TSC reference page version is preferred. 362 362 */ 363 363 364 - u64 (*hv_read_reference_counter)(void); 365 - EXPORT_SYMBOL_GPL(hv_read_reference_counter); 366 - 367 364 static union { 368 365 struct ms_hyperv_tsc_page page; 369 366 u8 reserved[PAGE_SIZE];
+14
drivers/hv/hv_common.c
··· 222 222 } 223 223 EXPORT_SYMBOL_GPL(hv_is_hibernation_supported); 224 224 225 + /* 226 + * Default function to read the Hyper-V reference counter, independent 227 + * of whether Hyper-V enlightened clocks/timers are being used. But on 228 + * architectures where it is used, Hyper-V enlightenment code in 229 + * hyperv_timer.c may override this function. 230 + */ 231 + static u64 __hv_read_ref_counter(void) 232 + { 233 + return hv_get_register(HV_REGISTER_TIME_REF_COUNT); 234 + } 235 + 236 + u64 (*hv_read_reference_counter)(void) = __hv_read_ref_counter; 237 + EXPORT_SYMBOL_GPL(hv_read_reference_counter); 238 + 225 239 /* These __weak functions provide default "no-op" behavior and 226 240 * may be overridden by architecture specific versions. Architectures 227 241 * for which the default "no-op" behavior is sufficient can leave
-5
drivers/hv/hv_util.c
··· 17 17 #include <linux/hyperv.h> 18 18 #include <linux/clockchips.h> 19 19 #include <linux/ptp_clock_kernel.h> 20 - #include <clocksource/hyperv_timer.h> 21 20 #include <asm/mshyperv.h> 22 21 23 22 #include "hyperv_vmbus.h" ··· 734 735 735 736 static int hv_timesync_init(struct hv_util_service *srv) 736 737 { 737 - /* TimeSync requires Hyper-V clocksource. */ 738 - if (!hv_read_reference_counter) 739 - return -ENODEV; 740 - 741 738 spin_lock_init(&host_ts.lock); 742 739 743 740 INIT_WORK(&adj_time_work, hv_set_host_time);
+2
include/asm-generic/mshyperv.h
··· 167 167 extern u32 *hv_vp_index; 168 168 extern u32 hv_max_vp_index; 169 169 170 + extern u64 (*hv_read_reference_counter)(void); 171 + 170 172 /* Sentinel value for an uninitialized entry in hv_vp_index array */ 171 173 #define VP_INVAL U32_MAX 172 174
+9 -2
include/clocksource/hyperv_timer.h
··· 20 20 #define HV_MAX_MAX_DELTA_TICKS 0xffffffff 21 21 #define HV_MIN_DELTA_TICKS 1 22 22 23 + #ifdef CONFIG_HYPERV_TIMER 24 + 23 25 /* Routines called by the VMbus driver */ 24 26 extern int hv_stimer_alloc(bool have_percpu_irqs); 25 27 extern int hv_stimer_cleanup(unsigned int cpu); ··· 30 28 extern void hv_stimer_global_cleanup(void); 31 29 extern void hv_stimer0_isr(void); 32 30 33 - #ifdef CONFIG_HYPERV_TIMER 34 - extern u64 (*hv_read_reference_counter)(void); 35 31 extern void hv_init_clocksource(void); 36 32 37 33 extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void); ··· 100 100 { 101 101 return U64_MAX; 102 102 } 103 + 104 + static inline int hv_stimer_cleanup(unsigned int cpu) { return 0; } 105 + static inline void hv_stimer_legacy_init(unsigned int cpu, int sint) {} 106 + static inline void hv_stimer_legacy_cleanup(unsigned int cpu) {} 107 + static inline void hv_stimer_global_cleanup(void) {} 108 + static inline void hv_stimer0_isr(void) {} 109 + 103 110 #endif /* CONFIG_HYPERV_TIMER */ 104 111 105 112 #endif