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>
This commit is contained in:
parent
1a1891d762
commit
cf11372949
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue