postgres.git / summary / log / commit / refs

commit    7fc36c5db55016f7a1d89b5e2efd82fe6fd39632
Author:   Andres Freund <andres@anarazel.de>
Date:     Thu Apr 09 15:50:24 2026 +0000

    instrumentation: Avoid CPUID 0x15/0x16 for Hypervisor TSC frequency
    
    This restricts the retrieval of the TSC frequency whilst under a Hypervisor to
    either Hypervisor-specific CPUID registers (0x40000010), or TSC
    calibration. We previously allowed retrieving from the traditional CPUID
    registers for TSC frequency (0x15/0x16) like on bare metal, but it turns out
    that they are not trustworthy when virtualized and can report wildly incorrect
    frequencies, like 7 kHz when the actual calibrated frequencty is 2.5 GHz.
    
    Per report from buildfarm member drongo.
    
    Author: Lukas Fittl <lukas@fittl.com>
    Reviewed-by: Andres Freund <andres@anarazel.de>
    Discussion: https://postgr.es/m/jr4hk2sxhqcfpb67ftz5g4vw33nm67cgf7go3wwmqsafu5aclq%405m67ukuhyszz


src/port/pg_cpu_x86.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/port/pg_cpu_x86.c b/src/port/pg_cpu_x86.c index 32d0cecbe2c..150b4a1d574 100644 --- a/src/port/pg_cpu_x86.c +++ b/src/port/pg_cpu_x86.c @@ -165,19 +165,16 @@ x86_tsc_frequency_khz(void) { unsigned int reg[4] = {0}; + /* + * If we're inside a virtual machine, try to fetch the TSC frequency from + * the hypervisor, using a hypervisor specific method. + * + * Note it is not safe to utilize the regular 0x15/0x16 CPUID registers + * (i.e. the logic below) in virtual machines, as they have been observed + * to be wildly incorrect when virtualized. + */ if (x86_feature_available(PG_HYPERVISOR)) - { - uint32 freq = x86_hypervisor_tsc_frequency_khz(); - - /* - * If the hypervisor specific logic didn't figure out the frequency, - * it's possible (although not likely, as often that's hidden from - * guests) that the non-virtualized logic can figure out the - * frequency. - */ - if (freq > 0) - return freq; - } + return x86_hypervisor_tsc_frequency_khz(); /* * On modern Intel CPUs, the TSC is implemented by invariant timekeeping [parent: 60165db6e1f2]