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