diff mbox series

[v2,1/3] arm: asm/system.h: mrc and mcr need .arm if __thumb2__ is not set

Message ID 047259e7e911d039a54a5674ebaa6a2c75008959.1737709089.git.jerome.forissier@linaro.org
State New
Headers show
Series Static initcalls | expand

Commit Message

Jerome Forissier Jan. 24, 2025, 9:10 a.m. UTC
The mcr and msr instructions are available in Thumb mode only if
Thumb2 is supported. Therefore, if __thumb2__ is not set, make
sure we switch to ARM mode by inserting a .arm directive in the
inline assembly.

Fixes LTO link errors with kirkwood platforms, triggered by a later
commit:

 tools/buildman/buildman -o /tmp/build -eP sheevaplug
 [...]
 {standard input}:24085: Error: selected processor does not support `mrc p15,0,r3,c1,c0,0' in Thumb mode

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 arch/arm/include/asm/system.h             | 22 +++++++++++++++++-----
 arch/arm/lib/cache.c                      |  5 +++--
 arch/arm/mach-kirkwood/include/mach/cpu.h |  9 +++++----
 3 files changed, 25 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index dbf9ab43e28..6784a4f25fc 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -394,11 +394,21 @@  void switch_to_hypervisor_ret(void);
 #define wfi()
 #endif
 
+#if !defined(__thumb2__)
+/*
+ * We will need to switch to ARM mode (.arm) for some instructions such as
+ * mrc p15 etc.
+ */
+#define asm_arm_or_thumb2(insn) asm volatile(".arm\n\t" insn)
+#else
+#define asm_arm_or_thumb2(insn) asm volatile(insn)
+#endif
+
 static inline unsigned long read_mpidr(void)
 {
 	unsigned long val;
 
-	asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (val));
+	asm_arm_or_thumb2("mrc p15, 0, %0, c0, c0, 5" : "=r" (val));
 
 	return val;
 }
@@ -427,11 +437,13 @@  static inline unsigned int get_cr(void)
 	unsigned int val;
 
 	if (is_hyp())
-		asm volatile("mrc p15, 4, %0, c1, c0, 0	@ get CR" : "=r" (val)
+		asm_arm_or_thumb2("mrc p15, 4, %0, c1, c0, 0	@ get CR"
+								  : "=r" (val)
 								  :
 								  : "cc");
 	else
-		asm volatile("mrc p15, 0, %0, c1, c0, 0	@ get CR" : "=r" (val)
+		asm_arm_or_thumb2("mrc p15, 0, %0, c1, c0, 0	@ get CR"
+								  : "=r" (val)
 								  :
 								  : "cc");
 	return val;
@@ -440,11 +452,11 @@  static inline unsigned int get_cr(void)
 static inline void set_cr(unsigned int val)
 {
 	if (is_hyp())
-		asm volatile("mcr p15, 4, %0, c1, c0, 0	@ set CR" :
+		asm_arm_or_thumb2("mcr p15, 4, %0, c1, c0, 0	@ set CR" :
 								  : "r" (val)
 								  : "cc");
 	else
-		asm volatile("mcr p15, 0, %0, c1, c0, 0	@ set CR" :
+		asm_arm_or_thumb2("mcr p15, 0, %0, c1, c0, 0	@ set CR" :
 								  : "r" (val)
 								  : "cc");
 	isb();
diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
index 516754caeaf..98e14c5c084 100644
--- a/arch/arm/lib/cache.c
+++ b/arch/arm/lib/cache.c
@@ -10,6 +10,7 @@ 
 #include <malloc.h>
 #include <asm/cache.h>
 #include <asm/global_data.h>
+#include <asm/system.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -125,8 +126,8 @@  void invalidate_l2_cache(void)
 {
 	unsigned int val = 0;
 
-	asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache"
-		: : "r" (val) : "cc");
+	asm_arm_or_thumb2("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache"
+			  : : "r" (val) : "cc");
 	isb();
 }
 #endif
diff --git a/arch/arm/mach-kirkwood/include/mach/cpu.h b/arch/arm/mach-kirkwood/include/mach/cpu.h
index 9eec786fe8f..dce190ddee2 100644
--- a/arch/arm/mach-kirkwood/include/mach/cpu.h
+++ b/arch/arm/mach-kirkwood/include/mach/cpu.h
@@ -85,8 +85,9 @@  struct mbus_win {
 static inline unsigned int readfr_extra_feature_reg(void)
 {
 	unsigned int val;
-	asm volatile ("mrc p15, 1, %0, c15, c1, 0 @ readfr exfr":"=r"
-			(val)::"cc");
+
+	asm_arm_or_thumb2("mrc p15, 1, %0, c15, c1, 0 @ readfr exfr":"=r"
+			  (val)::"cc");
 	return val;
 }
 
@@ -96,8 +97,8 @@  static inline unsigned int readfr_extra_feature_reg(void)
  */
 static inline void writefr_extra_feature_reg(unsigned int val)
 {
-	asm volatile ("mcr p15, 1, %0, c15, c1, 0 @ writefr exfr"::"r"
-			(val):"cc");
+	asm_arm_or_thumb2("mcr p15, 1, %0, c15, c1, 0 @ writefr exfr"::"r"
+			  (val):"cc");
 	isb();
 }