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>

authored by Andi Kleen and committed by Linus Torvalds d3f7eae1 d2d0251f

+13 -8
+4 -6
arch/i386/kernel/apic.c
··· 61 62 /* Local APIC timer verification ok */ 63 static int local_apic_timer_verify_ok; 64 - /* Disable local APIC timer from the kernel commandline or via dmi quirk */ 65 - static int local_apic_timer_disabled; 66 /* Local APIC timer works in C2 */ 67 int local_apic_timer_c2_ok; 68 EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); ··· 371 long delta, deltapm; 372 int pm_referenced = 0; 373 374 - if (boot_cpu_has(X86_FEATURE_LAPIC_TIMER_BROKEN)) 375 - local_apic_timer_disabled = 1; 376 - 377 /* 378 * The local apic timer can be disabled via the kernel 379 - * commandline or from the test above. Register the lapic 380 * timer as a dummy clock event source on SMP systems, so the 381 * broadcast mechanism is used. On UP systems simply ignore it. 382 */
··· 61 62 /* Local APIC timer verification ok */ 63 static int local_apic_timer_verify_ok; 64 + /* Disable local APIC timer from the kernel commandline or via dmi quirk 65 + or using CPU MSR check */ 66 + int local_apic_timer_disabled; 67 /* Local APIC timer works in C2 */ 68 int local_apic_timer_c2_ok; 69 EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); ··· 370 long delta, deltapm; 371 int pm_referenced = 0; 372 373 /* 374 * The local apic timer can be disabled via the kernel 375 + * commandline or from the CPU detection code. Register the lapic 376 * timer as a dummy clock event source on SMP systems, so the 377 * broadcast mechanism is used. On UP systems simply ignore it. 378 */
+6 -1
arch/i386/kernel/cpu/amd.c
··· 3 #include <linux/mm.h> 4 #include <asm/io.h> 5 #include <asm/processor.h> 6 7 #include "cpu.h" 8 ··· 23 extern void vide(void); 24 __asm__(".align 4\nvide: ret"); 25 26 #define ENABLE_C1E_MASK 0x18000000 27 #define CPUID_PROCESSOR_SIGNATURE 1 28 #define CPUID_XFAM 0x0ff00000 ··· 54 } 55 return 0; 56 } 57 58 int force_mwait __cpuinitdata; 59 ··· 285 num_cache_leaves = 3; 286 } 287 288 if (amd_apic_timer_broken()) 289 - set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability); 290 291 if (c->x86 == 0x10 && !force_mwait) 292 clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
··· 3 #include <linux/mm.h> 4 #include <asm/io.h> 5 #include <asm/processor.h> 6 + #include <asm/apic.h> 7 8 #include "cpu.h" 9 ··· 22 extern void vide(void); 23 __asm__(".align 4\nvide: ret"); 24 25 + #ifdef CONFIG_X86_LOCAL_APIC 26 #define ENABLE_C1E_MASK 0x18000000 27 #define CPUID_PROCESSOR_SIGNATURE 1 28 #define CPUID_XFAM 0x0ff00000 ··· 52 } 53 return 0; 54 } 55 + #endif 56 57 int force_mwait __cpuinitdata; 58 ··· 282 num_cache_leaves = 3; 283 } 284 285 + #ifdef CONFIG_X86_LOCAL_APIC 286 if (amd_apic_timer_broken()) 287 + local_apic_timer_disabled = 1; 288 + #endif 289 290 if (c->x86 == 0x10 && !force_mwait) 291 clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
+2
include/asm-i386/apic.h
··· 116 extern int timer_over_8254; 117 extern int local_apic_timer_c2_ok; 118 119 #else /* !CONFIG_X86_LOCAL_APIC */ 120 static inline void lapic_shutdown(void) { } 121
··· 116 extern int timer_over_8254; 117 extern int local_apic_timer_c2_ok; 118 119 + extern int local_apic_timer_disabled; 120 + 121 #else /* !CONFIG_X86_LOCAL_APIC */ 122 static inline void lapic_shutdown(void) { } 123
+1 -1
include/asm-i386/cpufeature.h
··· 79 #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ 80 #define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ 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 */ 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 */ 85
··· 79 #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ 80 #define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ 81 #define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ 82 + /* 14 free */ 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 */ 85