]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
x86: Add a synthetic TSC_RELIABLE feature bit.
authorAlok Kataria <akataria@vmware.com>
Fri, 31 Oct 2008 19:01:58 +0000 (12:01 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Sun, 2 Nov 2008 01:58:01 +0000 (18:58 -0700)
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>
arch/x86/include/asm/vmware.h
arch/x86/kernel/cpu/hypervisor.c
arch/x86/kernel/cpu/vmware.c
arch/x86/kernel/tsc_sync.c

index 02dfea5aebc40148c08ed173561c7fc9eb7d7943..c11b7e100d838278402ce2e3976d46fcc1c86b86 100644 (file)
@@ -22,5 +22,6 @@
 
 extern unsigned long vmware_get_tsc_khz(void);
 extern int vmware_platform(void);
+extern void vmware_set_feature_bits(struct cpuinfo_x86 *c);
 
 #endif
index 7bd55064ffe9be3fa3b0abb8ed89020c0773c361..35ae2b75226d23a7462f3999d1671067adb106ad 100644 (file)
@@ -41,8 +41,17 @@ unsigned long get_hypervisor_tsc_freq(void)
        return 0;
 }
 
+static inline void __cpuinit
+hypervisor_set_feature_bits(struct cpuinfo_x86 *c)
+{
+       if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) {
+               vmware_set_feature_bits(c);
+               return;
+       }
+}
+
 void __cpuinit init_hypervisor(struct cpuinfo_x86 *c)
 {
        detect_hypervisor_vendor(c);
+       hypervisor_set_feature_bits(c);
 }
-
index d5d1b75a4b7731b79a4e454552164c4a2348fd02..2ac4394fcb90bc7f345fb62b8a7a8e28bb2179e9 100644 (file)
@@ -86,3 +86,21 @@ unsigned long vmware_get_tsc_khz(void)
        BUG_ON(!vmware_platform());
        return __vmware_get_tsc_khz();
 }
+
+/*
+ * VMware hypervisor takes care of exporting a reliable TSC to the guest.
+ * Still, due to timing difference when running on virtual cpus, the TSC can
+ * be marked as unstable in some cases. For example, the TSC sync check at
+ * bootup can fail due to a marginal offset between vcpus' TSCs (though the
+ * TSCs do not drift from each other).  Also, the ACPI PM timer clocksource
+ * is not suitable as a watchdog when running on a hypervisor because the
+ * kernel may miss a wrap of the counter if the vcpu is descheduled for a
+ * long time. To skip these checks at runtime we set these capability bits,
+ * so that the kernel could just trust the hypervisor with providing a
+ * reliable virtual TSC that is suitable for timekeeping.
+ */
+void __cpuinit vmware_set_feature_bits(struct cpuinfo_x86 *c)
+{
+       set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+       set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
+}
index 9ffb01c31c40a8c9083e9949d065a442a62f46b7..5977c40a138f3bb9fdda1c12e9f914dd0bcdce09 100644 (file)
@@ -108,6 +108,12 @@ void __cpuinit check_tsc_sync_source(int cpu)
        if (unsynchronized_tsc())
                return;
 
+       if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
+               printk(KERN_INFO
+                      "Skipping synchronization checks as TSC is reliable.\n");
+               return;
+       }
+
        printk(KERN_INFO "checking TSC synchronization [CPU#%d -> CPU#%d]:",
                          smp_processor_id(), cpu);
 
@@ -161,7 +167,7 @@ void __cpuinit check_tsc_sync_target(void)
 {
        int cpus = 2;
 
-       if (unsynchronized_tsc())
+       if (unsynchronized_tsc() || boot_cpu_has(X86_FEATURE_TSC_RELIABLE))
                return;
 
        /*