mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
i386: Use global flag to disable broken local apic timer on AMD CPUs.
The Averatec 2370 and some other Turion laptop BIOS seems to program the ENABLE_C1E MSR inconsistently between cores. This confuses the lapic use heuristics because when C1E is enabled anywhere it seems to affect the complete chip. Use a global flag instead of a per cpu flag to handle this. If any CPU has C1E enabled disabled lapic use. Thanks to Cal Peake for debugging. Cc: tglx@linutronix.de Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
d2d0251f6f
commit
d3f7eae182
@ -61,8 +61,9 @@ static int enable_local_apic __initdata = 0;
|
|||||||
|
|
||||||
/* Local APIC timer verification ok */
|
/* Local APIC timer verification ok */
|
||||||
static int local_apic_timer_verify_ok;
|
static int local_apic_timer_verify_ok;
|
||||||
/* Disable local APIC timer from the kernel commandline or via dmi quirk */
|
/* Disable local APIC timer from the kernel commandline or via dmi quirk
|
||||||
static int local_apic_timer_disabled;
|
or using CPU MSR check */
|
||||||
|
int local_apic_timer_disabled;
|
||||||
/* Local APIC timer works in C2 */
|
/* Local APIC timer works in C2 */
|
||||||
int local_apic_timer_c2_ok;
|
int local_apic_timer_c2_ok;
|
||||||
EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
|
EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
|
||||||
@ -370,12 +371,9 @@ void __init setup_boot_APIC_clock(void)
|
|||||||
long delta, deltapm;
|
long delta, deltapm;
|
||||||
int pm_referenced = 0;
|
int pm_referenced = 0;
|
||||||
|
|
||||||
if (boot_cpu_has(X86_FEATURE_LAPIC_TIMER_BROKEN))
|
|
||||||
local_apic_timer_disabled = 1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The local apic timer can be disabled via the kernel
|
* The local apic timer can be disabled via the kernel
|
||||||
* commandline or from the test above. Register the lapic
|
* commandline or from the CPU detection code. Register the lapic
|
||||||
* timer as a dummy clock event source on SMP systems, so the
|
* timer as a dummy clock event source on SMP systems, so the
|
||||||
* broadcast mechanism is used. On UP systems simply ignore it.
|
* broadcast mechanism is used. On UP systems simply ignore it.
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
#include <asm/apic.h>
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
@ -22,6 +23,7 @@
|
|||||||
extern void vide(void);
|
extern void vide(void);
|
||||||
__asm__(".align 4\nvide: ret");
|
__asm__(".align 4\nvide: ret");
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
#define ENABLE_C1E_MASK 0x18000000
|
#define ENABLE_C1E_MASK 0x18000000
|
||||||
#define CPUID_PROCESSOR_SIGNATURE 1
|
#define CPUID_PROCESSOR_SIGNATURE 1
|
||||||
#define CPUID_XFAM 0x0ff00000
|
#define CPUID_XFAM 0x0ff00000
|
||||||
@ -52,6 +54,7 @@ static __cpuinit int amd_apic_timer_broken(void)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int force_mwait __cpuinitdata;
|
int force_mwait __cpuinitdata;
|
||||||
|
|
||||||
@ -282,8 +285,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
|||||||
num_cache_leaves = 3;
|
num_cache_leaves = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
if (amd_apic_timer_broken())
|
if (amd_apic_timer_broken())
|
||||||
set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability);
|
local_apic_timer_disabled = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (c->x86 == 0x10 && !force_mwait)
|
if (c->x86 == 0x10 && !force_mwait)
|
||||||
clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
|
clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
|
||||||
|
@ -116,6 +116,8 @@ extern void enable_NMI_through_LVT0 (void * dummy);
|
|||||||
extern int timer_over_8254;
|
extern int timer_over_8254;
|
||||||
extern int local_apic_timer_c2_ok;
|
extern int local_apic_timer_c2_ok;
|
||||||
|
|
||||||
|
extern int local_apic_timer_disabled;
|
||||||
|
|
||||||
#else /* !CONFIG_X86_LOCAL_APIC */
|
#else /* !CONFIG_X86_LOCAL_APIC */
|
||||||
static inline void lapic_shutdown(void) { }
|
static inline void lapic_shutdown(void) { }
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@
|
|||||||
#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
|
#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
|
||||||
#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
|
#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
|
||||||
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
|
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
|
||||||
#define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14) /* lapic timer broken in C1 */
|
/* 14 free */
|
||||||
#define X86_FEATURE_SYNC_RDTSC (3*32+15) /* RDTSC synchronizes the CPU */
|
#define X86_FEATURE_SYNC_RDTSC (3*32+15) /* RDTSC synchronizes the CPU */
|
||||||
#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */
|
#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user