diff mbox series

[03/10] ARM: assembler: introduce bl_r and bl_m macros

Message ID 20210921095408.133210-4-ardb@kernel.org (mailing list archive)
State New, archived
Headers show
Series ARM: add support for IRQ stacks | expand

Commit Message

Ard Biesheuvel Sept. 21, 2021, 9:54 a.m. UTC
Add some macros that abstract the difference between the ways indirect
calls are performed on older and newer ARM architecture revisions.

The main difference is to prefer blx instructions over explicit LR
assignments when possible, as these tend to confuse the prediction logic
in out-of-order cores when speculating across a function return.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/assembler.h | 37 ++++++++++++++++++++
 1 file changed, 37 insertions(+)
diff mbox series

Patch

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 7d23d4bb2168..abb8202ef0da 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -624,4 +624,41 @@  THUMB(	orr	\reg , \reg , #PSR_T_BIT	)
 	.endif
 	.endm
 
+	/*
+	 * bl_r - branch and link to register
+	 *
+	 * @dst: target to branch to
+	 * @c: conditional opcode suffix
+	 */
+	.macro		bl_r, dst:req, c
+	.if		__LINUX_ARM_ARCH__ < 6
+	mov\c		lr, pc
+	mov\c		pc, \dst
+	.else
+	blx\c		\dst
+	.endif
+	.endm
+
+	/*
+	 * bl_m - branch and link to address held in memory
+	 *
+	 * @dst: memory reference to load the branch target from
+	 *
+	 * This uses the same syntax as ldr instructions, including things like
+	 * register writeback (where it makes sense). For example,
+	 *
+	 *    bl_m    [ip, #<offset>]
+	 *
+	 * Note that @dst should not reference lr as it may be clobbered early.
+	 */
+	.macro		bl_m, dst:vararg
+	.if		__LINUX_ARM_ARCH__ < 6
+	mov		lr, pc
+	ldr		pc, \dst
+	.else
+	ldr		lr, \dst
+	blx		lr
+	.endif
+	.endm
+
 #endif /* __ASM_ASSEMBLER_H__ */