aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorAlok Kataria <akataria@vmware.com>2008-10-31 15:01:58 -0400
committerH. Peter Anvin <hpa@zytor.com>2008-11-01 21:58:01 -0400
commiteca0cd028bdf0f6aaceb0d023e9c7501079a7dda (patch)
tree13a3a723f4e286a617437442138f2a6130502142 /arch/x86/kernel
parent88b094fb8d4fe43b7025ea8d487059e8813e02cd (diff)
x86: Add a synthetic TSC_RELIABLE feature bit.
Impact: Changes timebase calibration on Vmware. Use the synthetic TSC_RELIABLE bit to workaround virtualization anomalies. Virtual TSCs can be kept nearly in sync, but because the virtual TSC offset is set by software, it's not perfect. So, the TSC synchronization test can fail. Even then the TSC can be used as a clocksource since the VMware platform exports a reliable TSC to the guest for timekeeping purposes. Use this bit to check if we need to skip the TSC sync checks. Along with this also set the CONSTANT_TSC bit when on VMware, since we still want to use TSC as clocksource on VM running over hardware which has unsynchronized TSC's (opteron's), since the hypervisor will take care of providing consistent TSC to the guest. 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')
-rw-r--r--arch/x86/kernel/cpu/hypervisor.c11
-rw-r--r--arch/x86/kernel/cpu/vmware.c18
-rw-r--r--arch/x86/kernel/tsc_sync.c8
3 files changed, 35 insertions, 2 deletions
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index 7bd55064ffe..35ae2b75226 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -41,8 +41,17 @@ unsigned long get_hypervisor_tsc_freq(void)
41 return 0; 41 return 0;
42} 42}
43 43
44static inline void __cpuinit
45hypervisor_set_feature_bits(struct cpuinfo_x86 *c)
46{
47 if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) {
48 vmware_set_feature_bits(c);
49 return;
50 }
51}
52
44void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) 53void __cpuinit init_hypervisor(struct cpuinfo_x86 *c)
45{ 54{
46 detect_hypervisor_vendor(c); 55 detect_hypervisor_vendor(c);
56 hypervisor_set_feature_bits(c);
47} 57}
48
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index d5d1b75a4b7..2ac4394fcb9 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -86,3 +86,21 @@ unsigned long vmware_get_tsc_khz(void)
86 BUG_ON(!vmware_platform()); 86 BUG_ON(!vmware_platform());
87 return __vmware_get_tsc_khz(); 87 return __vmware_get_tsc_khz();
88} 88}
89
90/*
91 * VMware hypervisor takes care of exporting a reliable TSC to the guest.
92 * Still, due to timing difference when running on virtual cpus, the TSC can
93 * be marked as unstable in some cases. For example, the TSC sync check at
94 * bootup can fail due to a marginal offset between vcpus' TSCs (though the
95 * TSCs do not drift from each other). Also, the ACPI PM timer clocksource
96 * is not suitable as a watchdog when running on a hypervisor because the
97 * kernel may miss a wrap of the counter if the vcpu is descheduled for a
98 * long time. To skip these checks at runtime we set these capability bits,
99 * so that the kernel could just trust the hypervisor with providing a
100 * reliable virtual TSC that is suitable for timekeeping.
101 */
102void __cpuinit vmware_set_feature_bits(struct cpuinfo_x86 *c)
103{
104 set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
105 set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
106}
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c
index 9ffb01c31c4..5977c40a138 100644
--- a/arch/x86/kernel/tsc_sync.c
+++ b/arch/x86/kernel/tsc_sync.c
@@ -108,6 +108,12 @@ void __cpuinit check_tsc_sync_source(int cpu)
108 if (unsynchronized_tsc()) 108 if (unsynchronized_tsc())
109 return; 109 return;
110 110
111 if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
112 printk(KERN_INFO
113 "Skipping synchronization checks as TSC is reliable.\n");
114 return;
115 }
116
111 printk(KERN_INFO "checking TSC synchronization [CPU#%d -> CPU#%d]:", 117 printk(KERN_INFO "checking TSC synchronization [CPU#%d -> CPU#%d]:",
112 smp_processor_id(), cpu); 118 smp_processor_id(), cpu);
113 119
@@ -161,7 +167,7 @@ void __cpuinit check_tsc_sync_target(void)
161{ 167{
162 int cpus = 2; 168 int cpus = 2;
163 169
164 if (unsynchronized_tsc()) 170 if (unsynchronized_tsc() || boot_cpu_has(X86_FEATURE_TSC_RELIABLE))
165 return; 171 return;
166 172
167 /* 173 /*