1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * arch/arm/lib/call_with_stack.S 4 * 5 * Copyright (C) 2011 ARM Ltd. 6 * Written by Will Deacon <will.deacon@arm.com> 7 */ 8 9#include <linux/linkage.h> 10#include <asm/assembler.h> 11#include <asm/unwind.h> 12 13/* 14 * void call_with_stack(void (*fn)(void *), void *arg, void *sp) 15 * 16 * Change the stack to that pointed at by sp, then invoke fn(arg) with 17 * the new stack. 18 * 19 * The sequence below follows the APCS frame convention for frame pointer 20 * unwinding, and implements the unwinder annotations needed by the EABI 21 * unwinder. 22 */ 23 24ENTRY(call_with_stack) 25#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC) 26 mov ip, sp 27 push {fp, ip, lr, pc} 28 sub fp, ip, #4 29#else 30UNWIND( .fnstart ) 31UNWIND( .save {fpreg, lr} ) 32 push {fpreg, lr} 33UNWIND( .setfp fpreg, sp ) 34 mov fpreg, sp 35#endif 36 mov sp, r2 37 mov r2, r0 38 mov r0, r1 39 40 bl_r r2 41 42#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC) 43 ldmdb fp, {fp, sp, pc} 44#else 45 mov sp, fpreg 46 pop {fpreg, pc} 47UNWIND( .fnend ) 48#endif 49ENDPROC(call_with_stack) 50