@@ -404,13 +404,26 @@ static void __init reduced_hw_init(void)
404404 x86_init .irqs .pre_vector_init = x86_init_noop ;
405405}
406406
407+ int hv_get_hypervisor_version (union hv_hypervisor_version_info * info )
408+ {
409+ unsigned int hv_max_functions ;
410+
411+ hv_max_functions = cpuid_eax (HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS );
412+ if (hv_max_functions < HYPERV_CPUID_VERSION ) {
413+ pr_err ("%s: Could not detect Hyper-V version\n" , __func__ );
414+ return - ENODEV ;
415+ }
416+
417+ cpuid (HYPERV_CPUID_VERSION , & info -> eax , & info -> ebx , & info -> ecx , & info -> edx );
418+
419+ return 0 ;
420+ }
421+
407422static void __init ms_hyperv_init_platform (void )
408423{
424+ union hv_hypervisor_version_info version ;
425+ unsigned int build = 0 ;
409426 int hv_max_functions_eax ;
410- int hv_host_info_eax ;
411- int hv_host_info_ebx ;
412- int hv_host_info_ecx ;
413- int hv_host_info_edx ;
414427
415428#ifdef CONFIG_PARAVIRT
416429 pv_info .name = "Hyper-V" ;
@@ -436,6 +449,18 @@ static void __init ms_hyperv_init_platform(void)
436449 pr_debug ("Hyper-V: max %u virtual processors, %u logical processors\n" ,
437450 ms_hyperv .max_vp_index , ms_hyperv .max_lp_index );
438451
452+ /*
453+ * Host builds earlier than 22621 (Win 11 22H2) have a bug in the
454+ * invariant TSC feature that may result in the guest seeing a "slow"
455+ * TSC after host hibernation. This causes problems with synthetic
456+ * timer interrupts. In such a case, avoid the bug by assuming the
457+ * feature is not present.
458+ */
459+ if (!hv_get_hypervisor_version (& version ))
460+ build = version .build_number ;
461+ if (build < 22621 )
462+ ms_hyperv .features &= ~HV_ACCESS_TSC_INVARIANT ;
463+
439464 /*
440465 * Check CPU management privilege.
441466 *
@@ -461,21 +486,6 @@ static void __init ms_hyperv_init_platform(void)
461486 pr_info ("Hyper-V: running on a nested hypervisor\n" );
462487 }
463488
464- /*
465- * Extract host information.
466- */
467- if (hv_max_functions_eax >= HYPERV_CPUID_VERSION ) {
468- hv_host_info_eax = cpuid_eax (HYPERV_CPUID_VERSION );
469- hv_host_info_ebx = cpuid_ebx (HYPERV_CPUID_VERSION );
470- hv_host_info_ecx = cpuid_ecx (HYPERV_CPUID_VERSION );
471- hv_host_info_edx = cpuid_edx (HYPERV_CPUID_VERSION );
472-
473- pr_info ("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n" ,
474- hv_host_info_ebx >> 16 , hv_host_info_ebx & 0xFFFF ,
475- hv_host_info_eax , hv_host_info_edx & 0xFFFFFF ,
476- hv_host_info_ecx , hv_host_info_edx >> 24 );
477- }
478-
479489 if (ms_hyperv .features & HV_ACCESS_FREQUENCY_MSRS &&
480490 ms_hyperv .misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE ) {
481491 x86_platform .calibrate_tsc = hv_get_tsc_khz ;
0 commit comments