x86: use the correct cpuid method to detect MWAIT support for C states
authorAndi Kleen <ak@suse.de>
Wed, 30 Jan 2008 12:33:16 +0000 (13:33 +0100)
committerIngo Molnar <mingo@elte.hu>
Wed, 30 Jan 2008 12:33:16 +0000 (13:33 +0100)
Previously there was a AMD specific quirk to handle the case of
AMD Fam10h MWAIT not supporting any C states. But it turns out
that CPUID already has ways to detectly detect that without
using special quirks.

The new code simply checks if MWAIT supports at least C1 and doesn't
use it if it doesn't. No more vendor specific code.

Note this is does not simply clear MWAIT because MWAIT can be still
useful even without C states.

Credit goes to Ben Serebrin for pointing out the (nearly) obvious.

Cc: "Andreas Herrmann" <andreas.herrmann3@amd.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup_64.c

index cd2fe15ff4b51e0c502a519d45ce87893944b693..06fa159232fd74b9520cb41a706f1d239e653572 100644 (file)
@@ -300,9 +300,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                local_apic_timer_disabled = 1;
 #endif
 
-       if (c->x86 == 0x10 && !force_mwait)
-               clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
-
        /* K6s reports MCEs but don't actually have all the MSRs */
        if (c->x86 < 6)
                clear_bit(X86_FEATURE_MCE, c->x86_capability);
index 69a69c3f43bb4940c6fa9485b0015debb68f432a..9f45a51af968be31679923ea94bf83a9e0c60e88 100644 (file)
@@ -285,9 +285,17 @@ static void mwait_idle(void)
        mwait_idle_with_hints(0, 0);
 }
 
+static int mwait_usable(const struct cpuinfo_x86 *c)
+{
+       if (force_mwait)
+               return 1;
+       /* Any C1 states supported? */
+       return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
+}
+
 void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
-       if (cpu_has(c, X86_FEATURE_MWAIT)) {
+       if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
                printk("monitor/mwait feature present.\n");
                /*
                 * Skip, if setup has overridden idle.
index 4e65ae8a54bf2c3c6d2a6750e1da71f4b36bae0e..dbe0a846ec52a2ec23033c4e480a63f8495eba85 100644 (file)
@@ -280,10 +280,19 @@ static void mwait_idle(void)
        }
 }
 
+
+static int mwait_usable(const struct cpuinfo_x86 *c)
+{
+       if (force_mwait)
+               return 1;
+       /* Any C1 states supported? */
+       return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
+}
+
 void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
        static int printed;
-       if (cpu_has(c, X86_FEATURE_MWAIT)) {
+       if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
                /*
                 * Skip, if setup has overridden idle.
                 * One CPU supports mwait => All CPUs supports mwait
index 71a420c7fee7ae45d4a91451953d1fe952d69fe5..4a3f00b49236aac3f105b13163694dcdc1a0165f 100644 (file)
@@ -761,10 +761,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
        /* MFENCE stops RDTSC speculation */
        set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
 
-       /* Family 10 doesn't support C states in MWAIT so don't use it */
-       if (c->x86 == 0x10 && !force_mwait)
-               clear_cpu_cap(c, X86_FEATURE_MWAIT);
-
        if (amd_apic_timer_broken())
                disable_apic_timer = 1;
 }