diff options
author | Andi Kleen <ak@suse.de> | 2007-08-10 16:31:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-08-11 18:58:13 -0400 |
commit | d3f7eae182b04997be19343a23f7009170f4f7a5 (patch) | |
tree | 162fc610811c762b322eedaae909847ab4465da1 | |
parent | d2d0251f6faa2cf341500a44310bbaa815a8a972 (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.c | 10 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/amd.c | 7 | ||||
-rw-r--r-- | include/asm-i386/apic.h | 2 | ||||
-rw-r--r-- | include/asm-i386/cpufeature.h | 2 |
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 */ |
63 | static int local_apic_timer_verify_ok; | 63 | static 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 |
65 | static int local_apic_timer_disabled; | 65 | or using CPU MSR check */ |
66 | int local_apic_timer_disabled; | ||
66 | /* Local APIC timer works in C2 */ | 67 | /* Local APIC timer works in C2 */ |
67 | int local_apic_timer_c2_ok; | 68 | int local_apic_timer_c2_ok; |
68 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); | 69 | EXPORT_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 @@ | |||
22 | extern void vide(void); | 23 | extern 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 | ||
56 | int force_mwait __cpuinitdata; | 59 | int 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); | |||
116 | extern int timer_over_8254; | 116 | extern int timer_over_8254; |
117 | extern int local_apic_timer_c2_ok; | 117 | extern int local_apic_timer_c2_ok; |
118 | 118 | ||
119 | extern int local_apic_timer_disabled; | ||
120 | |||
119 | #else /* !CONFIG_X86_LOCAL_APIC */ | 121 | #else /* !CONFIG_X86_LOCAL_APIC */ |
120 | static inline void lapic_shutdown(void) { } | 122 | static 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 | ||