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

Paul Walmsley paul at pwsan.com
Tue Jul 30 07:32:06 EDT 2013


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 at pwsan.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Russell King <rmk+kernel at arm.linux.org.uk>
Cc: Nicolas Pitre <nicolas.pitre at linaro.org>
Cc: Tony Lindgren <tony at 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(-)

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;							\
 	})
 
-- 
1.8.3.2




More information about the linux-arm-kernel mailing list