aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/tsc.c
diff options
context:
space:
mode:
authorAlok Kataria <akataria@vmware.com>2008-10-27 13:41:46 -0400
committerH. Peter Anvin <hpa@zytor.com>2008-11-01 21:57:08 -0400
commit88b094fb8d4fe43b7025ea8d487059e8813e02cd (patch)
treefa2fc5386aeb1d62d3901c9a39c8fbb2b6be43d2 /arch/x86/kernel/tsc.c
parent49ab56ac6e1b907b7dadb72a4012460359feaf0e (diff)
x86: Hypervisor detection and get tsc_freq from hypervisor
Impact: Changes timebase calibration on Vmware. v3->v2 : Abstract the hypervisor detection and feature (tsc_freq) request behind a hypervisor.c file v2->v1 : Add a x86_hyper_vendor field to the cpuinfo_x86 structure. This avoids multiple calls to the hypervisor detection function. This patch adds function to detect if we are running under VMware. The current way to check if we are on VMware is following, # check if "hypervisor present bit" is set, if so read the 0x40000000 cpuid leaf and check for "VMwareVMware" signature. # if the above fails, check the DMI vendors name for "VMware" string if we find one we query the VMware hypervisor port to check if we are under VMware. The DMI + "VMware hypervisor port check" is needed for older VMware products, which don't implement the hypervisor signature cpuid leaf. Also note that since we are checking for the DMI signature the hypervisor port should never be accessed on native hardware. This patch also adds a hypervisor_get_tsc_freq function, instead of calibrating the frequency which can be error prone in virtualized environment, we ask the hypervisor for it. We get the frequency from the hypervisor by accessing the hypervisor port if we are running on VMware. Other hypervisors too can add code to the generic routine to get frequency on their platform. Signed-off-by: Alok N Kataria <akataria@vmware.com> Signed-off-by: Dan Hecht <dhecht@vmware.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/tsc.c')
-rw-r--r--arch/x86/kernel/tsc.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 62348e4fd8d1..6dbf0bcb44a8 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -15,6 +15,7 @@
15#include <asm/vgtod.h> 15#include <asm/vgtod.h>
16#include <asm/time.h> 16#include <asm/time.h>
17#include <asm/delay.h> 17#include <asm/delay.h>
18#include <asm/hypervisor.h>
18 19
19unsigned int cpu_khz; /* TSC clocks / usec, not used here */ 20unsigned int cpu_khz; /* TSC clocks / usec, not used here */
20EXPORT_SYMBOL(cpu_khz); 21EXPORT_SYMBOL(cpu_khz);
@@ -352,9 +353,15 @@ unsigned long native_calibrate_tsc(void)
352{ 353{
353 u64 tsc1, tsc2, delta, ref1, ref2; 354 u64 tsc1, tsc2, delta, ref1, ref2;
354 unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; 355 unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
355 unsigned long flags, latch, ms, fast_calibrate; 356 unsigned long flags, latch, ms, fast_calibrate, tsc_khz;
356 int hpet = is_hpet_enabled(), i, loopmin; 357 int hpet = is_hpet_enabled(), i, loopmin;
357 358
359 tsc_khz = get_hypervisor_tsc_freq();
360 if (tsc_khz) {
361 printk(KERN_INFO "TSC: Frequency read from the hypervisor\n");
362 return tsc_khz;
363 }
364
358 local_irq_save(flags); 365 local_irq_save(flags);
359 fast_calibrate = quick_pit_calibrate(); 366 fast_calibrate = quick_pit_calibrate();
360 local_irq_restore(flags); 367 local_irq_restore(flags);