summaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/vmware.c
diff options
context:
space:
mode:
authorAlexey Makhalov <amakhalov@vmware.com>2016-10-19 22:02:11 -0700
committerThomas Gleixner <tglx@linutronix.de>2016-10-21 10:12:11 +0200
commitcf11372949434fc4a6194b1ed9eb861d08032d08 (patch)
tree20c5ecbe1186df54f94b6762d17d47f9d9dd8491 /arch/x86/kernel/cpu/vmware.c
parent1a1891d762d6e64daf07b5be4817e3fbb29e3c59 (diff)
x86/vmware: Read tsc_khz only once at boot time
Re-factor the vmware platform setup code to query the hypervisor for tsc frequency only once during boot. Since the VMware hypervisor guarantees constant TSC, calibrate_tsc now uses the saved value. Signed-off-by: Alexey Makhalov <amakhalov@vmware.com> Acked-by: Alok N Kataria <akataria@vmware.com> Cc: virtualization@lists.linux-foundation.org Link: http://lkml.kernel.org/r/20161020050211.GA25304@amakhalov-virtual-machine Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/cpu/vmware.c')
-rw-r--r--arch/x86/kernel/cpu/vmware.c37
1 files changed, 18 insertions, 19 deletions
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 81160578b91a..4e34da4be297 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -47,6 +47,8 @@
"2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) : \
"memory");
+static unsigned long vmware_tsc_khz __ro_after_init;
+
static inline int __vmware_platform(void)
{
uint32_t eax, ebx, ecx, edx;
@@ -56,35 +58,32 @@ static inline int __vmware_platform(void)
static unsigned long vmware_get_tsc_khz(void)
{
- uint64_t tsc_hz, lpj;
- uint32_t eax, ebx, ecx, edx;
-
- VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
-
- tsc_hz = eax | (((uint64_t)ebx) << 32);
- do_div(tsc_hz, 1000);
- BUG_ON(tsc_hz >> 32);
- pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
- (unsigned long) tsc_hz / 1000,
- (unsigned long) tsc_hz % 1000);
-
- if (!preset_lpj) {
- lpj = ((u64)tsc_hz * 1000);
- do_div(lpj, HZ);
- preset_lpj = lpj;
- }
-
- return tsc_hz;
+ return vmware_tsc_khz;
}
static void __init vmware_platform_setup(void)
{
uint32_t eax, ebx, ecx, edx;
+ uint64_t lpj, tsc_khz;
VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
if (ebx != UINT_MAX) {
+ lpj = tsc_khz = eax | (((uint64_t)ebx) << 32);
+ do_div(tsc_khz, 1000);
+ WARN_ON(tsc_khz >> 32);
+ pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
+ (unsigned long) tsc_khz / 1000,
+ (unsigned long) tsc_khz % 1000);
+
+ if (!preset_lpj) {
+ do_div(lpj, HZ);
+ preset_lpj = lpj;
+ }
+
+ vmware_tsc_khz = tsc_khz;
x86_platform.calibrate_tsc = vmware_get_tsc_khz;
+
#ifdef CONFIG_X86_LOCAL_APIC
/* Skip lapic calibration since we know the bus frequency. */
lapic_timer_frequency = ecx / HZ;