mcount-dyn.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /* Copyright (C) 2017 Andes Technology Corporation */
  3. #include <linux/init.h>
  4. #include <linux/linkage.h>
  5. #include <linux/export.h>
  6. #include <asm/asm.h>
  7. #include <asm/csr.h>
  8. #include <asm/unistd.h>
  9. #include <asm/thread_info.h>
  10. #include <asm/asm-offsets.h>
  11. #include <asm/ftrace.h>
  12. .text
  13. #define FENTRY_RA_OFFSET 8
  14. #define ABI_SIZE_ON_STACK 80
  15. #define ABI_A0 0
  16. #define ABI_A1 8
  17. #define ABI_A2 16
  18. #define ABI_A3 24
  19. #define ABI_A4 32
  20. #define ABI_A5 40
  21. #define ABI_A6 48
  22. #define ABI_A7 56
  23. #define ABI_T0 64
  24. #define ABI_RA 72
  25. .macro SAVE_ABI
  26. addi sp, sp, -ABI_SIZE_ON_STACK
  27. REG_S a0, ABI_A0(sp)
  28. REG_S a1, ABI_A1(sp)
  29. REG_S a2, ABI_A2(sp)
  30. REG_S a3, ABI_A3(sp)
  31. REG_S a4, ABI_A4(sp)
  32. REG_S a5, ABI_A5(sp)
  33. REG_S a6, ABI_A6(sp)
  34. REG_S a7, ABI_A7(sp)
  35. REG_S t0, ABI_T0(sp)
  36. REG_S ra, ABI_RA(sp)
  37. .endm
  38. .macro RESTORE_ABI
  39. REG_L a0, ABI_A0(sp)
  40. REG_L a1, ABI_A1(sp)
  41. REG_L a2, ABI_A2(sp)
  42. REG_L a3, ABI_A3(sp)
  43. REG_L a4, ABI_A4(sp)
  44. REG_L a5, ABI_A5(sp)
  45. REG_L a6, ABI_A6(sp)
  46. REG_L a7, ABI_A7(sp)
  47. REG_L t0, ABI_T0(sp)
  48. REG_L ra, ABI_RA(sp)
  49. addi sp, sp, ABI_SIZE_ON_STACK
  50. .endm
  51. #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
  52. /**
  53. * SAVE_ABI_REGS - save regs against the ftrace_regs struct
  54. *
  55. * After the stack is established,
  56. *
  57. * 0(sp) stores the PC of the traced function which can be accessed
  58. * by &(fregs)->epc in tracing function. Note that the real
  59. * function entry address should be computed with -FENTRY_RA_OFFSET.
  60. *
  61. * 8(sp) stores the function return address (i.e. parent IP) that
  62. * can be accessed by &(fregs)->ra in tracing function.
  63. *
  64. * The other regs are saved at the respective localtion and accessed
  65. * by the respective ftrace_regs member.
  66. *
  67. * Here is the layout of stack for your reference.
  68. *
  69. * PT_SIZE_ON_STACK -> +++++++++
  70. * + ..... +
  71. * + a0-a7 + --++++-> ftrace_caller saved
  72. * + t1 + --++++-> direct tramp address
  73. * + s0 + --+ // frame pointer
  74. * + sp + +
  75. * + ra + --+ // parent IP
  76. * sp -> + epc + --+ // PC
  77. * +++++++++
  78. **/
  79. .macro SAVE_ABI_REGS
  80. mv t4, sp // Save original SP in T4
  81. addi sp, sp, -FREGS_SIZE_ON_STACK
  82. REG_S t0, FREGS_EPC(sp)
  83. REG_S x1, FREGS_RA(sp)
  84. REG_S t4, FREGS_SP(sp) // Put original SP on stack
  85. #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
  86. REG_S x8, FREGS_S0(sp)
  87. #endif
  88. REG_S x6, FREGS_T1(sp)
  89. // save the arguments
  90. REG_S x10, FREGS_A0(sp)
  91. REG_S x11, FREGS_A1(sp)
  92. REG_S x12, FREGS_A2(sp)
  93. REG_S x13, FREGS_A3(sp)
  94. REG_S x14, FREGS_A4(sp)
  95. REG_S x15, FREGS_A5(sp)
  96. REG_S x16, FREGS_A6(sp)
  97. REG_S x17, FREGS_A7(sp)
  98. .endm
  99. .macro RESTORE_ABI_REGS, all=0
  100. REG_L t0, FREGS_EPC(sp)
  101. REG_L x1, FREGS_RA(sp)
  102. #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
  103. REG_L x8, FREGS_S0(sp)
  104. #endif
  105. REG_L x6, FREGS_T1(sp)
  106. // restore the arguments
  107. REG_L x10, FREGS_A0(sp)
  108. REG_L x11, FREGS_A1(sp)
  109. REG_L x12, FREGS_A2(sp)
  110. REG_L x13, FREGS_A3(sp)
  111. REG_L x14, FREGS_A4(sp)
  112. REG_L x15, FREGS_A5(sp)
  113. REG_L x16, FREGS_A6(sp)
  114. REG_L x17, FREGS_A7(sp)
  115. addi sp, sp, FREGS_SIZE_ON_STACK
  116. .endm
  117. .macro PREPARE_ARGS
  118. addi a0, t0, -FENTRY_RA_OFFSET
  119. la a1, function_trace_op
  120. REG_L a2, 0(a1)
  121. mv a1, ra
  122. mv a3, sp
  123. .endm
  124. #endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
  125. #ifndef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
  126. SYM_FUNC_START(ftrace_caller)
  127. SAVE_ABI
  128. addi a0, t0, -FENTRY_RA_OFFSET
  129. la a1, function_trace_op
  130. REG_L a2, 0(a1)
  131. mv a1, ra
  132. mv a3, sp
  133. SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
  134. call ftrace_stub
  135. #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  136. addi a0, sp, ABI_RA
  137. REG_L a1, ABI_T0(sp)
  138. addi a1, a1, -FENTRY_RA_OFFSET
  139. #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
  140. mv a2, s0
  141. #endif
  142. SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
  143. call ftrace_stub
  144. #endif
  145. RESTORE_ABI
  146. jr t0
  147. SYM_FUNC_END(ftrace_caller)
  148. #else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
  149. SYM_FUNC_START(ftrace_caller)
  150. mv t1, zero
  151. SAVE_ABI_REGS
  152. PREPARE_ARGS
  153. SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
  154. call ftrace_stub
  155. RESTORE_ABI_REGS
  156. bnez t1, .Ldirect
  157. jr t0
  158. .Ldirect:
  159. jr t1
  160. SYM_FUNC_END(ftrace_caller)
  161. #endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
  162. #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
  163. SYM_CODE_START(ftrace_stub_direct_tramp)
  164. jr t0
  165. SYM_CODE_END(ftrace_stub_direct_tramp)
  166. #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */