x86/time: correctly honor late clearing of TSC related feature flags
authorJan Beulich <jbeulich@suse.com>
Tue, 7 Feb 2017 13:32:40 +0000 (14:32 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 7 Feb 2017 13:32:40 +0000 (14:32 +0100)
As such clearing of flags may have an impact on the selected rendezvous
function, defer the establishing of a rendezvous function other than
the initial default one (std) until after all APs have been brought up.

But don't allow such feature flags to be cleared during CPU hotplug:
Platform and local system times may have diverged significantly by
then, potentially causing noticeably (even if only temporary) strange
behavior. As we're anyway expecting only sufficiently similar CPUs to
appear during hotplug, this shouldn't be introducing new limitations.

Reported-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
xen/arch/x86/time.c

index e17da1b6672e2cfddc8989225efe7a9371a598c2..d3b0c696e34799764a54c3e54de0ee4e7166e3c1 100644 (file)
@@ -1638,9 +1638,18 @@ static int __init verify_tsc_reliability(void)
 
             printk("Switched to Platform timer %s TSC\n",
                    freq_string(plt_src.frequency));
+            return 0;
         }
     }
 
+    /*
+     * While with constant-rate TSCs the scale factor can be shared, when TSCs
+     * are not marked as 'reliable', re-sync during rendezvous.
+     */
+    if ( boot_cpu_has(X86_FEATURE_CONSTANT_TSC) &&
+         !boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
+        time_calibration_rendezvous_fn = time_calibration_tsc_rendezvous;
+
     return 0;
 }
 __initcall(verify_tsc_reliability);
@@ -1650,14 +1659,6 @@ int __init init_xen_time(void)
 {
     tsc_check_writability();
 
-    /* If we have constant-rate TSCs then scale factor can be shared. */
-    if ( boot_cpu_has(X86_FEATURE_CONSTANT_TSC) )
-    {
-        /* If TSCs are not marked as 'reliable', re-sync during rendezvous. */
-        if ( !boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
-            time_calibration_rendezvous_fn = time_calibration_tsc_rendezvous;
-    }
-
     open_softirq(TIME_CALIBRATE_SOFTIRQ, local_time_calibration);
 
     /* NB. get_cmos_time() can take over one second to execute. */