[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 01/16] x86/tsc: Add a standalone helpers for getting TSC info from CPUID.0x15



Extract retrieval of TSC frequency information from CPUID into standalone
helpers so that TDX guest support and kvmlock can reuse the logic.  Provide
a version that includes the multiplier math as TDX in particular does NOT
want to use native_calibrate_tsc()'s fallback logic that derives the TSC
frequency based on CPUID.0x16 when the core crystal frequency isn't known.

No functional change intended.

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 arch/x86/include/asm/tsc.h | 41 ++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/tsc.c      | 14 ++-----------
 2 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
index 94408a784c8e..14a81a66b37c 100644
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -28,6 +28,47 @@ static inline cycles_t get_cycles(void)
 }
 #define get_cycles get_cycles
 
+static inline int cpuid_get_tsc_info(unsigned int *crystal_khz,
+                                    unsigned int *denominator,
+                                    unsigned int *numerator)
+{
+       unsigned int ecx_hz, edx;
+
+       if (boot_cpu_data.cpuid_level < CPUID_LEAF_TSC)
+               return -ENOENT;
+
+       *crystal_khz = *denominator = *numerator = ecx_hz = edx = 0;
+
+       /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */
+       cpuid(CPUID_LEAF_TSC, denominator, numerator, &ecx_hz, &edx);
+
+       if (!*denominator || !*numerator)
+               return -ENOENT;
+
+       /*
+        * Note, some CPUs provide the multiplier information, but not the core
+        * crystal frequency.  The multiplier information is still useful for
+        * such CPUs, as the crystal frequency can be gleaned from CPUID.0x16.
+        */
+       *crystal_khz = ecx_hz / 1000;
+       return 0;
+}
+
+static inline int cpuid_get_tsc_freq(unsigned int *tsc_khz,
+                                    unsigned int *crystal_khz)
+{
+       unsigned int denominator, numerator;
+
+       if (cpuid_get_tsc_info(tsc_khz, &denominator, &numerator))
+               return -ENOENT;
+
+       if (!*crystal_khz)
+               return -ENOENT;
+
+       *tsc_khz = *crystal_khz * numerator / denominator;
+       return 0;
+}
+
 extern void tsc_early_init(void);
 extern void tsc_init(void);
 extern void mark_tsc_unstable(char *reason);
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 34dec0b72ea8..e3faa2b36910 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -661,25 +661,15 @@ static unsigned long quick_pit_calibrate(void)
  */
 unsigned long native_calibrate_tsc(void)
 {
-       unsigned int eax_denominator, ebx_numerator, ecx_hz, edx;
+       unsigned int eax_denominator, ebx_numerator;
        unsigned int crystal_khz;
 
        if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
                return 0;
 
-       if (boot_cpu_data.cpuid_level < CPUID_LEAF_TSC)
+       if (cpuid_get_tsc_info(&crystal_khz, &eax_denominator, &ebx_numerator))
                return 0;
 
-       eax_denominator = ebx_numerator = ecx_hz = edx = 0;
-
-       /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */
-       cpuid(CPUID_LEAF_TSC, &eax_denominator, &ebx_numerator, &ecx_hz, &edx);
-
-       if (ebx_numerator == 0 || eax_denominator == 0)
-               return 0;
-
-       crystal_khz = ecx_hz / 1000;
-
        /*
         * Denverton SoCs don't report crystal clock, and also don't support
         * CPUID_LEAF_FREQ for the calculation below, so hardcode the 25MHz
-- 
2.48.1.362.g079036d154-goog




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.