From 6fe50e39508043f386fc1bd40bbc02b8a75c1940 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Fri, 4 Apr 2025 15:50:35 +0200 Subject: [PATCH] arm: asm/system.h: mrc and mcr need .arm if __thumb2__ is not set 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 --- 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 --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 849b3d0efb7..4c1b81483c9 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -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(); diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c index dd19bd3e4fb..ed6f15cb570 100644 --- a/arch/arm/lib/cache.c +++ b/arch/arm/lib/cache.c @@ -10,6 +10,7 @@ #include #include #include +#include #include 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 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(); } -- 2.39.5