]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
instrumentation: Avoid CPUID 0x15/0x16 for Hypervisor TSC frequency
authorAndres Freund <andres@anarazel.de>
Thu, 9 Apr 2026 15:50:24 +0000 (11:50 -0400)
committerAndres Freund <andres@anarazel.de>
Thu, 9 Apr 2026 15:50:46 +0000 (11:50 -0400)
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

index 32d0cecbe2c79592e4ab279875ffbfb4097b2c29..150b4a1d574d216e979fe537d571012940854906 100644 (file)
@@ -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