]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - arch/x86/kernel/fpu/init.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / arch / x86 / kernel / fpu / init.c
index 93982aebb39896224b28177c3212f37ca110dc70..19bdd1bf81607cfe06d57bf4d4e0b42b9088d691 100644 (file)
@@ -9,18 +9,6 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 
-/*
- * Initialize the TS bit in CR0 according to the style of context-switches
- * we are using:
- */
-static void fpu__init_cpu_ctx_switch(void)
-{
-       if (!boot_cpu_has(X86_FEATURE_EAGER_FPU))
-               stts();
-       else
-               clts();
-}
-
 /*
  * Initialize the registers found in all CPUs, CR0 and CR4:
  */
@@ -58,16 +46,9 @@ void fpu__init_cpu(void)
 {
        fpu__init_cpu_generic();
        fpu__init_cpu_xstate();
-       fpu__init_cpu_ctx_switch();
 }
 
-/*
- * The earliest FPU detection code.
- *
- * Set the X86_FEATURE_FPU CPU-capability bit based on
- * trying to execute an actual sequence of FPU instructions:
- */
-static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
+static bool fpu__probe_without_cpuid(void)
 {
        unsigned long cr0;
        u16 fsw, fcw;
@@ -78,18 +59,25 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
        cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
        write_cr0(cr0);
 
-       if (!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
-               asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
-                            : "+m" (fsw), "+m" (fcw));
+       asm volatile("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw));
+
+       pr_info("x86/fpu: Probing for FPU: FSW=0x%04hx FCW=0x%04hx\n", fsw, fcw);
 
-               if (fsw == 0 && (fcw & 0x103f) == 0x003f)
-                       set_cpu_cap(c, X86_FEATURE_FPU);
+       return fsw == 0 && (fcw & 0x103f) == 0x003f;
+}
+
+static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
+{
+       if (!boot_cpu_has(X86_FEATURE_CPUID) &&
+           !test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
+               if (fpu__probe_without_cpuid())
+                       setup_force_cpu_cap(X86_FEATURE_FPU);
                else
-                       clear_cpu_cap(c, X86_FEATURE_FPU);
+                       setup_clear_cpu_cap(X86_FEATURE_FPU);
        }
 
 #ifndef CONFIG_MATH_EMULATION
-       if (!boot_cpu_has(X86_FEATURE_FPU)) {
+       if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_FPU)) {
                pr_emerg("x86/fpu: Giving up, no FPU found and no math emulation present\n");
                for (;;)
                        asm volatile("hlt");
@@ -232,42 +220,6 @@ static void __init fpu__init_system_xstate_size_legacy(void)
        fpu_user_xstate_size = fpu_kernel_xstate_size;
 }
 
-/*
- * FPU context switching strategies:
- *
- * Against popular belief, we don't do lazy FPU saves, due to the
- * task migration complications it brings on SMP - we only do
- * lazy FPU restores.
- *
- * 'lazy' is the traditional strategy, which is based on setting
- * CR0::TS to 1 during context-switch (instead of doing a full
- * restore of the FPU state), which causes the first FPU instruction
- * after the context switch (whenever it is executed) to fault - at
- * which point we lazily restore the FPU state into FPU registers.
- *
- * Tasks are of course under no obligation to execute FPU instructions,
- * so it can easily happen that another context-switch occurs without
- * a single FPU instruction being executed. If we eventually switch
- * back to the original task (that still owns the FPU) then we have
- * not only saved the restores along the way, but we also have the
- * FPU ready to be used for the original task.
- *
- * 'lazy' is deprecated because it's almost never a performance win
- * and it's much more complicated than 'eager'.
- *
- * 'eager' switching is by default on all CPUs, there we switch the FPU
- * state during every context switch, regardless of whether the task
- * has used FPU instructions in that time slice or not. This is done
- * because modern FPU context saving instructions are able to optimize
- * state saving and restoration in hardware: they can detect both
- * unused and untouched FPU state and optimize accordingly.
- *
- * [ Note that even in 'lazy' mode we might optimize context switches
- *   to use 'eager' restores, if we detect that a task is using the FPU
- *   frequently. See the fpu->counter logic in fpu/internal.h for that. ]
- */
-static enum { ENABLE, DISABLE } eagerfpu = ENABLE;
-
 /*
  * Find supported xfeatures based on cpu features and command-line input.
  * This must be called after fpu__init_parse_early_param() is called and
@@ -275,40 +227,10 @@ static enum { ENABLE, DISABLE } eagerfpu = ENABLE;
  */
 u64 __init fpu__get_supported_xfeatures_mask(void)
 {
-       /* Support all xfeatures known to us */
-       if (eagerfpu != DISABLE)
-               return XCNTXT_MASK;
-
-       /* Warning of xfeatures being disabled for no eagerfpu mode */
-       if (xfeatures_mask & XFEATURE_MASK_EAGER) {
-               pr_err("x86/fpu: eagerfpu switching disabled, disabling the following xstate features: 0x%llx.\n",
-                       xfeatures_mask & XFEATURE_MASK_EAGER);
-       }
-
-       /* Return a mask that masks out all features requiring eagerfpu mode */
-       return ~XFEATURE_MASK_EAGER;
+       return XCNTXT_MASK;
 }
 
-/*
- * Disable features dependent on eagerfpu.
- */
-static void __init fpu__clear_eager_fpu_features(void)
-{
-       setup_clear_cpu_cap(X86_FEATURE_MPX);
-}
-
-/*
- * Pick the FPU context switching strategy:
- *
- * When eagerfpu is AUTO or ENABLE, we ensure it is ENABLE if either of
- * the following is true:
- *
- * (1) the cpu has xsaveopt, as it has the optimization and doing eager
- *     FPU switching has a relatively low cost compared to a plain xsave;
- * (2) the cpu has xsave features (e.g. MPX) that depend on eager FPU
- *     switching. Should the kernel boot with noxsaveopt, we support MPX
- *     with eager FPU switching at a higher cost.
- */
+/* Legacy code to initialize eager fpu mode. */
 static void __init fpu__init_system_ctx_switch(void)
 {
        static bool on_boot_cpu __initdata = 1;
@@ -317,18 +239,6 @@ static void __init fpu__init_system_ctx_switch(void)
        on_boot_cpu = 0;
 
        WARN_ON_FPU(current->thread.fpu.fpstate_active);
-       current_thread_info()->status = 0;
-
-       if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE)
-               eagerfpu = ENABLE;
-
-       if (xfeatures_mask & XFEATURE_MASK_EAGER)
-               eagerfpu = ENABLE;
-
-       if (eagerfpu == ENABLE)
-               setup_force_cpu_cap(X86_FEATURE_EAGER_FPU);
-
-       printk(KERN_INFO "x86/fpu: Using '%s' FPU context switches.\n", eagerfpu == ENABLE ? "eager" : "lazy");
 }
 
 /*
@@ -337,11 +247,6 @@ static void __init fpu__init_system_ctx_switch(void)
  */
 static void __init fpu__init_parse_early_param(void)
 {
-       if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) {
-               eagerfpu = DISABLE;
-               fpu__clear_eager_fpu_features();
-       }
-
        if (cmdline_find_option_bool(boot_command_line, "no387"))
                setup_clear_cpu_cap(X86_FEATURE_FPU);
 
@@ -376,14 +281,6 @@ void __init fpu__init_system(struct cpuinfo_x86 *c)
         */
        fpu__init_cpu();
 
-       /*
-        * But don't leave CR0::TS set yet, as some of the FPU setup
-        * methods depend on being able to execute FPU instructions
-        * that will fault on a set TS, such as the FXSAVE in
-        * fpu__init_system_mxcsr().
-        */
-       clts();
-
        fpu__init_system_generic();
        fpu__init_system_xstate_size_legacy();
        fpu__init_system_xstate();