aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-26 18:21:33 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-26 18:43:41 -0400
commitf7f847b01571e86044dc77e03d92f43699652f8d (patch)
treefe5b32756facabc6aea9d354d6894efd809a47f9
parentdf912ea4ae7233d1504fbd861ee127bd7ee5781d (diff)
Revert "x86-64: Disable local APIC timer use on AMD systems with C1E"
This reverts commit e66485d747505e9d960b864fc6c37f8b2afafaf0, since Rafael Wysocki noticed that the change only works for his in -mm, not in mainline (and that both "noapictimer" _and_ "apicmaintimer" are broken on his hardware, but that's apparently not a regression, just a symptom of the same issue that causes the automatic apic timer disable to not work). It turns out that it really doesn't work correctly on x86-64, since x86-64 doesn't use the generic clock events for timers yet. Thanks to Rafal for testing, and here's the ugly details on x86-64 as per Thomas: "I just looked into the code and the logic vs. noapictimer on SMP is completely broken. On i386 the noapictimer option not only disables the local APIC timer, it also registers the CPUs for broadcasting via IPI on SMP systems. The x86-64 code uses the broadcast only when the local apic timer is active, i.e. "noapictimer" is not on the command line. This defeats the whole purpose of "noapictimer". It should be there to make boxen work, where the local APIC timer actually has a hardware problem, e.g. the nx6325. The current implementation of x86_64 only fixes the ACPI c-states related problem where the APIC timer stops in C3(2), nothing else. On nx6325 and other AMD X2 equipped systems which have the C1E enabled we run into the following: PIT keeps jiffies (and the system) running, but the local APIC timer interrupts can get out of sync due to this C1E effect. I don't think this is a critical problem, but it is wrong nevertheless. I think it's safe to revert the C1E patch and postpone the fix to the clock events conversion." On further reflection, Thomas noted: "It's even worse than I thought on the first check: "noapictimer" on the command line of an SMP box prevents _ONLY_ the boot CPU apic timer from being used. But the secondary CPU is still unconditionally setting up the APIC timer and uses the non calibrated variable calibration_result, which is of course 0, to setup the APIC timer. Wreckage guaranteed." so we'll just have to wait for the x86 merge to hopefully fix this up for x86-64. Tested-and-requested-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86_64/kernel/setup.c34
-rw-r--r--include/asm-x86_64/apic.h1
2 files changed, 0 insertions, 35 deletions
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 32054bf5ba40..af838f6b0b7f 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -546,37 +546,6 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
546#endif 546#endif
547} 547}
548 548
549#define ENABLE_C1E_MASK 0x18000000
550#define CPUID_PROCESSOR_SIGNATURE 1
551#define CPUID_XFAM 0x0ff00000
552#define CPUID_XFAM_K8 0x00000000
553#define CPUID_XFAM_10H 0x00100000
554#define CPUID_XFAM_11H 0x00200000
555#define CPUID_XMOD 0x000f0000
556#define CPUID_XMOD_REV_F 0x00040000
557
558/* AMD systems with C1E don't have a working lAPIC timer. Check for that. */
559static __cpuinit int amd_apic_timer_broken(void)
560{
561 u32 lo, hi;
562 u32 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
563 switch (eax & CPUID_XFAM) {
564 case CPUID_XFAM_K8:
565 if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F)
566 break;
567 case CPUID_XFAM_10H:
568 case CPUID_XFAM_11H:
569 rdmsr(MSR_K8_ENABLE_C1E, lo, hi);
570 if (lo & ENABLE_C1E_MASK)
571 return 1;
572 break;
573 default:
574 /* err on the side of caution */
575 return 1;
576 }
577 return 0;
578}
579
580static void __cpuinit init_amd(struct cpuinfo_x86 *c) 549static void __cpuinit init_amd(struct cpuinfo_x86 *c)
581{ 550{
582 unsigned level; 551 unsigned level;
@@ -648,9 +617,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
648 /* Family 10 doesn't support C states in MWAIT so don't use it */ 617 /* Family 10 doesn't support C states in MWAIT so don't use it */
649 if (c->x86 == 0x10 && !force_mwait) 618 if (c->x86 == 0x10 && !force_mwait)
650 clear_bit(X86_FEATURE_MWAIT, &c->x86_capability); 619 clear_bit(X86_FEATURE_MWAIT, &c->x86_capability);
651
652 if (amd_apic_timer_broken())
653 disable_apic_timer = 1;
654} 620}
655 621
656static void __cpuinit detect_ht(struct cpuinfo_x86 *c) 622static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index e4580203dde2..85125ef3c414 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -20,7 +20,6 @@ extern int apic_verbosity;
20extern int apic_runs_main_timer; 20extern int apic_runs_main_timer;
21extern int ioapic_force; 21extern int ioapic_force;
22extern int apic_mapped; 22extern int apic_mapped;
23extern int disable_apic_timer;
24 23
25/* 24/*
26 * Define the default level of output to be very little 25 * Define the default level of output to be very little