Skip to content

Commit

Permalink
ARM: convert all "mov.* pc, reg" to "bx reg" for ARMv6+
Browse files Browse the repository at this point in the history
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: Will 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: Shawn 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: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Russell King committed Jul 18, 2014
1 parent af040ff commit 6ebbf2c
Show file tree
Hide file tree
Showing 106 changed files with 644 additions and 607 deletions.
3 changes: 2 additions & 1 deletion arch/arm/crypto/aes-armv4.S
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
@ that is being targetted.

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

.text

Expand Down Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions arch/arm/include/asm/assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
2 changes: 1 addition & 1 deletion arch/arm/include/asm/entry-macro-multi.S
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@
\symbol_name:
mov r8, lr
arch_irq_handler_default
mov pc, r8
ret r8
.endm
10 changes: 5 additions & 5 deletions arch/arm/kernel/debug.S
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ ENTRY(printascii)
ldrneb r1, [r0], #1
teqne r1, #0
bne 1b
mov pc, lr
ret lr
ENDPROC(printascii)

ENTRY(printch)
Expand All @@ -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

Expand All @@ -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)
Expand All @@ -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
42 changes: 21 additions & 21 deletions arch/arm/kernel/entry-armv.S
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -649,7 +649,7 @@ ENTRY(fp_enter)
.popsection

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

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

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

#else
Expand Down Expand Up @@ -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
Expand Down
13 changes: 7 additions & 6 deletions arch/arm/kernel/entry-common.S
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/

#include <asm/assembler.h>
#include <asm/unistd.h>
#include <asm/ftrace.h>
#include <asm/unwind.h>
Expand Down Expand Up @@ -88,7 +89,7 @@ ENTRY(ret_from_fork)
cmp r5, #0
movne r0, r4
adrne lr, BSYM(1f)
movne pc, r5
retne r5
1: get_thread_info tsk
b ret_slow_syscall
ENDPROC(ret_from_fork)
Expand Down Expand Up @@ -290,15 +291,15 @@ ENDPROC(ftrace_graph_caller_old)

.macro mcount_exit
ldmia sp!, {r0-r3, ip, lr}
mov pc, ip
ret ip
.endm

ENTRY(__gnu_mcount_nc)
UNWIND(.fnstart)
#ifdef CONFIG_DYNAMIC_FTRACE
mov ip, lr
ldmia sp!, {lr}
mov pc, ip
ret ip
#else
__mcount
#endif
Expand Down Expand Up @@ -333,12 +334,12 @@ return_to_handler:
bl ftrace_return_to_handler
mov lr, r0 @ r0 has real ret addr
ldmia sp!, {r0-r3}
mov pc, lr
ret lr
#endif

ENTRY(ftrace_stub)
.Lftrace_stub:
mov pc, lr
ret lr
ENDPROC(ftrace_stub)

#endif /* CONFIG_FUNCTION_TRACER */
Expand Down Expand Up @@ -561,7 +562,7 @@ sys_mmap2:
streq r5, [sp, #4]
beq sys_mmap_pgoff
mov r0, #-EINVAL
mov pc, lr
ret lr
#else
str r5, [sp, #4]
b sys_mmap_pgoff
Expand Down
14 changes: 0 additions & 14 deletions arch/arm/kernel/entry-header.S
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,6 @@
movs pc, lr @ return & move spsr_svc into cpsr
.endm

@
@ 32-bit wide "mov pc, reg"
@
.macro movw_pc, reg
mov pc, \reg
.endm
#else /* CONFIG_THUMB2_KERNEL */
.macro svc_exit, rpsr, irq = 0
.if \irq != 0
Expand Down Expand Up @@ -304,14 +298,6 @@
movs pc, lr @ return & move spsr_svc into cpsr
.endm
#endif /* ifdef CONFIG_CPU_V7M / else */

@
@ 32-bit wide "mov pc, reg"
@
.macro movw_pc, reg
mov pc, \reg
nop
.endm
#endif /* !CONFIG_THUMB2_KERNEL */

/*
Expand Down
4 changes: 2 additions & 2 deletions arch/arm/kernel/fiqasm.S
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ ENTRY(__set_fiq_regs)
ldr lr, [r0]
msr cpsr_c, r1 @ return to SVC mode
mov r0, r0 @ avoid hazard prior to ARMv4
mov pc, lr
ret lr
ENDPROC(__set_fiq_regs)

ENTRY(__get_fiq_regs)
Expand All @@ -45,5 +45,5 @@ ENTRY(__get_fiq_regs)
str lr, [r0]
msr cpsr_c, r1 @ return to SVC mode
mov r0, r0 @ avoid hazard prior to ARMv4
mov pc, lr
ret lr
ENDPROC(__get_fiq_regs)
7 changes: 4 additions & 3 deletions arch/arm/kernel/head-common.S
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*
*/
#include <asm/assembler.h>

#define ATAG_CORE 0x54410001
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
Expand Down Expand Up @@ -61,10 +62,10 @@ __vet_atags:
cmp r5, r6
bne 1f

2: mov pc, lr @ atag/dtb pointer is ok
2: ret lr @ atag/dtb pointer is ok

1: mov r2, #0
mov pc, lr
ret lr
ENDPROC(__vet_atags)

/*
Expand Down Expand Up @@ -162,7 +163,7 @@ __lookup_processor_type:
cmp r5, r6
blo 1b
mov r5, #0 @ unknown processor
2: mov pc, lr
2: ret lr
ENDPROC(__lookup_processor_type)

/*
Expand Down
8 changes: 4 additions & 4 deletions arch/arm/kernel/head-nommu.S
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ ENTRY(stext)
adr lr, BSYM(1f) @ return (PIC) address
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
THUMB( ret r12 )
1: b __after_proc_init
ENDPROC(stext)

Expand Down Expand Up @@ -119,7 +119,7 @@ ENTRY(secondary_startup)
mov r13, r12 @ __secondary_switched address
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
THUMB( ret r12 )
ENDPROC(secondary_startup)

ENTRY(__secondary_switched)
Expand Down Expand Up @@ -164,7 +164,7 @@ __after_proc_init:
#endif
mcr p15, 0, r0, c1, c0, 0 @ write control reg
#endif /* CONFIG_CPU_CP15 */
mov pc, r13
ret r13
ENDPROC(__after_proc_init)
.ltorg

Expand Down Expand Up @@ -254,7 +254,7 @@ ENTRY(__setup_mpu)
orr r0, r0, #CR_M @ Set SCTRL.M (MPU on)
mcr p15, 0, r0, c1, c0, 0 @ Enable MPU
isb
mov pc,lr
ret lr
ENDPROC(__setup_mpu)
#endif
#include "head-common.S"
Loading

0 comments on commit 6ebbf2c

Please sign in to comment.