@@ -773,14 +773,14 @@ ENDPROC(__fiq_usr)
* r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
* previous and next are guaranteed not to be the same.
*/
+ .align 5
ENTRY(__switch_to)
UNWIND(.fnstart )
UNWIND(.cantunwind )
- add ip, r1, #TI_CPU_SAVE
- ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack
- THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack
- THUMB( str sp, [ip], #4 )
- THUMB( str lr, [ip], #4 )
+ add r3, r1, #TI_CPU_SAVE
+ ARM( stmia r3, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack
+ THUMB( mov ip, sp )
+ THUMB( stmia r3, {r4 - sl, fp, ip, lr} ) @ Thumb2 does not permit SP here
ldr r4, [r2, #TI_TP_VALUE]
ldr r5, [r2, #TI_TP_VALUE + 4]
#ifdef CONFIG_CPU_USE_DOMAINS
@@ -805,20 +805,22 @@ ENTRY(__switch_to)
#endif
mov r5, r0
add r4, r2, #TI_CPU_SAVE
- ldr r0, =thread_notify_head
+ mov_l r0, thread_notify_head
mov r1, #THREAD_NOTIFY_SWITCH
bl atomic_notifier_call_chain
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP) && \
!defined(CONFIG_STACKPROTECTOR_PER_TASK)
str r9, [r8]
#endif
- THUMB( mov ip, r4 )
mov r0, r5
set_current r7, r8
- ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
- THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously
- THUMB( ldr sp, [ip], #4 )
- THUMB( ldr pc, [ip] )
+#if !defined(CONFIG_THUMB2_KERNEL)
+ ldmia r4, {r4 - sl, fp, sp, pc} @ Load all regs saved previously
+#else
+ ldmia r4, {r4 - sl, fp, ip, lr} @ Thumb2 does not permit SP here
+ mov sp, ip
+ ret lr
+#endif
UNWIND(.fnend )
ENDPROC(__switch_to)
The load/store-multiple instructions that essentially perform the switch_to operation in ARM mode, by loading/storing all callee save registers as well the stack pointer and the link register or program counter, is split into 3 separate loads or stores for Thumb-2, with the IP register used as a temporary to capture the target address. We can clean this up a bit, by sticking with a single STMIA or LDMIA instruction, but one that uses IP instead of SP. While at it, switch to a MOVW/MOVT pair to load thread_notify_head. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> --- arch/arm/kernel/entry-armv.S | 24 +++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-)