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

clocksource/drivers/hyperv: Enable TSC page clocksource on 32bit

There is no particular reason to not enable TSC page clocksource on
32-bit. mul_u64_u64_shr() is available and despite the increased
computational complexity (compared to 64bit) TSC page is still a huge win
compared to MSR-based clocksource.

In-kernel reads:
MSR based clocksource: 3361 cycles
TSC page clocksource: 49 cycles

Reads from userspace (utilizing vDSO in case of TSC page):
MSR based clocksource: 5664 cycles
TSC page clocksource: 131 cycles

Enabling TSC page on 32bits allows to get rid of CONFIG_HYPERV_TSCPAGE as
it is now not any different from CONFIG_HYPERV_TIMER.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lkml.kernel.org/r/20190822083630.17059-1-vkuznets@redhat.com

authored by

Vitaly Kuznetsov and committed by
Thomas Gleixner
3e2d9453 bd00cd52

+6 -22
+3 -3
arch/x86/include/asm/vdso/gettimeofday.h
··· 51 51 __attribute__((visibility("hidden"))); 52 52 #endif 53 53 54 - #ifdef CONFIG_HYPERV_TSCPAGE 54 + #ifdef CONFIG_HYPERV_TIMER 55 55 extern struct ms_hyperv_tsc_page hvclock_page 56 56 __attribute__((visibility("hidden"))); 57 57 #endif ··· 192 192 } 193 193 #endif 194 194 195 - #ifdef CONFIG_HYPERV_TSCPAGE 195 + #ifdef CONFIG_HYPERV_TIMER 196 196 static u64 vread_hvclock(void) 197 197 { 198 198 return hv_read_tsc_page(&hvclock_page); ··· 215 215 return vread_pvclock(); 216 216 } 217 217 #endif 218 - #ifdef CONFIG_HYPERV_TSCPAGE 218 + #ifdef CONFIG_HYPERV_TIMER 219 219 if (clock_mode == VCLOCK_HVCLOCK) { 220 220 barrier(); 221 221 return vread_hvclock();
-11
drivers/clocksource/hyperv_timer.c
··· 213 213 struct clocksource *hyperv_cs; 214 214 EXPORT_SYMBOL_GPL(hyperv_cs); 215 215 216 - #ifdef CONFIG_HYPERV_TSCPAGE 217 - 218 216 static struct ms_hyperv_tsc_page tsc_pg __aligned(PAGE_SIZE); 219 217 220 218 struct ms_hyperv_tsc_page *hv_get_tsc_page(void) ··· 243 245 .mask = CLOCKSOURCE_MASK(64), 244 246 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 245 247 }; 246 - #endif 247 248 248 249 static u64 notrace read_hv_clock_msr(struct clocksource *arg) 249 250 { ··· 269 272 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 270 273 }; 271 274 272 - #ifdef CONFIG_HYPERV_TSCPAGE 273 275 static bool __init hv_init_tsc_clocksource(void) 274 276 { 275 277 u64 tsc_msr; ··· 300 304 301 305 return true; 302 306 } 303 - #else 304 - static bool __init hv_init_tsc_clocksource(void) 305 - { 306 - return false; 307 - } 308 - #endif 309 - 310 307 311 308 void __init hv_init_clocksource(void) 312 309 {
-3
drivers/hv/Kconfig
··· 14 14 config HYPERV_TIMER 15 15 def_bool HYPERV 16 16 17 - config HYPERV_TSCPAGE 18 - def_bool HYPERV && X86_64 19 - 20 17 config HYPERV_UTILS 21 18 tristate "Microsoft Hyper-V Utilities driver" 22 19 depends on HYPERV && CONNECTOR && NLS
+3 -5
include/clocksource/hyperv_timer.h
··· 28 28 extern void hv_stimer_global_cleanup(void); 29 29 extern void hv_stimer0_isr(void); 30 30 31 - #if IS_ENABLED(CONFIG_HYPERV) 31 + #ifdef CONFIG_HYPERV_TIMER 32 32 extern struct clocksource *hyperv_cs; 33 33 extern void hv_init_clocksource(void); 34 - #endif /* CONFIG_HYPERV */ 35 34 36 - #ifdef CONFIG_HYPERV_TSCPAGE 37 35 extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void); 38 36 39 37 static inline notrace u64 ··· 89 91 return hv_read_tsc_page_tsc(tsc_pg, &cur_tsc); 90 92 } 91 93 92 - #else /* CONFIG_HYPERV_TSC_PAGE */ 94 + #else /* CONFIG_HYPERV_TIMER */ 93 95 static inline struct ms_hyperv_tsc_page *hv_get_tsc_page(void) 94 96 { 95 97 return NULL; ··· 100 102 { 101 103 return U64_MAX; 102 104 } 103 - #endif /* CONFIG_HYPERV_TSCPAGE */ 105 + #endif /* CONFIG_HYPERV_TIMER */ 104 106 105 107 #endif