Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 Feb 2017 23:03:51 +0000 (15:03 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 Feb 2017 23:03:51 +0000 (15:03 -0800)
Pull x86 fpu updates from Ingo Molnar:
 "The main changes relate to fixes between (lack of) CPUID and FPU
  detection that should only affect old or weird CPUs, by Andy
  Lutomirski"

* 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/fpu: Fix the "Giving up, no FPU found" test
  x86/fpu: Fix CPUID-less FPU detection
  x86/fpu: Fix "x86/fpu: Legacy x87 FPU detected" message
  x86/cpu: Re-apply forced caps every time CPU caps are re-read
  x86/cpu: Factor out application of forced CPU caps
  x86/cpu: Add X86_FEATURE_CPUID
  x86/fpu/xstate: Move XSAVES state init to a function

1  2 
arch/x86/include/asm/cpufeatures.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/fpu/xstate.c

  #define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */
  #define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
  #define X86_FEATURE_NONSTOP_TSC       ( 3*32+24) /* TSC does not stop in C states */
/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
#define X86_FEATURE_CPUID     ( 3*32+25) /* CPU has CPUID instruction itself */
  #define X86_FEATURE_EXTD_APICID       ( 3*32+26) /* has extended APICID (8 bits) */
  #define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
  #define X86_FEATURE_APERFMPERF        ( 3*32+28) /* APERFMPERF */
   *
   * Reuse free bits when adding new feature flags!
   */
 -
 +#define X86_FEATURE_RING3MWAIT        ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */
  #define X86_FEATURE_CPB               ( 7*32+ 2) /* AMD Core Performance Boost */
  #define X86_FEATURE_EPB               ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
  #define X86_FEATURE_CAT_L3    ( 7*32+ 4) /* Cache Allocation Technology L3 */
  #define X86_FEATURE_AVX512VBMI  (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
  #define X86_FEATURE_PKU               (16*32+ 3) /* Protection Keys for Userspace */
  #define X86_FEATURE_OSPKE     (16*32+ 4) /* OS Protection Keys Enable */
 +#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
  #define X86_FEATURE_RDPID     (16*32+ 22) /* RDPID instruction */
  
  /* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
  #define X86_BUG_SWAPGS_FENCE  X86_BUG(11) /* SWAPGS without input dep on GS */
  #define X86_BUG_MONITOR               X86_BUG(12) /* IPI required to wake up remote CPU */
  #define X86_BUG_AMD_E400      X86_BUG(13) /* CPU is among the affected by Erratum 400 */
 -
  #endif /* _ASM_X86_CPUFEATURES_H */
@@@ -35,7 -35,6 +35,7 @@@
  #include <asm/desc.h>
  #include <asm/fpu/internal.h>
  #include <asm/mtrr.h>
 +#include <asm/hwcap2.h>
  #include <linux/numa.h>
  #include <asm/asm.h>
  #include <asm/bugs.h>
@@@ -52,8 -51,6 +52,8 @@@
  
  #include "cpu.h"
  
 +u32 elf_hwcap2 __read_mostly;
 +
  /* all of these masks are initialized in setup_cpu_local_masks() */
  cpumask_var_t cpu_initialized_mask;
  cpumask_var_t cpu_callout_mask;
@@@ -86,7 -83,6 +86,7 @@@ static void default_init(struct cpuinfo
                        strcpy(c->x86_model_id, "386");
        }
  #endif
 +      clear_sched_clock_stable();
  }
  
  static const struct cpu_dev default_cpu = {
@@@ -659,6 -655,16 +659,16 @@@ void cpu_detect(struct cpuinfo_x86 *c
        }
  }
  
+ static void apply_forced_caps(struct cpuinfo_x86 *c)
+ {
+       int i;
+       for (i = 0; i < NCAPINTS; i++) {
+               c->x86_capability[i] &= ~cpu_caps_cleared[i];
+               c->x86_capability[i] |= cpu_caps_set[i];
+       }
+ }
  void get_cpu_cap(struct cpuinfo_x86 *c)
  {
        u32 eax, ebx, ecx, edx;
                c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
  
        init_scattered_cpuid_features(c);
+       /*
+        * Clear/Set all flags overridden by options, after probe.
+        * This needs to happen each time we re-probe, which may happen
+        * several times during CPU initialization.
+        */
+       apply_forced_caps(c);
  }
  
  static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
@@@ -805,14 -818,12 +822,12 @@@ static void __init early_identify_cpu(s
        memset(&c->x86_capability, 0, sizeof c->x86_capability);
        c->extended_cpuid_level = 0;
  
-       if (!have_cpuid_p())
-               identify_cpu_without_cpuid(c);
        /* cyrix could have cpuid enabled via c_identify()*/
        if (have_cpuid_p()) {
                cpu_detect(c);
                get_cpu_vendor(c);
                get_cpu_cap(c);
+               setup_force_cpu_cap(X86_FEATURE_CPUID);
  
                if (this_cpu->c_early_init)
                        this_cpu->c_early_init(c);
  
                if (this_cpu->c_bsp_init)
                        this_cpu->c_bsp_init(c);
+       } else {
+               identify_cpu_without_cpuid(c);
+               setup_clear_cpu_cap(X86_FEATURE_CPUID);
        }
  
        setup_force_cpu_cap(X86_FEATURE_ALWAYS);
@@@ -1019,7 -1033,6 +1037,7 @@@ static void identify_cpu(struct cpuinfo
        c->x86_model_id[0] = '\0';  /* Unset */
        c->x86_max_cores = 1;
        c->x86_coreid_bits = 0;
 +      c->cu_id = 0xff;
  #ifdef CONFIG_X86_64
        c->x86_clflush_size = 64;
        c->x86_phys_bits = 36;
                this_cpu->c_identify(c);
  
        /* Clear/Set all flags overridden by options, after probe */
-       for (i = 0; i < NCAPINTS; i++) {
-               c->x86_capability[i] &= ~cpu_caps_cleared[i];
-               c->x86_capability[i] |= cpu_caps_set[i];
-       }
+       apply_forced_caps(c);
  
  #ifdef CONFIG_X86_64
        c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
         */
        if (this_cpu->c_init)
                this_cpu->c_init(c);
 +      else
 +              clear_sched_clock_stable();
  
        /* Disable the PN if appropriate */
        squash_the_stupid_serial_number(c);
         * Clear/Set all flags overridden by options, need do it
         * before following smp all cpus cap AND.
         */
-       for (i = 0; i < NCAPINTS; i++) {
-               c->x86_capability[i] &= ~cpu_caps_cleared[i];
-               c->x86_capability[i] |= cpu_caps_set[i];
-       }
+       apply_forced_caps(c);
  
        /*
         * On SMP, boot_cpu_data holds the common feature set between
@@@ -78,7 -78,6 +78,7 @@@ void fpu__xstate_clear_all_cpu_caps(voi
        setup_clear_cpu_cap(X86_FEATURE_PKU);
        setup_clear_cpu_cap(X86_FEATURE_AVX512_4VNNIW);
        setup_clear_cpu_cap(X86_FEATURE_AVX512_4FMAPS);
 +      setup_clear_cpu_cap(X86_FEATURE_AVX512_VPOPCNTDQ);
  }
  
  /*
@@@ -706,8 -705,14 +706,14 @@@ void __init fpu__init_system_xstate(voi
        WARN_ON_FPU(!on_boot_cpu);
        on_boot_cpu = 0;
  
+       if (!boot_cpu_has(X86_FEATURE_FPU)) {
+               pr_info("x86/fpu: No FPU detected\n");
+               return;
+       }
        if (!boot_cpu_has(X86_FEATURE_XSAVE)) {
-               pr_info("x86/fpu: Legacy x87 FPU detected.\n");
+               pr_info("x86/fpu: x87 FPU will use %s\n",
+                       boot_cpu_has(X86_FEATURE_FXSR) ? "FXSAVE" : "FSAVE");
                return;
        }