diff mbox

[v2,2/6] x86/time: correctly honor late clearing of TSC related feature flags

Message ID 57A20720020000780010238D@prv-mh.provo.novell.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Beulich Aug. 3, 2016, 1 p.m. UTC
As such clearing of flags may have an impact on the selected rendezvous
function, handle such in a central place.

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 noticably (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>
Tested-by: Dario Faggioli <dario.faggioli@citrix.com>
Tested-by: Joao Martins <joao.m.martins@oracle.com>
x86/time: correctly honor late clearing of TSC related feature flags

As such clearing of flags may have an impact on the selected rendezvous
function, handle such in a central place.

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 noticably (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>
Tested-by: Dario Faggioli <dario.faggioli@citrix.com>
Tested-by: Joao Martins <joao.m.martins@oracle.com>

--- a/xen/arch/x86/cpu/mwait-idle.c
+++ b/xen/arch/x86/cpu/mwait-idle.c
@@ -1162,8 +1162,8 @@ static int mwait_idle_cpu_init(struct no
 		}
 
 		if (state > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC) &&
-		    !pm_idle_save)
-			setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+		    !pm_idle_save && system_state < SYS_STATE_active)
+			clear_tsc_cap(X86_FEATURE_TSC_RELIABLE);
 
 		cx = dev->states + dev->count;
 		cx->type = state;
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -1353,6 +1353,24 @@ static void time_calibration(void *unuse
                      &r, 1);
 }
 
+void __init clear_tsc_cap(unsigned int feature)
+{
+    void (*rendezvous_fn)(void *) = time_calibration_std_rendezvous;
+
+    if ( feature )
+        setup_clear_cpu_cap(feature);
+
+    /* 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) )
+            rendezvous_fn = time_calibration_tsc_rendezvous;
+    }
+
+    time_calibration_rendezvous_fn = rendezvous_fn;
+}
+
 static struct {
     s_time_t local_stime, master_stime;
 } ap_bringup_ref;
@@ -1478,7 +1496,7 @@ static int __init verify_tsc_reliability
         {
             printk("%s: TSC warp detected, disabling TSC_RELIABLE\n",
                    __func__);
-            setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+            clear_tsc_cap(X86_FEATURE_TSC_RELIABLE);
         }
     }
 
@@ -1491,13 +1509,7 @@ 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;
-    }
+    clear_tsc_cap(0);
 
     open_softirq(TIME_CALIBRATE_SOFTIRQ, local_time_calibration);
 
--- a/xen/include/asm-x86/time.h
+++ b/xen/include/asm-x86/time.h
@@ -70,6 +70,7 @@ void tsc_get_info(struct domain *d, uint
 void force_update_vcpu_system_time(struct vcpu *v);
 
 int host_tsc_is_safe(void);
+void clear_tsc_cap(unsigned int feature);
 void cpuid_time_leaf(uint32_t sub_idx, uint32_t *eax, uint32_t *ebx,
                      uint32_t *ecx, uint32_t *edx);

Comments

Jan Beulich Aug. 17, 2016, 1:41 p.m. UTC | #1
Ping?

>>> On 03.08.16 at 15:00, <JBeulich@suse.com> wrote:
> As such clearing of flags may have an impact on the selected rendezvous
> function, handle such in a central place.
> 
> 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 noticably (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>
> Tested-by: Dario Faggioli <dario.faggioli@citrix.com>
> Tested-by: Joao Martins <joao.m.martins@oracle.com>
> 
> --- a/xen/arch/x86/cpu/mwait-idle.c
> +++ b/xen/arch/x86/cpu/mwait-idle.c
> @@ -1162,8 +1162,8 @@ static int mwait_idle_cpu_init(struct no
>  		}
>  
>  		if (state > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC) &&
> -		    !pm_idle_save)
> -			setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
> +		    !pm_idle_save && system_state < SYS_STATE_active)
> +			clear_tsc_cap(X86_FEATURE_TSC_RELIABLE);
>  
>  		cx = dev->states + dev->count;
>  		cx->type = state;
> --- a/xen/arch/x86/time.c
> +++ b/xen/arch/x86/time.c
> @@ -1353,6 +1353,24 @@ static void time_calibration(void *unuse
>                       &r, 1);
>  }
>  
> +void __init clear_tsc_cap(unsigned int feature)
> +{
> +    void (*rendezvous_fn)(void *) = time_calibration_std_rendezvous;
> +
> +    if ( feature )
> +        setup_clear_cpu_cap(feature);
> +
> +    /* 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) )
> +            rendezvous_fn = time_calibration_tsc_rendezvous;
> +    }
> +
> +    time_calibration_rendezvous_fn = rendezvous_fn;
> +}
> +
>  static struct {
>      s_time_t local_stime, master_stime;
>  } ap_bringup_ref;
> @@ -1478,7 +1496,7 @@ static int __init verify_tsc_reliability
>          {
>              printk("%s: TSC warp detected, disabling TSC_RELIABLE\n",
>                     __func__);
> -            setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
> +            clear_tsc_cap(X86_FEATURE_TSC_RELIABLE);
>          }
>      }
>  
> @@ -1491,13 +1509,7 @@ 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;
> -    }
> +    clear_tsc_cap(0);
>  
>      open_softirq(TIME_CALIBRATE_SOFTIRQ, local_time_calibration);
>  
> --- a/xen/include/asm-x86/time.h
> +++ b/xen/include/asm-x86/time.h
> @@ -70,6 +70,7 @@ void tsc_get_info(struct domain *d, uint
>  void force_update_vcpu_system_time(struct vcpu *v);
>  
>  int host_tsc_is_safe(void);
> +void clear_tsc_cap(unsigned int feature);
>  void cpuid_time_leaf(uint32_t sub_idx, uint32_t *eax, uint32_t *ebx,
>                       uint32_t *ecx, uint32_t *edx);
>
diff mbox

Patch

--- a/xen/arch/x86/cpu/mwait-idle.c
+++ b/xen/arch/x86/cpu/mwait-idle.c
@@ -1162,8 +1162,8 @@  static int mwait_idle_cpu_init(struct no
 		}
 
 		if (state > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC) &&
-		    !pm_idle_save)
-			setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+		    !pm_idle_save && system_state < SYS_STATE_active)
+			clear_tsc_cap(X86_FEATURE_TSC_RELIABLE);
 
 		cx = dev->states + dev->count;
 		cx->type = state;
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -1353,6 +1353,24 @@  static void time_calibration(void *unuse
                      &r, 1);
 }
 
+void __init clear_tsc_cap(unsigned int feature)
+{
+    void (*rendezvous_fn)(void *) = time_calibration_std_rendezvous;
+
+    if ( feature )
+        setup_clear_cpu_cap(feature);
+
+    /* 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) )
+            rendezvous_fn = time_calibration_tsc_rendezvous;
+    }
+
+    time_calibration_rendezvous_fn = rendezvous_fn;
+}
+
 static struct {
     s_time_t local_stime, master_stime;
 } ap_bringup_ref;
@@ -1478,7 +1496,7 @@  static int __init verify_tsc_reliability
         {
             printk("%s: TSC warp detected, disabling TSC_RELIABLE\n",
                    __func__);
-            setup_clear_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+            clear_tsc_cap(X86_FEATURE_TSC_RELIABLE);
         }
     }
 
@@ -1491,13 +1509,7 @@  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;
-    }
+    clear_tsc_cap(0);
 
     open_softirq(TIME_CALIBRATE_SOFTIRQ, local_time_calibration);
 
--- a/xen/include/asm-x86/time.h
+++ b/xen/include/asm-x86/time.h
@@ -70,6 +70,7 @@  void tsc_get_info(struct domain *d, uint
 void force_update_vcpu_system_time(struct vcpu *v);
 
 int host_tsc_is_safe(void);
+void clear_tsc_cap(unsigned int feature);
 void cpuid_time_leaf(uint32_t sub_idx, uint32_t *eax, uint32_t *ebx,
                      uint32_t *ecx, uint32_t *edx);