ftrace.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * arch/arm64/include/asm/ftrace.h
  4. *
  5. * Copyright (C) 2013 Linaro Limited
  6. * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
  7. */
  8. #ifndef __ASM_FTRACE_H
  9. #define __ASM_FTRACE_H
  10. #include <asm/insn.h>
  11. #define HAVE_FUNCTION_GRAPH_FP_TEST
  12. #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
  13. #define ARCH_SUPPORTS_FTRACE_OPS 1
  14. #else
  15. #define MCOUNT_ADDR ((unsigned long)_mcount)
  16. #endif
  17. /* The BL at the callsite's adjusted rec->ip */
  18. #define MCOUNT_INSN_SIZE AARCH64_INSN_SIZE
  19. #define FTRACE_PLT_IDX 0
  20. #define NR_FTRACE_PLTS 1
  21. /*
  22. * Currently, gcc tends to save the link register after the local variables
  23. * on the stack. This causes the max stack tracer to report the function
  24. * frame sizes for the wrong functions. By defining
  25. * ARCH_FTRACE_SHIFT_STACK_TRACER, it will tell the stack tracer to expect
  26. * to find the return address on the stack after the local variables have
  27. * been set up.
  28. *
  29. * Note, this may change in the future, and we will need to deal with that
  30. * if it were to happen.
  31. */
  32. #define ARCH_FTRACE_SHIFT_STACK_TRACER 1
  33. #ifndef __ASSEMBLY__
  34. #include <linux/compat.h>
  35. extern void _mcount(unsigned long);
  36. extern void *return_address(unsigned int);
  37. struct dyn_arch_ftrace {
  38. /* No extra data needed for arm64 */
  39. };
  40. extern unsigned long ftrace_graph_call;
  41. extern void return_to_handler(void);
  42. unsigned long ftrace_call_adjust(unsigned long addr);
  43. #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
  44. struct dyn_ftrace;
  45. struct ftrace_ops;
  46. #define arch_ftrace_get_regs(regs) NULL
  47. /*
  48. * Note: sizeof(struct ftrace_regs) must be a multiple of 16 to ensure correct
  49. * stack alignment
  50. */
  51. struct ftrace_regs {
  52. /* x0 - x8 */
  53. unsigned long regs[9];
  54. #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
  55. unsigned long direct_tramp;
  56. #else
  57. unsigned long __unused;
  58. #endif
  59. unsigned long fp;
  60. unsigned long lr;
  61. unsigned long sp;
  62. unsigned long pc;
  63. };
  64. static __always_inline unsigned long
  65. ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs)
  66. {
  67. return fregs->pc;
  68. }
  69. static __always_inline void
  70. ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
  71. unsigned long pc)
  72. {
  73. fregs->pc = pc;
  74. }
  75. static __always_inline unsigned long
  76. ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs)
  77. {
  78. return fregs->sp;
  79. }
  80. static __always_inline unsigned long
  81. ftrace_regs_get_argument(struct ftrace_regs *fregs, unsigned int n)
  82. {
  83. if (n < 8)
  84. return fregs->regs[n];
  85. return 0;
  86. }
  87. static __always_inline unsigned long
  88. ftrace_regs_get_return_value(const struct ftrace_regs *fregs)
  89. {
  90. return fregs->regs[0];
  91. }
  92. static __always_inline void
  93. ftrace_regs_set_return_value(struct ftrace_regs *fregs,
  94. unsigned long ret)
  95. {
  96. fregs->regs[0] = ret;
  97. }
  98. static __always_inline void
  99. ftrace_override_function_with_return(struct ftrace_regs *fregs)
  100. {
  101. fregs->pc = fregs->lr;
  102. }
  103. int ftrace_regs_query_register_offset(const char *name);
  104. int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
  105. #define ftrace_init_nop ftrace_init_nop
  106. void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
  107. struct ftrace_ops *op, struct ftrace_regs *fregs);
  108. #define ftrace_graph_func ftrace_graph_func
  109. #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
  110. static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs,
  111. unsigned long addr)
  112. {
  113. /*
  114. * The ftrace trampoline will return to this address instead of the
  115. * instrumented function.
  116. */
  117. fregs->direct_tramp = addr;
  118. }
  119. #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
  120. #endif
  121. #define ftrace_return_address(n) return_address(n)
  122. /*
  123. * Because AArch32 mode does not share the same syscall table with AArch64,
  124. * tracing compat syscalls may result in reporting bogus syscalls or even
  125. * hang-up, so just do not trace them.
  126. * See kernel/trace/trace_syscalls.c
  127. *
  128. * x86 code says:
  129. * If the user really wants these, then they should use the
  130. * raw syscall tracepoints with filtering.
  131. */
  132. #define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
  133. static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
  134. {
  135. return is_compat_task();
  136. }
  137. #define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
  138. static inline bool arch_syscall_match_sym_name(const char *sym,
  139. const char *name)
  140. {
  141. /*
  142. * Since all syscall functions have __arm64_ prefix, we must skip it.
  143. * However, as we described above, we decided to ignore compat
  144. * syscalls, so we don't care about __arm64_compat_ prefix here.
  145. */
  146. return !strcmp(sym + 8, name);
  147. }
  148. #endif /* ifndef __ASSEMBLY__ */
  149. #ifndef __ASSEMBLY__
  150. #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  151. struct fgraph_ret_regs {
  152. /* x0 - x7 */
  153. unsigned long regs[8];
  154. unsigned long fp;
  155. unsigned long __unused;
  156. };
  157. static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
  158. {
  159. return ret_regs->regs[0];
  160. }
  161. static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
  162. {
  163. return ret_regs->fp;
  164. }
  165. void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
  166. unsigned long frame_pointer);
  167. #endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */
  168. #endif
  169. #endif /* __ASM_FTRACE_H */