From 62be90012c507b2bf1047eb2eaa1e9151f7172fe Mon Sep 17 00:00:00 2001 From: Satyam Sharma Date: Thu, 16 Aug 2007 06:09:25 +0530 Subject: [PATCH] i386: Fix a couple busy loops in mach_wakecpu.h:wait_for_init_deassert() Use cpu_relax() in the busy loops, as atomic_read() doesn't automatically imply volatility for i386 and x86_64. x86_64 doesn't have this issue because it open-codes the while loop in smpboot.c:smp_callin() itself that already uses cpu_relax(). For i386, however, smpboot.c:smp_callin() calls wait_for_init_deassert() which is buggy for mach-default and mach-es7000 cases. [ I test-built a kernel -- smp_callin() itself got inlined in its only callsite, smpboot.c:start_secondary() -- and the relevant piece of code disassembles to the following: 0xc1019704 : mov 0xc144c4c8,%eax 0xc1019709 : test %eax,%eax 0xc101970b : je 0xc1019709 init_deasserted (at 0xc144c4c8) gets fetched into %eax only once and then we loop over the test of the stale value in the register only, so these look like real bugs to me. With the fix below, this becomes: 0xc1019706 : pause 0xc1019708 : cmpl $0x0,0xc144c4c8 0xc101970f : je 0xc1019706 which looks nice and healthy. ] Thanks to Heiko Carstens for noticing this. Signed-off-by: Satyam Sharma Cc: Heiko Carstens Signed-off-by: Linus Torvalds --- include/asm-i386/mach-default/mach_wakecpu.h | 3 ++- include/asm-i386/mach-es7000/mach_wakecpu.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/asm-i386/mach-default/mach_wakecpu.h b/include/asm-i386/mach-default/mach_wakecpu.h index 673b85c9b273..3ebb17893aa5 100644 --- a/include/asm-i386/mach-default/mach_wakecpu.h +++ b/include/asm-i386/mach-default/mach_wakecpu.h @@ -15,7 +15,8 @@ static inline void wait_for_init_deassert(atomic_t *deassert) { - while (!atomic_read(deassert)); + while (!atomic_read(deassert)) + cpu_relax(); return; } diff --git a/include/asm-i386/mach-es7000/mach_wakecpu.h b/include/asm-i386/mach-es7000/mach_wakecpu.h index efc903b73486..84ff58314501 100644 --- a/include/asm-i386/mach-es7000/mach_wakecpu.h +++ b/include/asm-i386/mach-es7000/mach_wakecpu.h @@ -31,7 +31,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) static inline void wait_for_init_deassert(atomic_t *deassert) { #ifdef WAKE_SECONDARY_VIA_INIT - while (!atomic_read(deassert)); + while (!atomic_read(deassert)) + cpu_relax(); #endif return; }