mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-06 05:44:20 +08:00
0b78f2e92d
Restructure the code and add the unwind annotations so that both the frame pointer unwinder as well as the EHABI unwind info based unwinder will be able to follow the call stack through call_with_stack(). Since GCC and Clang use different formats for the stack frame, two methods are implemented: a GCC version that pushes fp, sp, lr and pc for compatibility with the frame pointer unwinder, and a second version that works with Clang, as well as with the EHABI unwinder both in ARM and Thumb2 modes. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Keith Packard <keithpac@amazon.com> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com> Tested-by: Marc Zyngier <maz@kernel.org> Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
50 lines
1.0 KiB
ArmAsm
50 lines
1.0 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* arch/arm/lib/call_with_stack.S
|
|
*
|
|
* Copyright (C) 2011 ARM Ltd.
|
|
* Written by Will Deacon <will.deacon@arm.com>
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/assembler.h>
|
|
#include <asm/unwind.h>
|
|
|
|
/*
|
|
* void call_with_stack(void (*fn)(void *), void *arg, void *sp)
|
|
*
|
|
* Change the stack to that pointed at by sp, then invoke fn(arg) with
|
|
* the new stack.
|
|
*
|
|
* The sequence below follows the APCS frame convention for frame pointer
|
|
* unwinding, and implements the unwinder annotations needed by the EABI
|
|
* unwinder.
|
|
*/
|
|
|
|
ENTRY(call_with_stack)
|
|
#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
|
|
mov ip, sp
|
|
push {fp, ip, lr, pc}
|
|
sub fp, ip, #4
|
|
#else
|
|
UNWIND( .fnstart )
|
|
UNWIND( .save {fpreg, lr} )
|
|
push {fpreg, lr}
|
|
UNWIND( .setfp fpreg, sp )
|
|
mov fpreg, sp
|
|
#endif
|
|
mov sp, r2
|
|
mov r2, r0
|
|
mov r0, r1
|
|
|
|
bl_r r2
|
|
|
|
#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
|
|
ldmdb fp, {fp, sp, pc}
|
|
#else
|
|
mov sp, fpreg
|
|
pop {fpreg, pc}
|
|
UNWIND( .fnend )
|
|
#endif
|
|
ENDPROC(call_with_stack)
|