From: Andres Freund Date: Thu, 9 Apr 2026 15:50:24 +0000 (-0400) Subject: instrumentation: Avoid CPUID 0x15/0x16 for Hypervisor TSC frequency X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7fc36c5db55016f7a1d89b5e2efd82fe6fd39632;p=thirdparty%2Fpostgresql.git 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 Reviewed-by: Andres Freund Discussion: https://postgr.es/m/jr4hk2sxhqcfpb67ftz5g4vw33nm67cgf7go3wwmqsafu5aclq%405m67ukuhyszz --- 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