Commit 0c07ee38 authored by Andi Kleen's avatar Andi Kleen Committed by Ingo Molnar

x86: use the correct cpuid method to detect MWAIT support for C states

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: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 30d432df
...@@ -300,9 +300,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) ...@@ -300,9 +300,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
local_apic_timer_disabled = 1; local_apic_timer_disabled = 1;
#endif #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 */ /* K6s reports MCEs but don't actually have all the MSRs */
if (c->x86 < 6) if (c->x86 < 6)
clear_bit(X86_FEATURE_MCE, c->x86_capability); clear_bit(X86_FEATURE_MCE, c->x86_capability);
......
...@@ -285,9 +285,17 @@ static void mwait_idle(void) ...@@ -285,9 +285,17 @@ static void mwait_idle(void)
mwait_idle_with_hints(0, 0); 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) 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"); printk("monitor/mwait feature present.\n");
/* /*
* Skip, if setup has overridden idle. * Skip, if setup has overridden idle.
......
...@@ -280,10 +280,19 @@ static void mwait_idle(void) ...@@ -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) void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
{ {
static int printed; 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. * Skip, if setup has overridden idle.
* One CPU supports mwait => All CPUs supports mwait * One CPU supports mwait => All CPUs supports mwait
......
...@@ -761,10 +761,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) ...@@ -761,10 +761,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
/* MFENCE stops RDTSC speculation */ /* MFENCE stops RDTSC speculation */
set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); 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()) if (amd_apic_timer_broken())
disable_apic_timer = 1; disable_apic_timer = 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment