From: Sean Christopherson <[email protected]> Sent: Wednesday, May 20, 2026 9:41 AM > > On Tue, May 19, 2026, Michael Kelley wrote: > > From: Sean Christopherson <[email protected]> Sent: Monday, May 18, 2026 > > 3:18 PM > > > > > diff --git a/arch/x86/kernel/cpu/mshyperv.c > > > > > b/arch/x86/kernel/cpu/mshyperv.c > > > > > --- a/arch/x86/kernel/cpu/mshyperv.c > > > > > +++ b/arch/x86/kernel/cpu/mshyperv.c > > > > > @@ -516,8 +516,13 @@ static void __init ms_hyperv_init_platform(void) > > > > > > > > > > if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS && > > > > > ms_hyperv.misc_features & > > > > > HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { > > > > > - tsc_register_calibration_routines(hv_get_tsc_khz, > > > > > hv_get_tsc_khz); > > > > > - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); > > > > > + enum tsc_properties tsc_properties = > > > > > TSC_FREQUENCY_KNOWN; > > > > > + > > > > > + if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) > > > > > + tsc_properties = TSC_FREQ_KNOWN_AND_RELIABLE; > > > > > + > > > > > + tsc_register_calibration_routines(hv_get_tsc_khz, > > > > > hv_get_tsc_khz, > > > > > + tsc_properties); > > > > > } > > > > > > > > [ ... ] > > > > > > > > > @@ -629,7 +634,6 @@ static void __init ms_hyperv_init_platform(void) > > > > > * is called. > > > > > */ > > > > > wrmsrq(HV_X64_MSR_TSC_INVARIANT_CONTROL, > > > > > HV_EXPOSE_INVARIANT_TSC); > > > > > - setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE); > > > > > } > > > > > > > > If a Hyper-V VM exposes an invariant TSC but lacks the frequency MSRs, > > > > does it bypass the tsc_register_calibration_routines() block entirely? > > > > > > Yes. > > > > > > > Without the standalone setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE) > > > > call > > > > here, it looks like these VMs will lose the reliable flag. > > > > > > > > Will this inadvertently enable the TSC watchdog, potentially causing a > > > > performance regression if the system falsely marks the TSC as unstable > > > > due > > > > to virtualization scheduling delays? > > > > > > Hmm, I was going to say that the change was intentional and desriable, > > > but looking > > > at this yet again, I don't think that's true. Enabling > > > HV_EXPOSE_INVARIANT_TSC > > > just means the kernel will (probably) set X86_FEATURE_CONSTANT_TSC and > > > X86_FEATURE_NONSTOP_TSC during early_init_intel(), AFAICT it doesn't lead > > > to > > > X86_FEATURE_TSC_RELIABLE being set. And I think in this case, marking > > > the TSC > > > as reliable makes sense; even if the kernel doesn't user Hyper-V's > > > calibration > > > info, the host is still clearly telling the guest that the TSC is > > > reliable. > > > > Yes, I agree. But I'm doubtful that such a combination ever occurs in > > practice. > > I've never seen an occurrence of a Hyper-V (even really old versions) guest > > where the frequency MSRs are not available or are not accessible. The > > Hyper-V spec allows for either condition, so we have the code to test the > > flags. I've thought of the flags as always set, though I suppose one never > > knows what the future holds. > > > > > > > > Michael, does keeping the > > > > > > setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE); > > > > > > but also passing TSC_FREQ_KNOWN_AND_RELIABLE to the calibration routine > > > make > > > sense? > > > > I don't see that it would break anything. But it seems a bit disjointed in > > that HV_ACCESS_TSC_INVARIANT is tested in two places in > > ms_hyperv_init_platform(). Does TSC_RELIABLE *need* to be passed to > > tsc_register_calibration_routines() if later code in > > ms_hyperv_init_platform() > > does setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE)? > > Sort of? It's not strictly necessary, but passing in TSC_RELIABLE allows > tsc_register_calibration_routines() to ensure it doesn't clobber a more robust > calibration routine with a "lesser" routine. I.e. not passing TSC_RELIABLE in > this case would trigger a false positive (and break Hyper-V). > > In other words, invoking setup_force_cpu_cap() is a (happy, desirable) side > effect, > not the primary goal. > > > In other words, I'm suggesting let tsc_register_calibration_routines() > > handle > > the TSC_FREQ_KNOWN case since that's what the calibration routines are all > > about. Leave the setting of X86_FEATURE_TSC_RELIABLE to the later code that > > tests HV_ACCESS_TSC_INVARIANT, instead of duplicating the > > setup_force_cpu_cap() operation. > > > > While combining FREQUENCY_KNOWN and RELIABLE into > > tsc_register_calibration_routines() is convenient, the two > > concepts turn out to be independent when looking strictly at > > the Hyper-V spec and code written to follow that spec. > > Combining them into the same function ends up being clumsy > > Yeah, it's a bit awkward for Hyper-V, but Hyper-V is definitely the odd one > out > here, in that it has an "out-of-band" feature that marks the TSC as reliable. > All other PV features that trigger overrides of the calibration routines > bundle > the RELIABLE aspect with the feature itself.
Indeed, Hyper-V is definitely the odd one here. Keeping the "setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE)" in the later code block where HV_ACCESS_TSC_INVARIANT is tested works well enough. In the real world, the frequency MSRs are available and accessible, so the additional "setup_force_cpu_cap()" is duplicative, but doesn't hurt anything. Michael
