* [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 related [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