| From d3f7eae182b04997be19343a23f7009170f4f7a5 Mon Sep 17 00:00:00 2001 |
| From: Andi Kleen <ak@suse.de> |
| Date: Fri, 10 Aug 2007 22:31:07 +0200 |
| Subject: i386: Use global flag to disable broken local apic timer on AMD CPUs. |
| |
| From: Andi Kleen <ak@suse.de> |
| |
| commit d3f7eae182b04997be19343a23f7009170f4f7a5 upstream |
| |
| 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 |
| Cc: Chuck Ebbert <cebbert@redhat.com> |
| Signed-off-by: Andi Kleen <ak@suse.de> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/i386/kernel/apic.c | 10 ++++------ |
| arch/i386/kernel/cpu/amd.c | 7 ++++++- |
| include/asm-i386/apic.h | 2 ++ |
| include/asm-i386/cpufeature.h | 2 +- |
| 4 files changed, 13 insertions(+), 8 deletions(-) |
| |
| --- a/arch/i386/kernel/apic.c |
| +++ b/arch/i386/kernel/apic.c |
| @@ -61,8 +61,9 @@ static int enable_local_apic __initdata |
| |
| /* Local APIC timer verification ok */ |
| static int local_apic_timer_verify_ok; |
| -/* Disable local APIC timer from the kernel commandline or via dmi quirk */ |
| -static int local_apic_timer_disabled; |
| +/* Disable local APIC timer from the kernel commandline or via dmi quirk |
| + or using CPU MSR check */ |
| +int local_apic_timer_disabled; |
| /* Local APIC timer works in C2 */ |
| int local_apic_timer_c2_ok; |
| EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); |
| @@ -367,12 +368,9 @@ void __init setup_boot_APIC_clock(void) |
| long delta, deltapm; |
| 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 |
| - * 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 |
| * broadcast mechanism is used. On UP systems simply ignore it. |
| */ |
| --- a/arch/i386/kernel/cpu/amd.c |
| +++ b/arch/i386/kernel/cpu/amd.c |
| @@ -3,6 +3,7 @@ |
| #include <linux/mm.h> |
| #include <asm/io.h> |
| #include <asm/processor.h> |
| +#include <asm/apic.h> |
| |
| #include "cpu.h" |
| |
| @@ -22,6 +23,7 @@ |
| extern void vide(void); |
| __asm__(".align 4\nvide: ret"); |
| |
| +#ifdef CONFIG_X86_LOCAL_APIC |
| #define ENABLE_C1E_MASK 0x18000000 |
| #define CPUID_PROCESSOR_SIGNATURE 1 |
| #define CPUID_XFAM 0x0ff00000 |
| @@ -52,6 +54,7 @@ static __cpuinit int amd_apic_timer_brok |
| } |
| return 0; |
| } |
| +#endif |
| |
| int force_mwait __cpuinitdata; |
| |
| @@ -275,8 +278,10 @@ static void __cpuinit init_amd(struct cp |
| if (cpuid_eax(0x80000000) >= 0x80000006) |
| num_cache_leaves = 3; |
| |
| +#ifdef CONFIG_X86_LOCAL_APIC |
| 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) |
| clear_bit(X86_FEATURE_MWAIT, c->x86_capability); |
| --- a/include/asm-i386/apic.h |
| +++ b/include/asm-i386/apic.h |
| @@ -116,6 +116,8 @@ extern void enable_NMI_through_LVT0 (voi |
| extern int timer_over_8254; |
| extern int local_apic_timer_c2_ok; |
| |
| +extern int local_apic_timer_disabled; |
| + |
| #else /* !CONFIG_X86_LOCAL_APIC */ |
| static inline void lapic_shutdown(void) { } |
| |
| --- a/include/asm-i386/cpufeature.h |
| +++ b/include/asm-i386/cpufeature.h |
| @@ -79,7 +79,7 @@ |
| #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_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 */ |
| |
| /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ |