Revert "Merge remote-tracking branch 'linux-2.6.32.y/master' into develop"
[firefly-linux-kernel-4.4.55.git] / arch / x86 / kernel / process.c
index 847ab41603155ad493df143b24e6c9055f0f10e8..5fd5b07bf3a5774cd996e312d9fe55533a37b984 100644 (file)
@@ -91,18 +91,6 @@ void flush_thread(void)
 {
        struct task_struct *tsk = current;
 
-#ifdef CONFIG_X86_64
-       if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
-               clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
-               if (test_tsk_thread_flag(tsk, TIF_IA32)) {
-                       clear_tsk_thread_flag(tsk, TIF_IA32);
-               } else {
-                       set_tsk_thread_flag(tsk, TIF_IA32);
-                       current_thread_info()->status |= TS_COMPAT;
-               }
-       }
-#endif
-
        clear_tsk_thread_flag(tsk, TIF_DEBUG);
 
        tsk->thread.debugreg0 = 0;
@@ -451,21 +439,39 @@ static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
 }
 
 /*
- * Check for AMD CPUs, which have potentially C1E support
+ * Check for AMD CPUs, where APIC timer interrupt does not wake up CPU from C1e.
+ * For more information see
+ * - Erratum #400 for NPT family 0xf and family 0x10 CPUs
+ * - Erratum #365 for family 0x11 (not affected because C1e not in use)
  */
 static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c)
 {
+       u64 val;
        if (c->x86_vendor != X86_VENDOR_AMD)
-               return 0;
-
-       if (c->x86 < 0x0F)
-               return 0;
+               goto no_c1e_idle;
 
        /* Family 0x0f models < rev F do not have C1E */
-       if (c->x86 == 0x0f && c->x86_model < 0x40)
-               return 0;
+       if (c->x86 == 0x0F && c->x86_model >= 0x40)
+               return 1;
 
-       return 1;
+       if (c->x86 == 0x10) {
+               /*
+                * check OSVW bit for CPUs that are not affected
+                * by erratum #400
+                */
+               if (cpu_has(c, X86_FEATURE_OSVW)) {
+                       rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val);
+                       if (val >= 2) {
+                               rdmsrl(MSR_AMD64_OSVW_STATUS, val);
+                               if (!(val & BIT(1)))
+                                       goto no_c1e_idle;
+                       }
+               }
+               return 1;
+       }
+
+no_c1e_idle:
+       return 0;
 }
 
 static cpumask_var_t c1e_mask;
@@ -555,10 +561,8 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 void __init init_c1e_mask(void)
 {
        /* If we're using c1e_idle, we need to allocate c1e_mask. */
-       if (pm_idle == c1e_idle) {
-               alloc_cpumask_var(&c1e_mask, GFP_KERNEL);
-               cpumask_clear(c1e_mask);
-       }
+       if (pm_idle == c1e_idle)
+               zalloc_cpumask_var(&c1e_mask, GFP_KERNEL);
 }
 
 static int __init idle_setup(char *str)