xref: /linux/arch/s390/include/asm/ftrace.h (revision e5eb28f6d1afebed4bb7d740a797d0390bd3a357)
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 ARCH_SUPPORTS_FTRACE_OPS 1
6c9343637SVasily Gorbik #define MCOUNT_INSN_SIZE	6
7c9343637SVasily Gorbik 
8ec7bf478SMartin Schwidefsky #ifndef __ASSEMBLER__
95d360a75SHeiko Carstens #include <asm/stacktrace.h>
10dfd9f7abSHeiko Carstens 
return_address(unsigned int n)116e042492SArnd Bergmann static __always_inline unsigned long return_address(unsigned int n)
12*2947a456SNathan Chancellor {
136e042492SArnd Bergmann 	struct stack_frame *sf;
146e042492SArnd Bergmann 
15dcddba96SHeiko Carstens 	if (!n)
166e042492SArnd Bergmann 		return (unsigned long)__builtin_return_address(0);
177eed2e09SHeiko Carstens 
18c933146aSHeiko Carstens 	sf = (struct stack_frame *)current_frame_address();
19c933146aSHeiko Carstens 	do {
20f8c26027SVasily Gorbik 		sf = (struct stack_frame *)sf->back_chain;
21dfd9f7abSHeiko Carstens 		if (!sf)
22dfd9f7abSHeiko Carstens 			return 0;
23dfd9f7abSHeiko Carstens 	} while (--n);
24c9343637SVasily Gorbik 	return sf->gprs[8];
25c933146aSHeiko Carstens }
26dfd9f7abSHeiko Carstens #define ftrace_return_address(n) return_address(n)
27c933146aSHeiko Carstens 
28c933146aSHeiko Carstens void ftrace_caller(void);
295d360a75SHeiko Carstens 
30c9343637SVasily Gorbik extern void *ftrace_func;
31c9343637SVasily Gorbik 
32de5012b4SIlya Leoshkevich struct dyn_arch_ftrace { };
33de5012b4SIlya Leoshkevich 
34de5012b4SIlya Leoshkevich #define MCOUNT_ADDR 0
35de5012b4SIlya Leoshkevich #define FTRACE_ADDR ((unsigned long)ftrace_caller)
36de5012b4SIlya Leoshkevich 
37c9343637SVasily Gorbik #define KPROBE_ON_FTRACE_NOP	0
38c9343637SVasily Gorbik #define KPROBE_ON_FTRACE_CALL	1
39dfd9f7abSHeiko Carstens 
40dfd9f7abSHeiko Carstens struct module;
41f2963886SMartin Schwidefsky struct dyn_ftrace;
42dfd9f7abSHeiko Carstens struct ftrace_ops;
43dfd9f7abSHeiko Carstens 
445740a7c7SHeiko Carstens bool ftrace_need_init_nop(void);
455740a7c7SHeiko Carstens #define ftrace_need_init_nop ftrace_need_init_nop
465740a7c7SHeiko Carstens 
475740a7c7SHeiko Carstens int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
485740a7c7SHeiko Carstens #define ftrace_init_nop ftrace_init_nop
495740a7c7SHeiko Carstens 
ftrace_call_adjust(unsigned long addr)501389f179SHeiko Carstens static inline unsigned long ftrace_call_adjust(unsigned long addr)
511389f179SHeiko Carstens {
521389f179SHeiko Carstens 	return addr;
531389f179SHeiko Carstens }
541389f179SHeiko Carstens #define ftrace_get_symaddr(fentry_ip) ((unsigned long)(fentry_ip))
555740a7c7SHeiko Carstens 
565740a7c7SHeiko Carstens #include <linux/ftrace_regs.h>
571256e70aSSven Schnelle 
arch_ftrace_get_regs(struct ftrace_regs * fregs)581256e70aSSven Schnelle static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
591256e70aSSven Schnelle {
601256e70aSSven Schnelle 	struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
611256e70aSSven Schnelle 
621256e70aSSven Schnelle 	if (test_pt_regs_flag(regs, PIF_FTRACE_FULL_REGS))
631256e70aSSven Schnelle 		return regs;
641256e70aSSven Schnelle 	return NULL;
651256e70aSSven Schnelle }
661256e70aSSven Schnelle 
671256e70aSSven Schnelle static __always_inline void
ftrace_regs_set_instruction_pointer(struct ftrace_regs * fregs,unsigned long ip)681256e70aSSven Schnelle ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
691256e70aSSven Schnelle 				    unsigned long ip)
701256e70aSSven Schnelle {
711256e70aSSven Schnelle 	arch_ftrace_regs(fregs)->regs.psw.addr = ip;
721256e70aSSven Schnelle }
731256e70aSSven Schnelle 
7494d095ffSMark Rutland #undef ftrace_regs_get_frame_pointer
7594d095ffSMark Rutland static __always_inline unsigned long
ftrace_regs_get_frame_pointer(struct ftrace_regs * fregs)7694d095ffSMark Rutland ftrace_regs_get_frame_pointer(struct ftrace_regs *fregs)
7794d095ffSMark Rutland {
7894d095ffSMark Rutland 	return ftrace_regs_get_stack_pointer(fregs);
7994d095ffSMark Rutland }
800ef86097SMark Rutland 
810ef86097SMark Rutland static __always_inline unsigned long
ftrace_regs_get_return_address(const struct ftrace_regs * fregs)82176510ebSHeiko Carstens ftrace_regs_get_return_address(const struct ftrace_regs *fregs)
83176510ebSHeiko Carstens {
841389f179SHeiko Carstens 	return arch_ftrace_regs(fregs)->regs.gprs[14];
85176510ebSHeiko Carstens }
86176510ebSHeiko Carstens 
8794d095ffSMark Rutland #define arch_ftrace_fill_perf_regs(fregs, _regs)	 do {		\
8894d095ffSMark Rutland 		(_regs)->psw.mask = 0;					\
8994d095ffSMark Rutland 		(_regs)->psw.addr = arch_ftrace_regs(fregs)->regs.psw.addr;		\
9094d095ffSMark Rutland 		(_regs)->gprs[15] = arch_ftrace_regs(fregs)->regs.gprs[15];		\
9194d095ffSMark Rutland 	} while (0)
9294d095ffSMark Rutland 
9394d095ffSMark Rutland #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
9494d095ffSMark Rutland /*
9594d095ffSMark Rutland  * When an ftrace registered caller is tracing a function that is
9694d095ffSMark Rutland  * also set by a register_ftrace_direct() call, it needs to be
9794d095ffSMark Rutland  * differentiated in the ftrace_caller trampoline. To do this,
9894d095ffSMark Rutland  * place the direct caller in the ORIG_GPR2 part of pt_regs. This
9994d095ffSMark Rutland  * tells the ftrace_caller that there's a direct caller.
1009705bc70SMark Rutland  */
arch_ftrace_set_direct_caller(struct ftrace_regs * fregs,unsigned long addr)101fb8bfca0SHeiko Carstens static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
1022ab3a0a9SHeiko Carstens {
1032ab3a0a9SHeiko Carstens 	struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
1042ab3a0a9SHeiko Carstens 	regs->orig_gpr2 = addr;
1052ab3a0a9SHeiko Carstens }
1062ab3a0a9SHeiko Carstens #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
1072ab3a0a9SHeiko Carstens 
1089705bc70SMark Rutland /*
1092ab3a0a9SHeiko Carstens  * Even though the system call numbers are identical for s390/s390x a
1109705bc70SMark Rutland  * different system call table is used for compat tasks. This may lead
1112ab3a0a9SHeiko Carstens  * to e.g. incorrect or missing trace event sysfs files.
1122ab3a0a9SHeiko Carstens  * Therefore simply do not trace compat system calls at all.
1139705bc70SMark Rutland  * See kernel/trace/trace_syscalls.c.
1142ab3a0a9SHeiko Carstens  */
1152ab3a0a9SHeiko Carstens #define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
arch_trace_is_compat_syscall(struct pt_regs * regs)116fb8bfca0SHeiko Carstens static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
117fb8bfca0SHeiko Carstens {
118fb8bfca0SHeiko Carstens 	return is_compat_task();
119fb8bfca0SHeiko Carstens }
120fb8bfca0SHeiko Carstens 
121fb8bfca0SHeiko Carstens #define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
arch_syscall_match_sym_name(const char * sym,const char * name)122fb8bfca0SHeiko Carstens static inline bool arch_syscall_match_sym_name(const char *sym,
123fb8bfca0SHeiko Carstens 					       const char *name)
124fb8bfca0SHeiko Carstens {
125fb8bfca0SHeiko Carstens 	/*
126fb8bfca0SHeiko Carstens 	 * Skip __s390_ and __s390x_ prefix - due to compat wrappers
127fb8bfca0SHeiko Carstens 	 * and aliasing some symbols of 64 bit system call functions
128fb8bfca0SHeiko Carstens 	 * may get the __s390_ prefix instead of the __s390x_ prefix.
129fb8bfca0SHeiko Carstens 	 */
130fb8bfca0SHeiko Carstens 	return !strcmp(sym + 7, name) || !strcmp(sym + 8, name);
131fb8bfca0SHeiko Carstens }
132fb8bfca0SHeiko Carstens 
133fb8bfca0SHeiko Carstens void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
134fb8bfca0SHeiko Carstens 		       struct ftrace_ops *op, struct ftrace_regs *fregs);
135fb8bfca0SHeiko Carstens #define ftrace_graph_func ftrace_graph_func
136fb8bfca0SHeiko Carstens 
137fb8bfca0SHeiko Carstens #endif /* __ASSEMBLER__ */
138fb8bfca0SHeiko Carstens 
139fb8bfca0SHeiko Carstens #ifdef CONFIG_FUNCTION_TRACER
140dfd9f7abSHeiko Carstens 
141f768a20cSSven Schnelle #define FTRACE_NOP_INSN .word 0xc004, 0x0000, 0x0000 /* brcl 0,0 */
142f768a20cSSven Schnelle 
143f768a20cSSven Schnelle #ifndef CC_USING_HOTPATCH
144f768a20cSSven Schnelle 
145f768a20cSSven Schnelle #define FTRACE_GEN_MCOUNT_RECORD(name)		\
146f768a20cSSven Schnelle 	.section __mcount_loc, "a", @progbits;	\
147f768a20cSSven Schnelle 	.quad name;				\
148f768a20cSSven Schnelle 	.previous;
149f768a20cSSven Schnelle 
150f768a20cSSven Schnelle #else /* !CC_USING_HOTPATCH */
151f768a20cSSven Schnelle 
152f768a20cSSven Schnelle #define FTRACE_GEN_MCOUNT_RECORD(name)
153f768a20cSSven Schnelle 
154f768a20cSSven Schnelle #endif /* !CC_USING_HOTPATCH */
155f768a20cSSven Schnelle 
156f768a20cSSven Schnelle #define FTRACE_GEN_NOP_ASM(name)		\
157f768a20cSSven Schnelle 	FTRACE_GEN_MCOUNT_RECORD(name)		\
158f768a20cSSven Schnelle 	FTRACE_NOP_INSN
159f768a20cSSven Schnelle 
160f768a20cSSven Schnelle #else /* CONFIG_FUNCTION_TRACER */
161f768a20cSSven Schnelle 
162f768a20cSSven Schnelle #define FTRACE_GEN_NOP_ASM(name)
163f768a20cSSven Schnelle 
164f768a20cSSven Schnelle #endif /* CONFIG_FUNCTION_TRACER */
165f768a20cSSven Schnelle 
166f768a20cSSven Schnelle #endif /* _ASM_S390_FTRACE_H */
167f768a20cSSven Schnelle