xref: /openbmc/linux/arch/s390/include/asm/ftrace.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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