[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86: don't write_tsc() non-zero values on CPUs updating only the lower 32 bits



# HG changeset patch
# User Keir Fraser <keir@xxxxxxx>
# Date 1302853928 -3600
# Node ID 1329d99b4f161b7617a667f601077cc92559f248
# Parent  b5165fb66b56d9438d77b475eaa9db67318d1ea1
x86: don't write_tsc() non-zero values on CPUs updating only the lower 32 bits

This means suppressing the uses in time_calibration_tsc_rendezvous(),
cstate_restore_tsc(), and synchronize_tsc_slave(), and fixes a boot
hang of Linux Dom0 when loading processor.ko on such systems that
have support for C states above C1.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxx>
---


diff -r b5165fb66b56 -r 1329d99b4f16 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c      Thu Apr 14 14:57:24 2011 +0100
+++ b/xen/arch/x86/acpi/cpu_idle.c      Fri Apr 15 08:52:08 2011 +0100
@@ -1098,3 +1098,7 @@
     hpet_disable_legacy_broadcast();
 }
 
+bool_t cpuidle_using_deep_cstate(void)
+{
+    return xen_cpuidle && max_cstate > (local_apic_timer_c2_ok ? 2 : 1);
+}
diff -r b5165fb66b56 -r 1329d99b4f16 xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Thu Apr 14 14:57:24 2011 +0100
+++ b/xen/arch/x86/smpboot.c    Fri Apr 15 08:52:08 2011 +0100
@@ -41,6 +41,7 @@
 #include <asm/flushtlb.h>
 #include <asm/msr.h>
 #include <asm/mtrr.h>
+#include <asm/time.h>
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
@@ -124,6 +125,12 @@
     ;
 }
 
+/*
+ * TSC's upper 32 bits can't be written in earlier CPUs (before
+ * Prescott), there is no way to resync one AP against BP.
+ */
+bool_t disable_tsc_sync;
+
 static atomic_t tsc_count;
 static uint64_t tsc_value;
 static cpumask_t tsc_sync_cpu_mask;
@@ -132,6 +139,9 @@
 {
     unsigned int i;
 
+    if ( disable_tsc_sync )
+        return;
+
     if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) &&
          !cpu_isset(slave, tsc_sync_cpu_mask) )
         return;
@@ -153,6 +163,9 @@
 {
     unsigned int i;
 
+    if ( disable_tsc_sync )
+        return;
+
     if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) &&
          !cpu_isset(slave, tsc_sync_cpu_mask) )
         return;
diff -r b5165fb66b56 -r 1329d99b4f16 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Thu Apr 14 14:57:24 2011 +0100
+++ b/xen/arch/x86/time.c       Fri Apr 15 08:52:08 2011 +0100
@@ -21,6 +21,7 @@
 #include <xen/smp.h>
 #include <xen/irq.h>
 #include <xen/softirq.h>
+#include <xen/cpuidle.h>
 #include <xen/symbols.h>
 #include <xen/keyhandler.h>
 #include <xen/guest_access.h>
@@ -680,6 +681,8 @@
     if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
         return;
 
+    ASSERT(boot_cpu_has(X86_FEATURE_TSC_RELIABLE));
+
     write_tsc(stime2tsc(read_platform_stime()));
 }
 
@@ -1382,6 +1385,66 @@
     }
 }
 
+/*
+ * On certain older Intel CPUs writing the TSC MSR clears the upper 32 bits. 
+ * Obviously we must not use write_tsc() on such CPUs.
+ *
+ * Additionally, AMD specifies that being able to write the TSC MSR is not an 
+ * architectural feature (but, other than their manual says, also cannot be 
+ * determined from CPUID bits).
+ */
+static void __init tsc_check_writability(void)
+{
+    const char *what = NULL;
+    uint64_t tsc;
+
+    /*
+     * If all CPUs are reported as synchronised and in sync, we never write
+     * the TSCs (except unavoidably, when a CPU is physically hot-plugged).
+     * Hence testing for writability is pointless and even harmful.
+     */
+    if ( boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
+        return;
+
+    rdtscll(tsc);
+    if ( wrmsr_safe(MSR_IA32_TSC, 0) == 0 )
+    {
+        uint64_t tmp, tmp2;
+        rdtscll(tmp2);
+        write_tsc(tsc | (1ULL << 32));
+        rdtscll(tmp);
+        if ( ABS((s64)tmp - (s64)tmp2) < (1LL << 31) )
+            what = "only partially";
+    }
+    else
+    {
+        what = "not";
+    }
+
+    /* Nothing to do if the TSC is fully writable. */
+    if ( !what )
+    {
+        /*
+         * Paranoia - write back original TSC value. However, APs get synced
+         * with BSP as they are brought up, so this doesn't much matter.
+         */
+        write_tsc(tsc);
+        return;
+    }
+
+    printk(XENLOG_WARNING "TSC %s writable\n", what);
+
+    /* time_calibration_tsc_rendezvous() must not be used */
+    setup_clear_cpu_cap(X86_FEATURE_CONSTANT_TSC);
+
+    /* cstate_restore_tsc() must not be used (or do nothing) */
+    if ( !boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
+        cpuidle_disable_deep_cstate();
+
+    /* synchronize_tsc_slave() must do nothing */
+    disable_tsc_sync = 1;
+}
+
 /* Late init function (after all CPUs are booted). */
 int __init init_xen_time(void)
 {
@@ -1398,6 +1461,8 @@
             setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
     }
 
+    tsc_check_writability();
+
     /* If we have constant-rate TSCs then scale factor can be shared. */
     if ( boot_cpu_has(X86_FEATURE_CONSTANT_TSC) )
     {
@@ -1451,7 +1516,7 @@
      * XXX dom0 may rely on RTC interrupt delivery, so only enable
      * hpet_broadcast if FSB mode available or if force_hpet_broadcast.
      */
-    if ( xen_cpuidle && !boot_cpu_has(X86_FEATURE_ARAT) )
+    if ( cpuidle_using_deep_cstate() && !boot_cpu_has(X86_FEATURE_ARAT) )
     {
         hpet_broadcast_setup();
         if ( !hpet_broadcast_is_available() )
diff -r b5165fb66b56 -r 1329d99b4f16 xen/include/asm-x86/setup.h
--- a/xen/include/asm-x86/setup.h       Thu Apr 14 14:57:24 2011 +0100
+++ b/xen/include/asm-x86/setup.h       Fri Apr 15 08:52:08 2011 +0100
@@ -4,7 +4,6 @@
 #include <xen/multiboot.h>
 
 extern bool_t early_boot;
-extern s8 xen_cpuidle;
 extern unsigned long xenheap_initial_phys_start;
 
 void init_done(void);
diff -r b5165fb66b56 -r 1329d99b4f16 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Thu Apr 14 14:57:24 2011 +0100
+++ b/xen/include/asm-x86/time.h        Fri Apr 15 08:52:08 2011 +0100
@@ -24,6 +24,8 @@
 
 typedef u64 cycles_t;
 
+extern bool_t disable_tsc_sync;
+
 static inline cycles_t get_cycles(void)
 {
     cycles_t c;
diff -r b5165fb66b56 -r 1329d99b4f16 xen/include/xen/cpuidle.h
--- a/xen/include/xen/cpuidle.h Thu Apr 14 14:57:24 2011 +0100
+++ b/xen/include/xen/cpuidle.h Fri Apr 15 08:52:08 2011 +0100
@@ -85,7 +85,10 @@
     void (*reflect)         (struct acpi_processor_power *dev);
 };
 
+extern s8 xen_cpuidle;
 extern struct cpuidle_governor *cpuidle_current_governor;
+
+bool_t cpuidle_using_deep_cstate(void);
 void cpuidle_disable_deep_cstate(void);
 
 extern void cpuidle_wakeup_mwait(cpumask_t *mask);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.