call_with_stack.S 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  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 <[email protected]>
  7. */
  8. #include <linux/linkage.h>
  9. #include <asm/assembler.h>
  10. #include <asm/unwind.h>
  11. /*
  12. * void call_with_stack(void (*fn)(void *), void *arg, void *sp)
  13. *
  14. * Change the stack to that pointed at by sp, then invoke fn(arg) with
  15. * the new stack.
  16. *
  17. * The sequence below follows the APCS frame convention for frame pointer
  18. * unwinding, and implements the unwinder annotations needed by the EABI
  19. * unwinder.
  20. */
  21. ENTRY(call_with_stack)
  22. #if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
  23. mov ip, sp
  24. push {fp, ip, lr, pc}
  25. sub fp, ip, #4
  26. #else
  27. UNWIND( .fnstart )
  28. UNWIND( .save {fpreg, lr} )
  29. push {fpreg, lr}
  30. UNWIND( .setfp fpreg, sp )
  31. mov fpreg, sp
  32. #endif
  33. mov sp, r2
  34. mov r2, r0
  35. mov r0, r1
  36. bl_r r2
  37. #if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
  38. ldmdb fp, {fp, sp, pc}
  39. #else
  40. mov sp, fpreg
  41. pop {fpreg, pc}
  42. UNWIND( .fnend )
  43. #endif
  44. .globl call_with_stack_end
  45. call_with_stack_end:
  46. ENDPROC(call_with_stack)