diff mbox

[v2] ARM: v6: prevent gcc 4.5 from reordering extended CP15 reads above is_smp() test

Message ID alpine.DEB.2.02.1307301125420.4505@utopia.booyaka.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paul Walmsley July 30, 2013, 11:32 a.m. UTC
Commit 621a0147d5c921f4cc33636ccd0602ad5d7cbfbc ("ARM: 7757/1: mm:
don't flush icache in switch_mm with hardware broadcasting") breaks
the boot on OMAP2430SDP with omap2plus_defconfig.  Tracked to an
undefined instruction abort from the CP15 read in
cache_ops_need_broadcast().  It turns out that gcc 4.5 reorders the
extended CP15 read above the is_smp() test.  This breaks ARM1136 r0
cores, since they don't support several CP15 registers that later ARM
cores do.  ARM1136JF-S TRM section 3.2.1 "Register allocation" has the
details.

So mark the extended CP15 read as clobbering memory, which prevents
the compiler from reordering it before the is_smp() test.  Russell
states that the code generated from this approach is preferable to
marking the inline asm as volatile.  Remove the existing condition
code clobber as it's obsolete, per Nico's post:

    http://www.spinics.net/lists/arm-kernel/msg261208.html

This patch is a collaboration with Will Deacon and Russell King.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
---

Intended for v3.11-rc.

Basic test logs available here:

http://www.pwsan.com/omap/testlogs/bisect_2430sdp_hang_v3.11-rc/20130730045715/

N.B., several boards have problems on v3.11-rc that are unrelated to this 
patch.

 arch/arm/include/asm/cputype.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Comments

Will Deacon July 30, 2013, 3:04 p.m. UTC | #1
On Tue, Jul 30, 2013 at 12:32:06PM +0100, Paul Walmsley wrote:
> 
> Commit 621a0147d5c921f4cc33636ccd0602ad5d7cbfbc ("ARM: 7757/1: mm:
> don't flush icache in switch_mm with hardware broadcasting") breaks
> the boot on OMAP2430SDP with omap2plus_defconfig.  Tracked to an
> undefined instruction abort from the CP15 read in
> cache_ops_need_broadcast().  It turns out that gcc 4.5 reorders the
> extended CP15 read above the is_smp() test.  This breaks ARM1136 r0
> cores, since they don't support several CP15 registers that later ARM
> cores do.  ARM1136JF-S TRM section 3.2.1 "Register allocation" has the
> details.
> 
> So mark the extended CP15 read as clobbering memory, which prevents
> the compiler from reordering it before the is_smp() test.  Russell
> states that the code generated from this approach is preferable to
> marking the inline asm as volatile.  Remove the existing condition
> code clobber as it's obsolete, per Nico's post:
> 
>     http://www.spinics.net/lists/arm-kernel/msg261208.html
> 
> This patch is a collaboration with Will Deacon and Russell King.
> 
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> Cc: Tony Lindgren <tony@atomide.com>
> ---

Acked-by: Will Deacon <will.deacon@arm.com>

Will
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 8c25dc4..9672e97 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -89,13 +89,18 @@  extern unsigned int processor_id;
 		__val;							\
 	})
 
+/*
+ * The memory clobber prevents gcc 4.5 from reordering the mrc before
+ * any is_smp() tests, which can cause undefined instruction aborts on
+ * ARM1136 r0 due to the missing extended CP15 registers.
+ */
 #define read_cpuid_ext(ext_reg)						\
 	({								\
 		unsigned int __val;					\
 		asm("mrc	p15, 0, %0, c0, " ext_reg		\
 		    : "=r" (__val)					\
 		    :							\
-		    : "cc");						\
+		    : "memory");					\
 		__val;							\
 	})