aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2007-08-10 16:31:07 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-11 18:58:13 -0400
commitd3f7eae182b04997be19343a23f7009170f4f7a5 (patch)
tree162fc610811c762b322eedaae909847ab4465da1
parentd2d0251f6faa2cf341500a44310bbaa815a8a972 (diff)
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>
-rw-r--r--arch/i386/kernel/apic.c10
-rw-r--r--arch/i386/kernel/cpu/amd.c7
-rw-r--r--include/asm-i386/apic.h2
-rw-r--r--include/asm-i386/cpufeature.h2
4 files changed, 13 insertions, 8 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index bfc6cb7df7e7..f9fff29e01a9 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -61,8 +61,9 @@ static int enable_local_apic __initdata = 0;
61 61
62/* Local APIC timer verification ok */ 62/* Local APIC timer verification ok */
63static int local_apic_timer_verify_ok; 63static int local_apic_timer_verify_ok;
64/* Disable local APIC timer from the kernel commandline or via dmi quirk */ 64/* Disable local APIC timer from the kernel commandline or via dmi quirk
65static int local_apic_timer_disabled; 65 or using CPU MSR check */
66int local_apic_timer_disabled;
66/* Local APIC timer works in C2 */ 67/* Local APIC timer works in C2 */
67int local_apic_timer_c2_ok; 68int local_apic_timer_c2_ok;
68EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); 69EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
@@ -370,12 +371,9 @@ void __init setup_boot_APIC_clock(void)
370 long delta, deltapm; 371 long delta, deltapm;
371 int pm_referenced = 0; 372 int pm_referenced = 0;
372 373
373 if (boot_cpu_has(X86_FEATURE_LAPIC_TIMER_BROKEN))
374 local_apic_timer_disabled = 1;
375
376 /* 374 /*
377 * The local apic timer can be disabled via the kernel 375 * The local apic timer can be disabled via the kernel
378 * commandline or from the test above. Register the lapic 376 * commandline or from the CPU detection code. Register the lapic
379 * timer as a dummy clock event source on SMP systems, so the 377 * timer as a dummy clock event source on SMP systems, so the
380 * broadcast mechanism is used. On UP systems simply ignore it. 378 * broadcast mechanism is used. On UP systems simply ignore it.
381 */ 379 */
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index c7ba455d5ac7..dcf6bbb1c7c0 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -3,6 +3,7 @@
3#include <linux/mm.h> 3#include <linux/mm.h>
4#include <asm/io.h> 4#include <asm/io.h>
5#include <asm/processor.h> 5#include <asm/processor.h>
6#include <asm/apic.h>
6 7
7#include "cpu.h" 8#include "cpu.h"
8 9
@@ -22,6 +23,7 @@
22extern void vide(void); 23extern void vide(void);
23__asm__(".align 4\nvide: ret"); 24__asm__(".align 4\nvide: ret");
24 25
26#ifdef CONFIG_X86_LOCAL_APIC
25#define ENABLE_C1E_MASK 0x18000000 27#define ENABLE_C1E_MASK 0x18000000
26#define CPUID_PROCESSOR_SIGNATURE 1 28#define CPUID_PROCESSOR_SIGNATURE 1
27#define CPUID_XFAM 0x0ff00000 29#define CPUID_XFAM 0x0ff00000
@@ -52,6 +54,7 @@ static __cpuinit int amd_apic_timer_broken(void)
52 } 54 }
53 return 0; 55 return 0;
54} 56}
57#endif
55 58
56int force_mwait __cpuinitdata; 59int force_mwait __cpuinitdata;
57 60
@@ -282,8 +285,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
282 num_cache_leaves = 3; 285 num_cache_leaves = 3;
283 } 286 }
284 287
288#ifdef CONFIG_X86_LOCAL_APIC
285 if (amd_apic_timer_broken()) 289 if (amd_apic_timer_broken())
286 set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability); 290 local_apic_timer_disabled = 1;
291#endif
287 292
288 if (c->x86 == 0x10 && !force_mwait) 293 if (c->x86 == 0x10 && !force_mwait)
289 clear_bit(X86_FEATURE_MWAIT, c->x86_capability); 294 clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 1e8f6f252dd3..4091b33dcb10 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -116,6 +116,8 @@ extern void enable_NMI_through_LVT0 (void * dummy);
116extern int timer_over_8254; 116extern int timer_over_8254;
117extern int local_apic_timer_c2_ok; 117extern int local_apic_timer_c2_ok;
118 118
119extern int local_apic_timer_disabled;
120
119#else /* !CONFIG_X86_LOCAL_APIC */ 121#else /* !CONFIG_X86_LOCAL_APIC */
120static inline void lapic_shutdown(void) { } 122static inline void lapic_shutdown(void) { }
121 123
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index c961c03cf1e2..7b3aa28ebc6e 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -79,7 +79,7 @@
79#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ 79#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
80#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ 80#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
81#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ 81#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
82#define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14) /* lapic timer broken in C1 */ 82/* 14 free */
83#define X86_FEATURE_SYNC_RDTSC (3*32+15) /* RDTSC synchronizes the CPU */ 83#define X86_FEATURE_SYNC_RDTSC (3*32+15) /* RDTSC synchronizes the CPU */
84#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */ 84#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */
85 85