Message ID | 20211017131723.4034662-10-ardb@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ARM: add support for IRQ stacks | expand |
On Sun, Oct 17, 2021 at 6:17 AM Ard Biesheuvel <ardb@kernel.org> wrote: > > 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. Thanks for the patch! Reviewed-by: Nick Desaulniers <ndesaulniers@google.com> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org> > Acked-by: Linus Walleij <linus.walleij@linaro.org> > Tested-by: Keith Packard <keithpac@amazon.com> > --- > arch/arm/lib/call_with_stack.S | 33 +++++++++++++++----- > 1 file changed, 25 insertions(+), 8 deletions(-) > > diff --git a/arch/arm/lib/call_with_stack.S b/arch/arm/lib/call_with_stack.S > index 28b0341ae786..0a268a6c513c 100644 > --- a/arch/arm/lib/call_with_stack.S > +++ b/arch/arm/lib/call_with_stack.S > @@ -8,25 +8,42 @@ > > #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) > - str sp, [r2, #-4]! > - str lr, [r2, #-4]! > > +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 > > - badr lr, 1f > - ret r2 > + bl_r r2 > > -1: ldr lr, [sp] > - ldr sp, [sp, #4] > - ret lr > +#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) > -- > 2.30.2 >
diff --git a/arch/arm/lib/call_with_stack.S b/arch/arm/lib/call_with_stack.S index 28b0341ae786..0a268a6c513c 100644 --- a/arch/arm/lib/call_with_stack.S +++ b/arch/arm/lib/call_with_stack.S @@ -8,25 +8,42 @@ #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) - str sp, [r2, #-4]! - str lr, [r2, #-4]! +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 - badr lr, 1f - ret r2 + bl_r r2 -1: ldr lr, [sp] - ldr sp, [sp, #4] - ret lr +#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)