Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ebbf2ce authored by Russell King's avatar Russell King
Browse files

ARM: convert all "mov.* pc, reg" to "bx reg" for ARMv6+



ARMv6 and greater introduced a new instruction ("bx") which can be used
to return from function calls.  Recent CPUs perform better when the
"bx lr" instruction is used rather than the "mov pc, lr" instruction,
and this sequence is strongly recommended to be used by the ARM
architecture manual (section A.4.1.1).

We provide a new macro "ret" with all its variants for the condition
code which will resolve to the appropriate instruction.

Rather than doing this piecemeal, and miss some instances, change all
the "mov pc" instances to use the new macro, with the exception of
the "movs" instruction and the kprobes code.  This allows us to detect
the "mov pc, lr" case and fix it up - and also gives us the possibility
of deploying this for other registers depending on the CPU selection.

Reported-by: default avatarWill Deacon <will.deacon@arm.com>
Tested-by: Stephen Warren <swarren@nvidia.com> # Tegra Jetson TK1
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr> # mioa701_bootresume.S
Tested-by: Andrew Lunn <andrew@lunn.ch> # Kirkwood
Tested-by: default avatarShawn Guo <shawn.guo@freescale.com>
Tested-by: Tony Lindgren <tony@atomide.com> # OMAPs
Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com> # Armada XP, 375, 385
Acked-by: Sekhar Nori <nsekhar@ti.com> # DaVinci
Acked-by: Christoffer Dall <christoffer.dall@linaro.org> # kvm/hyp
Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com> # PXA3xx
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> # Xen
Tested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> # ARMv7M
Tested-by: Simon Horman <horms+renesas@verge.net.au> # Shmobile
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent af040ffc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
@ that is being targetted.

#include <linux/linkage.h>
#include <asm/assembler.h>

.text

@@ -648,7 +649,7 @@ _armv4_AES_set_encrypt_key:

.Ldone:	mov	r0,#0
	ldmia   sp!,{r4-r12,lr}
.Labrt:	mov	pc,lr
.Labrt:	ret	lr
ENDPROC(private_AES_set_encrypt_key)

.align	5
+21 −0
Original line number Diff line number Diff line
@@ -427,4 +427,25 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
#endif
	.endm

	.irp	c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
	.macro	ret\c, reg
#if __LINUX_ARM_ARCH__ < 6
	mov\c	pc, \reg
#else
	.ifeqs	"\reg", "lr"
	bx\c	\reg
	.else
	mov\c	pc, \reg
	.endif
#endif
	.endm
	.endr

	.macro	ret.w, reg
	ret	\reg
#ifdef CONFIG_THUMB2_KERNEL
	nop
#endif
	.endm

#endif /* __ASM_ASSEMBLER_H__ */
+1 −1
Original line number Diff line number Diff line
@@ -35,5 +35,5 @@
\symbol_name:
	mov	r8, lr
	arch_irq_handler_default
	mov     pc, r8
	ret	r8
	.endm
+5 −5
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ ENTRY(printascii)
		ldrneb	r1, [r0], #1
		teqne	r1, #0
		bne	1b
		mov	pc, lr
		ret	lr
ENDPROC(printascii)

ENTRY(printch)
@@ -105,7 +105,7 @@ ENTRY(debug_ll_addr)
		addruart r2, r3, ip
		str	r2, [r0]
		str	r3, [r1]
		mov	pc, lr
		ret	lr
ENDPROC(debug_ll_addr)
#endif

@@ -116,7 +116,7 @@ ENTRY(printascii)
		mov	r0, #0x04		@ SYS_WRITE0
	ARM(	svc	#0x123456	)
	THUMB(	svc	#0xab		)
		mov	pc, lr
		ret	lr
ENDPROC(printascii)

ENTRY(printch)
@@ -125,14 +125,14 @@ ENTRY(printch)
		mov	r0, #0x03		@ SYS_WRITEC
	ARM(	svc	#0x123456	)
	THUMB(	svc	#0xab		)
		mov	pc, lr
		ret	lr
ENDPROC(printch)

ENTRY(debug_ll_addr)
		mov	r2, #0
		str	r2, [r0]
		str	r2, [r1]
		mov	pc, lr
		ret	lr
ENDPROC(debug_ll_addr)

#endif
+21 −21
Original line number Diff line number Diff line
@@ -224,7 +224,7 @@ svc_preempt:
1:	bl	preempt_schedule_irq		@ irq en/disable is done inside
	ldr	r0, [tsk, #TI_FLAGS]		@ get new tasks TI_FLAGS
	tst	r0, #_TIF_NEED_RESCHED
	moveq	pc, r8				@ go again
	reteq	r8				@ go again
	b	1b
#endif

@@ -490,7 +490,7 @@ ENDPROC(__und_usr)
	.pushsection .fixup, "ax"
	.align	2
4:	str     r4, [sp, #S_PC]			@ retry current instruction
	mov	pc, r9
	ret	r9
	.popsection
	.pushsection __ex_table,"a"
	.long	1b, 4b
@@ -552,7 +552,7 @@ call_fpe:
#endif
	tst	r0, #0x08000000			@ only CDP/CPRT/LDC/STC have bit 27
	tstne	r0, #0x04000000			@ bit 26 set on both ARM and Thumb-2
	moveq	pc, lr
	reteq	lr
	and	r8, r0, #0x00000f00		@ mask out CP number
 THUMB(	lsr	r8, r8, #8		)
	mov	r7, #1
@@ -571,33 +571,33 @@ call_fpe:
 THUMB(	add	pc, r8			)
	nop

	movw_pc	lr				@ CP#0
	ret.w	lr				@ CP#0
	W(b)	do_fpe				@ CP#1 (FPE)
	W(b)	do_fpe				@ CP#2 (FPE)
	movw_pc	lr				@ CP#3
	ret.w	lr				@ CP#3
#ifdef CONFIG_CRUNCH
	b	crunch_task_enable		@ CP#4 (MaverickCrunch)
	b	crunch_task_enable		@ CP#5 (MaverickCrunch)
	b	crunch_task_enable		@ CP#6 (MaverickCrunch)
#else
	movw_pc	lr				@ CP#4
	movw_pc	lr				@ CP#5
	movw_pc	lr				@ CP#6
	ret.w	lr				@ CP#4
	ret.w	lr				@ CP#5
	ret.w	lr				@ CP#6
#endif
	movw_pc	lr				@ CP#7
	movw_pc	lr				@ CP#8
	movw_pc	lr				@ CP#9
	ret.w	lr				@ CP#7
	ret.w	lr				@ CP#8
	ret.w	lr				@ CP#9
#ifdef CONFIG_VFP
	W(b)	do_vfp				@ CP#10 (VFP)
	W(b)	do_vfp				@ CP#11 (VFP)
#else
	movw_pc	lr				@ CP#10 (VFP)
	movw_pc	lr				@ CP#11 (VFP)
	ret.w	lr				@ CP#10 (VFP)
	ret.w	lr				@ CP#11 (VFP)
#endif
	movw_pc	lr				@ CP#12
	movw_pc	lr				@ CP#13
	movw_pc	lr				@ CP#14 (Debug)
	movw_pc	lr				@ CP#15 (Control)
	ret.w	lr				@ CP#12
	ret.w	lr				@ CP#13
	ret.w	lr				@ CP#14 (Debug)
	ret.w	lr				@ CP#15 (Control)

#ifdef NEED_CPU_ARCHITECTURE
	.align	2
@@ -649,7 +649,7 @@ ENTRY(fp_enter)
	.popsection

ENTRY(no_fp)
	mov	pc, lr
	ret	lr
ENDPROC(no_fp)

__und_usr_fault_32:
@@ -745,7 +745,7 @@ ENDPROC(__switch_to)
#ifdef CONFIG_ARM_THUMB
	bx	\reg
#else
	mov	pc, \reg
	ret	\reg
#endif
	.endm

@@ -837,7 +837,7 @@ kuser_cmpxchg64_fixup:
#if __LINUX_ARM_ARCH__ < 6
	bcc	kuser_cmpxchg32_fixup
#endif
	mov	pc, lr
	ret	lr
	.previous

#else
@@ -905,7 +905,7 @@ kuser_cmpxchg32_fixup:
	subs	r8, r4, r7
	rsbcss	r8, r8, #(2b - 1b)
	strcs	r7, [sp, #S_PC]
	mov	pc, lr
	ret	lr
	.previous

#else
Loading