arm: asm/system.h: mrc and mcr need .arm if __thumb2__ is not set
authorJerome Forissier <jerome.forissier@linaro.org>
Fri, 4 Apr 2025 13:50:35 +0000 (15:50 +0200)
committerTom Rini <trini@konsulko.com>
Mon, 14 Apr 2025 14:59:39 +0000 (08:59 -0600)
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
arch/arm/lib/cache.c
arch/arm/mach-kirkwood/include/mach/cpu.h

index 849b3d0..4c1b814 100644 (file)
@@ -428,11 +428,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;
 }
@@ -461,11 +471,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;
@@ -474,11 +486,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();
index dd19bd3..ed6f15c 100644 (file)
@@ -10,6 +10,7 @@
 #include <malloc.h>
 #include <asm/cache.h>
 #include <asm/global_data.h>
+#include <asm/system.h>
 #include <linux/errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -126,8 +127,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
index 9eec786..dce190d 100644 (file)
@@ -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();
 }