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