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 <[email protected]>
Tested-by: Stephen Warren <[email protected]> # Tegra Jetson TK1
Tested-by: Robert Jarzmik <[email protected]> # mioa701_bootresume.S
Tested-by: Andrew Lunn <[email protected]> # Kirkwood
Tested-by: Shawn Guo <[email protected]>
Tested-by: Tony Lindgren <[email protected]> # OMAPs
Tested-by: Gregory CLEMENT <[email protected]> # Armada XP, 375, 385
Acked-by: Sekhar Nori <[email protected]> # DaVinci
Acked-by: Christoffer Dall <[email protected]> # kvm/hyp
Acked-by: Haojian Zhuang <[email protected]> # PXA3xx
Acked-by: Stefano Stabellini <[email protected]> # Xen
Tested-by: Uwe Kleine-König <[email protected]> # ARMv7M
Tested-by: Simon Horman <[email protected]> # Shmobile
Signed-off-by: Russell King <[email protected]>

Conflicts:
	arch/arm/kernel/entry-header.S
	arch/arm/kernel/head-nommu.S
	arch/arm/kernel/head.S
	arch/arm/kernel/iwmmxt.S
	arch/arm/lib/bswapsdi2.S
	arch/arm/mach-ep93xx/crunch-bits.S
	arch/arm/mach-imx/suspend-imx6.S
	arch/arm/mach-mvebu/coherency_ll.S
	arch/arm/mach-mvebu/headsmp-a9.S
	arch/arm/mach-shmobile/headsmp.S
	arch/arm/mach-tegra/sleep-tegra20.S
	arch/arm/mach-tegra/sleep-tegra30.S
	arch/arm/mach-tegra/sleep.S
	arch/arm/mm/cache-nop.S
	arch/arm/mm/cache-v7.S
	arch/arm/mm/l2c-l2x0-resume.S
	arch/arm/mm/proc-v7.S
	arch/arm/mm/proc-v7m.S
	arch/arm/mm/tlb-v7.S
	arch/arm/vfp/entry.S
	arch/arm/vfp/vfphw.S
  • Loading branch information
Russell King authored and NotNoelChannel committed Nov 29, 2023
1 parent 45b94f9 commit 11c569b
Show file tree
Hide file tree
Showing 97 changed files with 1,263 additions and 532 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 @@ -368,4 +368,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
43 changes: 22 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 @@ -486,7 +486,8 @@ ENDPROC(__und_usr)
*/
.pushsection .fixup, "ax"
.align 2
4: mov pc, r9
4: str r4, [sp, #S_PC] @ retry current instruction
ret r9
.popsection
.pushsection __ex_table,"a"
.long 1b, 4b
Expand Down Expand Up @@ -548,7 +549,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 @@ -567,33 +568,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 @@ -645,7 +646,7 @@ ENTRY(fp_enter)
.popsection

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

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

Expand Down Expand Up @@ -833,7 +834,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 @@ -901,7 +902,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 @@ -563,7 +564,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
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 @@ -161,7 +162,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
16 changes: 8 additions & 8 deletions arch/arm/kernel/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ ENTRY(stext)
mov r8, r4 @ set TTBR1 to swapper_pg_dir
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
THUMB( ret r12 )
1: b __enable_mmu
ENDPROC(stext)
.ltorg
Expand Down Expand Up @@ -333,7 +333,7 @@ __create_page_tables:
#ifdef CONFIG_ARM_LPAE
sub r4, r4, #0x1000 @ point to the PGD table
#endif
mov pc, lr
ret lr
ENDPROC(__create_page_tables)
.ltorg
.align
Expand Down Expand Up @@ -381,7 +381,7 @@ ENTRY(secondary_startup)
ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor
@ (return control reg)
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
THUMB( ret r12 )
ENDPROC(secondary_startup)

/*
Expand Down Expand Up @@ -469,7 +469,7 @@ ENTRY(__turn_mmu_on)
instr_sync
mov r3, r3
mov r3, r13
mov pc, r3
ret r3
__turn_mmu_on_end:
ENDPROC(__turn_mmu_on)
.popsection
Expand All @@ -488,12 +488,12 @@ __fixup_smp:
orr r4, r4, #0x0000b000
orr r4, r4, #0x00000020 @ val 0x4100b020
teq r3, r4 @ ARM 11MPCore?
moveq pc, lr @ yes, assume SMP
reteq lr @ yes, assume SMP

mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
and r0, r0, #0xc0000000 @ multiprocessing extensions and
teq r0, #0x80000000 @ not part of a uniprocessor system?
moveq pc, lr @ yes, assume SMP
retne lr

__fixup_smp_on_up:
adr r0, 1f
Expand All @@ -520,7 +520,7 @@ smp_on_up:
.text
__do_fixup_smp_on_up:
cmp r4, r5
movhs pc, lr
reths lr
ldmia r4!, {r0, r6}
ARM( str r6, [r0, r3] )
THUMB( add r0, r0, r3 )
Expand Down Expand Up @@ -612,7 +612,7 @@ ARM_BE8(rev16 ip, ip)
2: cmp r4, r5
ldrcc r7, [r4], #4 @ use branch for delay slot
bcc 1b
mov pc, lr
ret lr
#endif
ENDPROC(__fixup_a_pv_table)

Expand Down
Loading

0 comments on commit 11c569b

Please sign in to comment.