xref: /openbmc/linux/arch/arm/lib/call_with_stack.S (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
145051539SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
22d81f1feSWill Deacon/*
32d81f1feSWill Deacon * arch/arm/lib/call_with_stack.S
42d81f1feSWill Deacon *
52d81f1feSWill Deacon * Copyright (C) 2011 ARM Ltd.
62d81f1feSWill Deacon * Written by Will Deacon <will.deacon@arm.com>
72d81f1feSWill Deacon */
82d81f1feSWill Deacon
92d81f1feSWill Deacon#include <linux/linkage.h>
102d81f1feSWill Deacon#include <asm/assembler.h>
110b78f2e9SArd Biesheuvel#include <asm/unwind.h>
122d81f1feSWill Deacon
132d81f1feSWill Deacon/*
142d81f1feSWill Deacon * void call_with_stack(void (*fn)(void *), void *arg, void *sp)
152d81f1feSWill Deacon *
162d81f1feSWill Deacon * Change the stack to that pointed at by sp, then invoke fn(arg) with
172d81f1feSWill Deacon * the new stack.
180b78f2e9SArd Biesheuvel *
190b78f2e9SArd Biesheuvel * The sequence below follows the APCS frame convention for frame pointer
200b78f2e9SArd Biesheuvel * unwinding, and implements the unwinder annotations needed by the EABI
210b78f2e9SArd Biesheuvel * unwinder.
222d81f1feSWill Deacon */
232d81f1feSWill Deacon
240b78f2e9SArd BiesheuvelENTRY(call_with_stack)
250b78f2e9SArd Biesheuvel#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
260b78f2e9SArd Biesheuvel	mov	ip, sp
270b78f2e9SArd Biesheuvel	push	{fp, ip, lr, pc}
280b78f2e9SArd Biesheuvel	sub	fp, ip, #4
290b78f2e9SArd Biesheuvel#else
300b78f2e9SArd BiesheuvelUNWIND( .fnstart		)
310b78f2e9SArd BiesheuvelUNWIND( .save	{fpreg, lr}	)
320b78f2e9SArd Biesheuvel	push	{fpreg, lr}
330b78f2e9SArd BiesheuvelUNWIND( .setfp	fpreg, sp	)
340b78f2e9SArd Biesheuvel	mov	fpreg, sp
350b78f2e9SArd Biesheuvel#endif
362d81f1feSWill Deacon	mov	sp, r2
372d81f1feSWill Deacon	mov	r2, r0
382d81f1feSWill Deacon	mov	r0, r1
392d81f1feSWill Deacon
400b78f2e9SArd Biesheuvel	bl_r	r2
412d81f1feSWill Deacon
420b78f2e9SArd Biesheuvel#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
430b78f2e9SArd Biesheuvel	ldmdb	fp, {fp, sp, pc}
440b78f2e9SArd Biesheuvel#else
450b78f2e9SArd Biesheuvel	mov	sp, fpreg
460b78f2e9SArd Biesheuvel	pop	{fpreg, pc}
470b78f2e9SArd BiesheuvelUNWIND( .fnend			)
480b78f2e9SArd Biesheuvel#endif
49*5854e4d8SLi Huafei	.globl call_with_stack_end
50*5854e4d8SLi Huafeicall_with_stack_end:
512d81f1feSWill DeaconENDPROC(call_with_stack)
52