LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
@ 2008-02-24 11:07 Mikael Pettersson
2008-02-24 13:57 ` Ingo Molnar
0 siblings, 1 reply; 10+ messages in thread
From: Mikael Pettersson @ 2008-02-24 11:07 UTC (permalink / raw)
To: linux-kernel; +Cc: hpa, mingo, tglx
The kernel for this 486 has CONFIG_M486=y and CONFIG_M586TSC=n,
but the 2.6.25 kernels still try to access the TSC. Here's the
oops from 2.6.25-rc2-git8:
Pid: 0, comm: swapper Not tainted (2.6.25-rc2-git8 #1)
EIP: 0060:[<c0106216>] EFLAGS: 00010002 CPU: 0
EIP is at native_read_tsc+0x6/0x10
EAX: ffff8ce6 EBX: c19f8620 ECX: c19f8620 EDX: 00300100
ESI: 00300100 EDI: 00000001 EBP: c19f7578 ESP: c02a7eec
DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068
Process swapper (pid: 0, ti=c02a6000 task=c028d300 task.ti=c02a6000)
Stack: c01b37e5 00000000 00001000 ffff8ce6 00000000 c19f7578 00000000 c019a2e7
c02e05cc c02e05cc c01da229 00000016 c01da302 00001000 00000001 c029d4e0
c02e05cc 00000050 c01dee35 00000000 c02e05cc c01dfc18 c02e0580 c1834ca0
Call Trace:
[<c01b37e5>] add_timer_randomness+0x115/0x170
[<c019a2e7>] __blk_end_request+0x17/0x50
[<c01da229>] __ide_end_request+0x39/0xe0
[<c01da302>] ide_end_request+0x32/0x50
[<c01dee35>] task_end_request+0x25/0x70
[<c01dfc18>] task_in_intr+0xd8/0xe0
[<c01db4fa>] ide_intr+0x7a/0x1a0
[<c01dfb40>] task_in_intr+0x0/0xe0
[<c01171f2>] run_timer_softirq+0x12/0x150
[<c012ccf0>] handle_IRQ_event+0x30/0x70
[<c012e0b2>] handle_level_irq+0x42/0x90
[<c0104571>] do_IRQ+0x41/0x70
[<c0102e23>] common_interrupt+0x23/0x30
[<c0120000>] arm_timer+0xa0/0x2b0
[<c010195d>] default_idle+0x3d/0x60
[<c0101920>] default_idle+0x0/0x60
[<c01017e0>] cpu_idle+0x20/0x70
[<c02a8a83>] start_kernel+0x1e3/0x260
=======================
Code: 90 90 90 90 90 b8 8e 21 00 00 e9 a6 28 0a 00 8d b6 00 00 00 00 e6 ed c3 90 90 90 90 90 90 90 90 9
EIP: [<c0106216>] native_read_tsc+0x6/0x10 SS:ESP 0068:c02a7eec
Kernel panic - not syncing: Fatal exception in interrupt
This bug is also seen with 2.6.25-rc1.
Kernels up to and including 2.6.24 did not have this bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-24 11:07 [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage Mikael Pettersson
@ 2008-02-24 13:57 ` Ingo Molnar
2008-02-24 15:16 ` Mikael Pettersson
0 siblings, 1 reply; 10+ messages in thread
From: Ingo Molnar @ 2008-02-24 13:57 UTC (permalink / raw)
To: Mikael Pettersson; +Cc: linux-kernel, hpa, mingo, tglx
* Mikael Pettersson <mikpe@it.uu.se> wrote:
> The kernel for this 486 has CONFIG_M486=y and CONFIG_M586TSC=n, but
> the 2.6.25 kernels still try to access the TSC. Here's the oops from
> 2.6.25-rc2-git8:
hm, could you send me the full .config you used?
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-24 13:57 ` Ingo Molnar
@ 2008-02-24 15:16 ` Mikael Pettersson
2008-02-24 15:32 ` Ingo Molnar
2008-02-24 17:27 ` Mikael Pettersson
0 siblings, 2 replies; 10+ messages in thread
From: Mikael Pettersson @ 2008-02-24 15:16 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Mikael Pettersson, linux-kernel, hpa, mingo, tglx
Ingo Molnar writes:
>
> * Mikael Pettersson <mikpe@it.uu.se> wrote:
>
> > The kernel for this 486 has CONFIG_M486=y and CONFIG_M586TSC=n, but
> > the 2.6.25 kernels still try to access the TSC. Here's the oops from
> > 2.6.25-rc2-git8:
>
> hm, could you send me the full .config you used?
I've put it here:
<http://user.it.uu.se/~mikpe/linux/tmp/config-2.6.24-git8>
Meanwhile, I've traced the breakage to 2.6.24-git8.
2.6.24-git8 changed include/asm-x86/tsc.h:get_cycles() to call
rdtscll() even if CONFIG_X86_TSC isn't set. The call is protected
by a cpu_has_tsc test, but starting with 2.6.24-git8 cpu_has_tsc
is non-zero on this machine, which is very very wrong.
Diffing dmesg between git7 and git8 doesn't sched any light since
git8 also removed the printouts of the x86 caps as they were being
initialised and updated. I'm currently adding those printouts back
in the hope of seeing where and when the caps get broken.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-24 15:16 ` Mikael Pettersson
@ 2008-02-24 15:32 ` Ingo Molnar
2008-02-24 17:27 ` Mikael Pettersson
1 sibling, 0 replies; 10+ messages in thread
From: Ingo Molnar @ 2008-02-24 15:32 UTC (permalink / raw)
To: Mikael Pettersson; +Cc: linux-kernel, hpa, mingo, tglx
* Mikael Pettersson <mikpe@it.uu.se> wrote:
> 2.6.24-git8 changed include/asm-x86/tsc.h:get_cycles() to call
> rdtscll() even if CONFIG_X86_TSC isn't set. The call is protected by a
> cpu_has_tsc test, but starting with 2.6.24-git8 cpu_has_tsc is
> non-zero on this machine, which is very very wrong.
does reverting the commit below solve the problem?
Ingo
-------------->
commit 404ee5b14b68d3cba287c2596588b83790c49f7b
Author: Andi Kleen <ak@suse.de>
Date: Wed Jan 30 13:33:20 2008 +0100
x86: convert TSC disabling to generic cpuid disable bitmap
Fix from: Ian Campbell <ijc@hellion.org.uk>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index a96abd4..9b95edc 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -154,7 +154,7 @@ static void __init check_config(void)
* If we configured ourselves for a TSC, we'd better have one!
*/
#ifdef CONFIG_X86_TSC
- if (!cpu_has_tsc && !tsc_disable)
+ if (!cpu_has_tsc)
panic("Kernel compiled for Pentium+, requires TSC feature!");
#endif
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index c66991a..dfc9563 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -446,10 +446,6 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
* we do "generic changes."
*/
- /* TSC disabled? */
- if ( tsc_disable )
- clear_bit(X86_FEATURE_TSC, c->x86_capability);
-
/* If the model name is still unset, do table lookup. */
if ( !c->x86_model_id[0] ) {
char *p;
@@ -650,11 +646,6 @@ void __cpuinit cpu_init(void)
if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
- if (tsc_disable && cpu_has_tsc) {
- printk(KERN_NOTICE "Disabling TSC...\n");
- /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
- clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
- }
load_idt(&idt_descr);
switch_to_new_gdt();
diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c
index 9000d82..e65281b 100644
--- a/arch/x86/kernel/numaq_32.c
+++ b/arch/x86/kernel/numaq_32.c
@@ -82,7 +82,7 @@ static int __init numaq_tsc_disable(void)
{
if (num_online_nodes() > 1) {
printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
- tsc_disable = 1;
+ setup_clear_cpu_cap(X86_FEATURE_TSC);
}
return 0;
}
diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c
index 2a7b95b..43517e3 100644
--- a/arch/x86/kernel/tsc_32.c
+++ b/arch/x86/kernel/tsc_32.c
@@ -24,8 +24,6 @@ static int tsc_enabled;
unsigned int tsc_khz;
EXPORT_SYMBOL_GPL(tsc_khz);
-int tsc_disable;
-
#ifdef CONFIG_X86_TSC
static int __init tsc_setup(char *str)
{
@@ -40,8 +38,7 @@ static int __init tsc_setup(char *str)
*/
static int __init tsc_setup(char *str)
{
- tsc_disable = 1;
-
+ setup_clear_cpu_cap(X86_FEATURE_TSC);
return 1;
}
#endif
@@ -395,7 +392,7 @@ void __init tsc_init(void)
{
int cpu;
- if (!cpu_has_tsc || tsc_disable)
+ if (!cpu_has_tsc)
goto out_no_tsc;
cpu_khz = calculate_cpu_khz();
@@ -439,10 +436,5 @@ void __init tsc_init(void)
return;
out_no_tsc:
- /*
- * Set the tsc_disable flag if there's no TSC support, this
- * makes it a fast flag for the kernel to see whether it
- * should be using the TSC.
- */
- tsc_disable = 1;
+ setup_clear_cpu_cap(X86_FEATURE_TSC);
}
diff --git a/arch/x86/mach-voyager/setup.c b/arch/x86/mach-voyager/setup.c
index 81257a8..5ae5466 100644
--- a/arch/x86/mach-voyager/setup.c
+++ b/arch/x86/mach-voyager/setup.c
@@ -37,7 +37,7 @@ void __init pre_setup_arch_hook(void)
{
/* Voyagers run their CPUs from independent clocks, so disable
* the TSC code because we can't sync them */
- tsc_disable = 1;
+ setup_clear_cpu_cap(X86_FEATURE_TSC);
}
void __init trap_init_hook(void)
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index d083ff5..b3721fd 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -592,7 +592,7 @@ __init void xen_time_init(void)
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
- tsc_disable = 0;
+ setup_force_cpu_cap(X86_FEATURE_TSC);
xen_setup_timer(cpu);
xen_setup_cpu_clockevents();
diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h
index b8f53f8..3fb7dfa 100644
--- a/include/asm-x86/cpufeature.h
+++ b/include/asm-x86/cpufeature.h
@@ -135,6 +135,10 @@
clear_cpu_cap(&boot_cpu_data, bit); \
set_bit(bit, cleared_cpu_caps); \
} while (0)
+#define setup_force_cpu_cap(bit) do { \
+ set_cpu_cap(&boot_cpu_data, bit); \
+ clear_bit(bit, cleared_cpu_caps); \
+} while (0)
#define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU)
#define cpu_has_vme boot_cpu_has(X86_FEATURE_VME)
diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h
index 071e0ce..a6e8d35 100644
--- a/include/asm-x86/tsc.h
+++ b/include/asm-x86/tsc.h
@@ -16,8 +16,6 @@ typedef unsigned long long cycles_t;
extern unsigned int cpu_khz;
extern unsigned int tsc_khz;
-/* flag for disabling the tsc */
-extern int tsc_disable;
extern void disable_TSC(void);
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-24 15:16 ` Mikael Pettersson
2008-02-24 15:32 ` Ingo Molnar
@ 2008-02-24 17:27 ` Mikael Pettersson
2008-02-24 17:52 ` Ingo Molnar
2008-02-25 0:57 ` H. Peter Anvin
1 sibling, 2 replies; 10+ messages in thread
From: Mikael Pettersson @ 2008-02-24 17:27 UTC (permalink / raw)
To: Mikael Pettersson; +Cc: Ingo Molnar, linux-kernel, hpa, mingo, tglx
Mikael Pettersson writes:
> Ingo Molnar writes:
> >
> > * Mikael Pettersson <mikpe@it.uu.se> wrote:
> >
> > > The kernel for this 486 has CONFIG_M486=y and CONFIG_M586TSC=n, but
> > > the 2.6.25 kernels still try to access the TSC. Here's the oops from
> > > 2.6.25-rc2-git8:
> >
> > hm, could you send me the full .config you used?
>
> I've put it here:
> <http://user.it.uu.se/~mikpe/linux/tmp/config-2.6.24-git8>
>
> Meanwhile, I've traced the breakage to 2.6.24-git8.
>
> 2.6.24-git8 changed include/asm-x86/tsc.h:get_cycles() to call
> rdtscll() even if CONFIG_X86_TSC isn't set. The call is protected
> by a cpu_has_tsc test, but starting with 2.6.24-git8 cpu_has_tsc
> is non-zero on this machine, which is very very wrong.
>
> Diffing dmesg between git7 and git8 doesn't sched any light since
> git8 also removed the printouts of the x86 caps as they were being
> initialised and updated. I'm currently adding those printouts back
> in the hope of seeing where and when the caps get broken.
That turned out to be very illuminating:
--- dmesg-2.6.24-git7 2008-02-24 18:01:25.295851000 +0100
+++ dmesg-2.6.24-git8 2008-02-24 18:01:25.530358000 +0100
...
CPU: After generic identify, caps: 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000
CPU: After all inits, caps: 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+CPU: After applying cleared_cpu_caps, caps: 00000013 00000000 00000000 00000000 00000000 00000000 00000000 00000000
Notice how the TSC cap bit goes from Off to On.
(The first two lines are printout loops from -git7 forward-ported
to -git8, the third line is the same printout loop added just after
the xor-with-cleared_cpu_caps[] loop.)
Here's how the breakage occurs:
1. arch/x86/kernel/tsc_32.c:tsc_init() sees !cpu_has_tsc,
so bails and calls setup_clear_cpu_cap(X86_FEATURE_TSC).
2. include/asm-x86/cpufeature.h:setup_clear_cpu_cap(bit) clears
the bit in boot_cpu_data and sets it in cleared_cpu_caps
3. arch/x86/kernel/cpu/common.c:identify_cpu() XORs all caps
in with cleared_cpu_caps
HOWEVER, at this point c->x86_capability correctly has TSC
Off, cleared_cpu_caps has TSC On, so the XOR incorrectly
sets TSC to On in c->x86_capability, with disastrous results.
The real bug is that clearing bits with XOR only works if the
bits are known to be 1 prior to the XOR, and that's not true here.
A simple fix is to convert the XOR to AND-NOT instead. The following
patch does that, and allows my 486 to boot 2.6.25-rc kernels again.
Signed-off-by: Mikael Pettersson <mikpe@it.uu.se>
---
There's a similar XOR loop in arch/x86/kernel/setup_64.c.
I haven't seen it fail yet, but perhaps it should be changed
too, for robustness and symmetry.
--- linux-2.6.25-rc2-git8/arch/x86/kernel/cpu/common.c.~1~ 2008-02-24 17:42:56.000000000 +0100
+++ linux-2.6.25-rc2-git8/arch/x86/kernel/cpu/common.c 2008-02-24 17:44:06.000000000 +0100
@@ -504,7 +504,7 @@ void __cpuinit identify_cpu(struct cpuin
/* Clear all flags overriden by options */
for (i = 0; i < NCAPINTS; i++)
- c->x86_capability[i] ^= cleared_cpu_caps[i];
+ c->x86_capability[i] &= ~cleared_cpu_caps[i];
/* Init Machine Check Exception if available. */
mcheck_init(c);
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-24 17:27 ` Mikael Pettersson
@ 2008-02-24 17:52 ` Ingo Molnar
2008-02-25 0:57 ` H. Peter Anvin
1 sibling, 0 replies; 10+ messages in thread
From: Ingo Molnar @ 2008-02-24 17:52 UTC (permalink / raw)
To: Mikael Pettersson; +Cc: linux-kernel, hpa, mingo, tglx
* Mikael Pettersson <mikpe@it.uu.se> wrote:
>
> That turned out to be very illuminating:
>
> --- dmesg-2.6.24-git7 2008-02-24 18:01:25.295851000 +0100
> +++ dmesg-2.6.24-git8 2008-02-24 18:01:25.530358000 +0100
> ...
> CPU: After generic identify, caps: 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>
> CPU: After all inits, caps: 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> +CPU: After applying cleared_cpu_caps, caps: 00000013 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>
> Notice how the TSC cap bit goes from Off to On.
>
> (The first two lines are printout loops from -git7 forward-ported
> to -git8, the third line is the same printout loop added just after
> the xor-with-cleared_cpu_caps[] loop.)
>
> Here's how the breakage occurs:
> 1. arch/x86/kernel/tsc_32.c:tsc_init() sees !cpu_has_tsc,
> so bails and calls setup_clear_cpu_cap(X86_FEATURE_TSC).
> 2. include/asm-x86/cpufeature.h:setup_clear_cpu_cap(bit) clears
> the bit in boot_cpu_data and sets it in cleared_cpu_caps
> 3. arch/x86/kernel/cpu/common.c:identify_cpu() XORs all caps
> in with cleared_cpu_caps
> HOWEVER, at this point c->x86_capability correctly has TSC
> Off, cleared_cpu_caps has TSC On, so the XOR incorrectly
> sets TSC to On in c->x86_capability, with disastrous results.
>
> The real bug is that clearing bits with XOR only works if the bits are
> known to be 1 prior to the XOR, and that's not true here.
>
> A simple fix is to convert the XOR to AND-NOT instead. The following
> patch does that, and allows my 486 to boot 2.6.25-rc kernels again.
thanks for the fix, i've queued it up. The breakage was introduced via:
commit 7d851c8d3db0f79b92c8b14361779ede8acd2488
Author: Andi Kleen <ak@suse.de>
Date: Wed Jan 30 13:33:20 2008 +0100
x86: add framework to disable CPUID bits on the command line
There are already various options to disable specific cpuid bits
on the command line. They all use their own variable. Add a generic
mask to make this easier in the future.
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-24 17:27 ` Mikael Pettersson
2008-02-24 17:52 ` Ingo Molnar
@ 2008-02-25 0:57 ` H. Peter Anvin
2008-02-25 8:26 ` Ingo Molnar
1 sibling, 1 reply; 10+ messages in thread
From: H. Peter Anvin @ 2008-02-25 0:57 UTC (permalink / raw)
To: Mikael Pettersson; +Cc: Ingo Molnar, linux-kernel, mingo, tglx
Mikael Pettersson wrote:
>
> Here's how the breakage occurs:
> 1. arch/x86/kernel/tsc_32.c:tsc_init() sees !cpu_has_tsc,
> so bails and calls setup_clear_cpu_cap(X86_FEATURE_TSC).
> 2. include/asm-x86/cpufeature.h:setup_clear_cpu_cap(bit) clears
> the bit in boot_cpu_data and sets it in cleared_cpu_caps
> 3. arch/x86/kernel/cpu/common.c:identify_cpu() XORs all caps
> in with cleared_cpu_caps
> HOWEVER, at this point c->x86_capability correctly has TSC
> Off, cleared_cpu_caps has TSC On, so the XOR incorrectly
> sets TSC to On in c->x86_capability, with disastrous results.
>
> The real bug is that clearing bits with XOR only works if the
> bits are known to be 1 prior to the XOR, and that's not true here.
>
> A simple fix is to convert the XOR to AND-NOT instead. The following
> patch does that, and allows my 486 to boot 2.6.25-rc kernels again.
>
Please fix it in both places. Using XOR instead of AND-NOT is a bug,
plain and simple.
-hpa
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-25 0:57 ` H. Peter Anvin
@ 2008-02-25 8:26 ` Ingo Molnar
2008-02-25 9:17 ` Mikael Pettersson
0 siblings, 1 reply; 10+ messages in thread
From: Ingo Molnar @ 2008-02-25 8:26 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: Mikael Pettersson, linux-kernel, mingo, tglx
* H. Peter Anvin <hpa@zytor.com> wrote:
> Please fix it in both places. Using XOR instead of AND-NOT is a bug,
> plain and simple.
yes, i already fixed that when i added Mikael's patch and it's all
queued up.
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-25 8:26 ` Ingo Molnar
@ 2008-02-25 9:17 ` Mikael Pettersson
2008-02-25 9:19 ` Ingo Molnar
0 siblings, 1 reply; 10+ messages in thread
From: Mikael Pettersson @ 2008-02-25 9:17 UTC (permalink / raw)
To: Ingo Molnar; +Cc: H. Peter Anvin, Mikael Pettersson, linux-kernel, mingo, tglx
Ingo Molnar writes:
>
> * H. Peter Anvin <hpa@zytor.com> wrote:
>
> > Please fix it in both places. Using XOR instead of AND-NOT is a bug,
> > plain and simple.
>
> yes, i already fixed that when i added Mikael's patch and it's all
> queued up.
Ok. For reference and for LKML viewers, this is what
the final patch should be:
diff -rupN linux-2.6.25-rc3/arch/x86/kernel/cpu/common.c linux-2.6.25-rc3.x86-apply-cleared_cpu_caps-correctly/arch/x86/kernel/cpu/common.c
--- linux-2.6.25-rc3/arch/x86/kernel/cpu/common.c 2008-02-25 09:29:03.000000000 +0100
+++ linux-2.6.25-rc3.x86-apply-cleared_cpu_caps-correctly/arch/x86/kernel/cpu/common.c 2008-02-25 09:44:11.000000000 +0100
@@ -504,7 +504,7 @@ void __cpuinit identify_cpu(struct cpuin
/* Clear all flags overriden by options */
for (i = 0; i < NCAPINTS; i++)
- c->x86_capability[i] ^= cleared_cpu_caps[i];
+ c->x86_capability[i] &= ~cleared_cpu_caps[i];
/* Init Machine Check Exception if available. */
mcheck_init(c);
diff -rupN linux-2.6.25-rc3/arch/x86/kernel/setup_64.c linux-2.6.25-rc3.x86-apply-cleared_cpu_caps-correctly/arch/x86/kernel/setup_64.c
--- linux-2.6.25-rc3/arch/x86/kernel/setup_64.c 2008-02-25 09:29:03.000000000 +0100
+++ linux-2.6.25-rc3.x86-apply-cleared_cpu_caps-correctly/arch/x86/kernel/setup_64.c 2008-02-25 09:44:57.000000000 +0100
@@ -1021,7 +1021,7 @@ void __cpuinit identify_cpu(struct cpuin
/* Clear all flags overriden by options */
for (i = 0; i < NCAPINTS; i++)
- c->x86_capability[i] ^= cleared_cpu_caps[i];
+ c->x86_capability[i] &= ~cleared_cpu_caps[i];
#ifdef CONFIG_X86_MCE
mcheck_init(c);
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage
2008-02-25 9:17 ` Mikael Pettersson
@ 2008-02-25 9:19 ` Ingo Molnar
0 siblings, 0 replies; 10+ messages in thread
From: Ingo Molnar @ 2008-02-25 9:19 UTC (permalink / raw)
To: Mikael Pettersson; +Cc: H. Peter Anvin, linux-kernel, mingo, tglx
* Mikael Pettersson <mikpe@it.uu.se> wrote:
> > yes, i already fixed that when i added Mikael's patch and it's all
> > queued up.
>
> Ok. For reference and for LKML viewers, this is what the final patch
> should be:
below is the full commit - will send it to Linus later today.
Ingo
--------------->
Subject: x86: fix boot failure on 486 due to TSC breakage
From: Mikael Pettersson <mikpe@it.uu.se>
Date: Sun, 24 Feb 2008 18:27:03 +0100
> Diffing dmesg between git7 and git8 doesn't sched any light since
> git8 also removed the printouts of the x86 caps as they were being
> initialised and updated. I'm currently adding those printouts back
> in the hope of seeing where and when the caps get broken.
That turned out to be very illuminating:
--- dmesg-2.6.24-git7 2008-02-24 18:01:25.295851000 +0100
+++ dmesg-2.6.24-git8 2008-02-24 18:01:25.530358000 +0100
...
CPU: After generic identify, caps: 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000
CPU: After all inits, caps: 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+CPU: After applying cleared_cpu_caps, caps: 00000013 00000000 00000000 00000000 00000000 00000000 00000000 00000000
Notice how the TSC cap bit goes from Off to On.
(The first two lines are printout loops from -git7 forward-ported
to -git8, the third line is the same printout loop added just after
the xor-with-cleared_cpu_caps[] loop.)
Here's how the breakage occurs:
1. arch/x86/kernel/tsc_32.c:tsc_init() sees !cpu_has_tsc,
so bails and calls setup_clear_cpu_cap(X86_FEATURE_TSC).
2. include/asm-x86/cpufeature.h:setup_clear_cpu_cap(bit) clears
the bit in boot_cpu_data and sets it in cleared_cpu_caps
3. arch/x86/kernel/cpu/common.c:identify_cpu() XORs all caps
in with cleared_cpu_caps
HOWEVER, at this point c->x86_capability correctly has TSC
Off, cleared_cpu_caps has TSC On, so the XOR incorrectly
sets TSC to On in c->x86_capability, with disastrous results.
The real bug is that clearing bits with XOR only works if the
bits are known to be 1 prior to the XOR, and that's not true here.
A simple fix is to convert the XOR to AND-NOT instead. The following
patch does that, and allows my 486 to boot 2.6.25-rc kernels again.
[ mingo@elte.hu: fixed a similar bug in setup_64.c as well. ]
The breakage was introduced via commit 7d851c8d3db0.
Signed-off-by: Mikael Pettersson <mikpe@it.uu.se>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
arch/x86/kernel/cpu/common.c | 2 +-
arch/x86/kernel/setup_64.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
Index: linux-x86.q/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/cpu/common.c
+++ linux-x86.q/arch/x86/kernel/cpu/common.c
@@ -504,7 +504,7 @@ void __cpuinit identify_cpu(struct cpuin
/* Clear all flags overriden by options */
for (i = 0; i < NCAPINTS; i++)
- c->x86_capability[i] ^= cleared_cpu_caps[i];
+ c->x86_capability[i] &= ~cleared_cpu_caps[i];
/* Init Machine Check Exception if available. */
mcheck_init(c);
Index: linux-x86.q/arch/x86/kernel/setup_64.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/setup_64.c
+++ linux-x86.q/arch/x86/kernel/setup_64.c
@@ -1021,7 +1021,7 @@ void __cpuinit identify_cpu(struct cpuin
/* Clear all flags overriden by options */
for (i = 0; i < NCAPINTS; i++)
- c->x86_capability[i] ^= cleared_cpu_caps[i];
+ c->x86_capability[i] &= ~cleared_cpu_caps[i];
#ifdef CONFIG_X86_MCE
mcheck_init(c);
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2008-02-25 9:20 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-24 11:07 [BUG] 2.6.25-rc2-git8 fails to boot on 486 due to TSC breakage Mikael Pettersson
2008-02-24 13:57 ` Ingo Molnar
2008-02-24 15:16 ` Mikael Pettersson
2008-02-24 15:32 ` Ingo Molnar
2008-02-24 17:27 ` Mikael Pettersson
2008-02-24 17:52 ` Ingo Molnar
2008-02-25 0:57 ` H. Peter Anvin
2008-02-25 8:26 ` Ingo Molnar
2008-02-25 9:17 ` Mikael Pettersson
2008-02-25 9:19 ` Ingo Molnar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).