1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
25d360a75SHeiko Carstens #ifndef _ASM_S390_FTRACE_H
35d360a75SHeiko Carstens #define _ASM_S390_FTRACE_H
45d360a75SHeiko Carstens
5ec7bf478SMartin Schwidefsky #define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
6c9343637SVasily Gorbik #define ARCH_SUPPORTS_FTRACE_OPS 1
7c9343637SVasily Gorbik #define MCOUNT_INSN_SIZE 6
8ec7bf478SMartin Schwidefsky
95d360a75SHeiko Carstens #ifndef __ASSEMBLY__
10dfd9f7abSHeiko Carstens
116e042492SArnd Bergmann #ifdef CONFIG_CC_IS_CLANG
126e042492SArnd Bergmann /* https://bugs.llvm.org/show_bug.cgi?id=41424 */
136e042492SArnd Bergmann #define ftrace_return_address(n) 0UL
146e042492SArnd Bergmann #else
15dcddba96SHeiko Carstens #define ftrace_return_address(n) __builtin_return_address(n)
166e042492SArnd Bergmann #endif
177eed2e09SHeiko Carstens
18c933146aSHeiko Carstens void ftrace_caller(void);
19c933146aSHeiko Carstens
20f8c26027SVasily Gorbik extern void *ftrace_func;
21dfd9f7abSHeiko Carstens
22dfd9f7abSHeiko Carstens struct dyn_arch_ftrace { };
23dfd9f7abSHeiko Carstens
24c9343637SVasily Gorbik #define MCOUNT_ADDR 0
25c933146aSHeiko Carstens #define FTRACE_ADDR ((unsigned long)ftrace_caller)
26dfd9f7abSHeiko Carstens
27c933146aSHeiko Carstens #define KPROBE_ON_FTRACE_NOP 0
28c933146aSHeiko Carstens #define KPROBE_ON_FTRACE_CALL 1
295d360a75SHeiko Carstens
30c9343637SVasily Gorbik struct module;
31c9343637SVasily Gorbik struct dyn_ftrace;
32de5012b4SIlya Leoshkevich
33de5012b4SIlya Leoshkevich bool ftrace_need_init_nop(void);
34de5012b4SIlya Leoshkevich #define ftrace_need_init_nop ftrace_need_init_nop
35de5012b4SIlya Leoshkevich
36de5012b4SIlya Leoshkevich int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
37c9343637SVasily Gorbik #define ftrace_init_nop ftrace_init_nop
38c9343637SVasily Gorbik
ftrace_call_adjust(unsigned long addr)39dfd9f7abSHeiko Carstens static inline unsigned long ftrace_call_adjust(unsigned long addr)
40dfd9f7abSHeiko Carstens {
41f2963886SMartin Schwidefsky return addr;
42dfd9f7abSHeiko Carstens }
43dfd9f7abSHeiko Carstens
445740a7c7SHeiko Carstens struct ftrace_regs {
455740a7c7SHeiko Carstens struct pt_regs regs;
465740a7c7SHeiko Carstens };
475740a7c7SHeiko Carstens
arch_ftrace_get_regs(struct ftrace_regs * fregs)485740a7c7SHeiko Carstens static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
495740a7c7SHeiko Carstens {
501389f179SHeiko Carstens struct pt_regs *regs = &fregs->regs;
511389f179SHeiko Carstens
521389f179SHeiko Carstens if (test_pt_regs_flag(regs, PIF_FTRACE_FULL_REGS))
531389f179SHeiko Carstens return regs;
541389f179SHeiko Carstens return NULL;
555740a7c7SHeiko Carstens }
565740a7c7SHeiko Carstens
57*1256e70aSSven Schnelle #ifdef CONFIG_FUNCTION_GRAPH_TRACER
58*1256e70aSSven Schnelle struct fgraph_ret_regs {
59*1256e70aSSven Schnelle unsigned long gpr2;
60*1256e70aSSven Schnelle unsigned long fp;
61*1256e70aSSven Schnelle };
62*1256e70aSSven Schnelle
fgraph_ret_regs_return_value(struct fgraph_ret_regs * ret_regs)63*1256e70aSSven Schnelle static __always_inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
64*1256e70aSSven Schnelle {
65*1256e70aSSven Schnelle return ret_regs->gpr2;
66*1256e70aSSven Schnelle }
67*1256e70aSSven Schnelle
fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs * ret_regs)68*1256e70aSSven Schnelle static __always_inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
69*1256e70aSSven Schnelle {
70*1256e70aSSven Schnelle return ret_regs->fp;
71*1256e70aSSven Schnelle }
72*1256e70aSSven Schnelle #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
73*1256e70aSSven Schnelle
7494d095ffSMark Rutland static __always_inline unsigned long
ftrace_regs_get_instruction_pointer(const struct ftrace_regs * fregs)7594d095ffSMark Rutland ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs)
7694d095ffSMark Rutland {
7794d095ffSMark Rutland return fregs->regs.psw.addr;
7894d095ffSMark Rutland }
7994d095ffSMark Rutland
800ef86097SMark Rutland static __always_inline void
ftrace_regs_set_instruction_pointer(struct ftrace_regs * fregs,unsigned long ip)810ef86097SMark Rutland ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
82176510ebSHeiko Carstens unsigned long ip)
83176510ebSHeiko Carstens {
841389f179SHeiko Carstens fregs->regs.psw.addr = ip;
85176510ebSHeiko Carstens }
86176510ebSHeiko Carstens
8794d095ffSMark Rutland #define ftrace_regs_get_argument(fregs, n) \
8894d095ffSMark Rutland regs_get_kernel_argument(&(fregs)->regs, n)
8994d095ffSMark Rutland #define ftrace_regs_get_stack_pointer(fregs) \
9094d095ffSMark Rutland kernel_stack_pointer(&(fregs)->regs)
9194d095ffSMark Rutland #define ftrace_regs_return_value(fregs) \
9294d095ffSMark Rutland regs_return_value(&(fregs)->regs)
9394d095ffSMark Rutland #define ftrace_regs_set_return_value(fregs, ret) \
9494d095ffSMark Rutland regs_set_return_value(&(fregs)->regs, ret)
9594d095ffSMark Rutland #define ftrace_override_function_with_return(fregs) \
9694d095ffSMark Rutland override_function_with_return(&(fregs)->regs)
9794d095ffSMark Rutland #define ftrace_regs_query_register_offset(name) \
9894d095ffSMark Rutland regs_query_register_offset(name)
9994d095ffSMark Rutland
1009705bc70SMark Rutland #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
101fb8bfca0SHeiko Carstens /*
1022ab3a0a9SHeiko Carstens * When an ftrace registered caller is tracing a function that is
1032ab3a0a9SHeiko Carstens * also set by a register_ftrace_direct() call, it needs to be
1042ab3a0a9SHeiko Carstens * differentiated in the ftrace_caller trampoline. To do this,
1052ab3a0a9SHeiko Carstens * place the direct caller in the ORIG_GPR2 part of pt_regs. This
1062ab3a0a9SHeiko Carstens * tells the ftrace_caller that there's a direct caller.
1072ab3a0a9SHeiko Carstens */
arch_ftrace_set_direct_caller(struct ftrace_regs * fregs,unsigned long addr)1089705bc70SMark Rutland static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
1092ab3a0a9SHeiko Carstens {
1109705bc70SMark Rutland struct pt_regs *regs = &fregs->regs;
1112ab3a0a9SHeiko Carstens regs->orig_gpr2 = addr;
1122ab3a0a9SHeiko Carstens }
1139705bc70SMark Rutland #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
1142ab3a0a9SHeiko Carstens
1152ab3a0a9SHeiko Carstens /*
116fb8bfca0SHeiko Carstens * Even though the system call numbers are identical for s390/s390x a
117fb8bfca0SHeiko Carstens * different system call table is used for compat tasks. This may lead
118fb8bfca0SHeiko Carstens * to e.g. incorrect or missing trace event sysfs files.
119fb8bfca0SHeiko Carstens * Therefore simply do not trace compat system calls at all.
120fb8bfca0SHeiko Carstens * See kernel/trace/trace_syscalls.c.
121fb8bfca0SHeiko Carstens */
122fb8bfca0SHeiko Carstens #define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
arch_trace_is_compat_syscall(struct pt_regs * regs)123fb8bfca0SHeiko Carstens static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
124fb8bfca0SHeiko Carstens {
125fb8bfca0SHeiko Carstens return is_compat_task();
126fb8bfca0SHeiko Carstens }
127fb8bfca0SHeiko Carstens
128fb8bfca0SHeiko Carstens #define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
arch_syscall_match_sym_name(const char * sym,const char * name)129fb8bfca0SHeiko Carstens static inline bool arch_syscall_match_sym_name(const char *sym,
130fb8bfca0SHeiko Carstens const char *name)
131fb8bfca0SHeiko Carstens {
132fb8bfca0SHeiko Carstens /*
133fb8bfca0SHeiko Carstens * Skip __s390_ and __s390x_ prefix - due to compat wrappers
134fb8bfca0SHeiko Carstens * and aliasing some symbols of 64 bit system call functions
135fb8bfca0SHeiko Carstens * may get the __s390_ prefix instead of the __s390x_ prefix.
136fb8bfca0SHeiko Carstens */
137fb8bfca0SHeiko Carstens return !strcmp(sym + 7, name) || !strcmp(sym + 8, name);
138fb8bfca0SHeiko Carstens }
139fb8bfca0SHeiko Carstens
140dfd9f7abSHeiko Carstens #endif /* __ASSEMBLY__ */
141f768a20cSSven Schnelle
142f768a20cSSven Schnelle #ifdef CONFIG_FUNCTION_TRACER
143f768a20cSSven Schnelle
144f768a20cSSven Schnelle #define FTRACE_NOP_INSN .word 0xc004, 0x0000, 0x0000 /* brcl 0,0 */
145f768a20cSSven Schnelle
146f768a20cSSven Schnelle #ifndef CC_USING_HOTPATCH
147f768a20cSSven Schnelle
148f768a20cSSven Schnelle #define FTRACE_GEN_MCOUNT_RECORD(name) \
149f768a20cSSven Schnelle .section __mcount_loc, "a", @progbits; \
150f768a20cSSven Schnelle .quad name; \
151f768a20cSSven Schnelle .previous;
152f768a20cSSven Schnelle
153f768a20cSSven Schnelle #else /* !CC_USING_HOTPATCH */
154f768a20cSSven Schnelle
155f768a20cSSven Schnelle #define FTRACE_GEN_MCOUNT_RECORD(name)
156f768a20cSSven Schnelle
157f768a20cSSven Schnelle #endif /* !CC_USING_HOTPATCH */
158f768a20cSSven Schnelle
159f768a20cSSven Schnelle #define FTRACE_GEN_NOP_ASM(name) \
160f768a20cSSven Schnelle FTRACE_GEN_MCOUNT_RECORD(name) \
161f768a20cSSven Schnelle FTRACE_NOP_INSN
162f768a20cSSven Schnelle
163f768a20cSSven Schnelle #else /* CONFIG_FUNCTION_TRACER */
164f768a20cSSven Schnelle
165f768a20cSSven Schnelle #define FTRACE_GEN_NOP_ASM(name)
166f768a20cSSven Schnelle
167f768a20cSSven Schnelle #endif /* CONFIG_FUNCTION_TRACER */
168f768a20cSSven Schnelle
1695d360a75SHeiko Carstens #endif /* _ASM_S390_FTRACE_H */
170