x86: Warn on CPU hot-add to tsc-reliable system
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 28 May 2010 07:03:02 +0000 (08:03 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 28 May 2010 07:03:02 +0000 (08:03 +0100)
...and provide a boot option to indicate TSCs may be skewed.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/setup.c
xen/arch/x86/smpboot.c
xen/arch/x86/time.c

index 845f31d531cdaa9c14eb036d1e6a82b07a516c12..b54ba7b894b26ecee4558b740ab4c7c0253c696d 100644 (file)
@@ -69,10 +69,6 @@ integer_param("maxcpus", max_cpus);
 static int __initdata opt_watchdog = 0;
 boolean_param("watchdog", opt_watchdog);
 
-/* opt_tsc_unstable: Override all tests; assume TSC is unreliable. */
-static int opt_tsc_unstable;
-boolean_param("tsc_unstable", opt_tsc_unstable);
-
 /* **** Linux config option: propagated to domain0. */
 /* "acpi=off":    Sisables both ACPI table parsing and interpreter. */
 /* "acpi=force":  Override the disable blacklist.                   */
@@ -416,14 +412,6 @@ void __init __start_xen(unsigned long mbi_p)
     }
     cmdline_parse(cmdline);
 
-    /* If TSC is marked as unstable, clear all enhanced TSC features. */
-    if ( opt_tsc_unstable )
-    {
-        setup_clear_cpu_cap(X86_FEATURE_CONSTANT_TSC);
-        setup_clear_cpu_cap(X86_FEATURE_NONSTOP_TSC);
-        setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
-    }
-
     parse_video_info();
 
     set_current((struct vcpu *)0xfffff000); /* debug sanity */
index f8376431dc4329ec5e8c9c9b9a4f02eb0ec3bb11..d873e85e25e19c7b72a8ca99cd026906e1a8966f 100644 (file)
@@ -923,7 +923,17 @@ int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm)
     }
 
     /* Physically added CPUs do not have synchronised TSC. */
-    cpu_set(cpu, tsc_sync_cpu_mask);
+    if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
+    {
+        static bool_t once_only;
+        if ( !test_and_set_bool(once_only) )
+            printk(XENLOG_WARNING
+                   " ** New physical CPU %u may have skewed TSC and hence "
+                   "break assumed cross-CPU TSC coherency.\n"
+                   " ** Consider using boot parameter \"tsc=skewed\" "
+                   "which forces TSC emulation where appropriate.\n", cpu);
+        cpu_set(cpu, tsc_sync_cpu_mask);
+    }
 
     srat_detect_node(cpu);
     numa_add_cpu(cpu);
index ee535c186e83dad5b6e5fc14eff5fc5b0776e8bd..d500490254f2c1f1568fb22c39246d6e038949d1 100644 (file)
@@ -1598,6 +1598,25 @@ struct tm wallclock_time(void)
  * PV SoftTSC Emulation.
  */
 
+/*
+ * tsc=unstable: Override all tests; assume TSC is unreliable.
+ * tsc=skewed: Assume TSCs are individually reliable, but skewed across CPUs.
+ */
+static void __init tsc_parse(const char *s)
+{
+    if ( !strcmp(s, "unstable") )
+    {
+        setup_clear_cpu_cap(X86_FEATURE_CONSTANT_TSC);
+        setup_clear_cpu_cap(X86_FEATURE_NONSTOP_TSC);
+        setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+    }
+    else if ( !strcmp(s, "skewed") )
+    {
+        setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+    }
+}
+custom_param("tsc", tsc_parse);
+
 u64 gtime_to_gtsc(struct domain *d, u64 tsc)
 {
     if ( !is_hvm_domain(d) )
@@ -1636,7 +1655,7 @@ void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs, int rdtscp)
 
 int host_tsc_is_safe(void)
 {
-    return boot_cpu_has(X86_FEATURE_TSC_RELIABLE) || (num_online_cpus() == 1);
+    return boot_cpu_has(X86_FEATURE_TSC_RELIABLE);
 }
 
 void cpuid_time_leaf(uint32_t sub_idx, uint32_t *eax, uint32_t *ebx,