18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_S390_FTRACE_H
38c2ecf20Sopenharmony_ci#define _ASM_S390_FTRACE_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#define ARCH_SUPPORTS_FTRACE_OPS 1
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
88c2ecf20Sopenharmony_ci#define MCOUNT_INSN_SIZE	6
98c2ecf20Sopenharmony_ci#else
108c2ecf20Sopenharmony_ci#define MCOUNT_INSN_SIZE	24
118c2ecf20Sopenharmony_ci#define MCOUNT_RETURN_FIXUP	18
128c2ecf20Sopenharmony_ci#endif
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#ifdef CONFIG_CC_IS_CLANG
198c2ecf20Sopenharmony_ci/* https://bugs.llvm.org/show_bug.cgi?id=41424 */
208c2ecf20Sopenharmony_ci#define ftrace_return_address(n) 0UL
218c2ecf20Sopenharmony_ci#else
228c2ecf20Sopenharmony_ci#define ftrace_return_address(n) __builtin_return_address(n)
238c2ecf20Sopenharmony_ci#endif
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_civoid _mcount(void);
268c2ecf20Sopenharmony_civoid ftrace_caller(void);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciextern char ftrace_graph_caller_end;
298c2ecf20Sopenharmony_ciextern unsigned long ftrace_plt;
308c2ecf20Sopenharmony_ciextern void *ftrace_func;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistruct dyn_arch_ftrace { };
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define MCOUNT_ADDR ((unsigned long)_mcount)
358c2ecf20Sopenharmony_ci#define FTRACE_ADDR ((unsigned long)ftrace_caller)
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define KPROBE_ON_FTRACE_NOP	0
388c2ecf20Sopenharmony_ci#define KPROBE_ON_FTRACE_CALL	1
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic inline unsigned long ftrace_call_adjust(unsigned long addr)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	return addr;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistruct ftrace_insn {
468c2ecf20Sopenharmony_ci	u16 opc;
478c2ecf20Sopenharmony_ci	s32 disp;
488c2ecf20Sopenharmony_ci} __packed;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic inline void ftrace_generate_nop_insn(struct ftrace_insn *insn)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci#ifdef CONFIG_FUNCTION_TRACER
538c2ecf20Sopenharmony_ci#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
548c2ecf20Sopenharmony_ci	/* brcl 0,0 */
558c2ecf20Sopenharmony_ci	insn->opc = 0xc004;
568c2ecf20Sopenharmony_ci	insn->disp = 0;
578c2ecf20Sopenharmony_ci#else
588c2ecf20Sopenharmony_ci	/* jg .+24 */
598c2ecf20Sopenharmony_ci	insn->opc = 0xc0f4;
608c2ecf20Sopenharmony_ci	insn->disp = MCOUNT_INSN_SIZE / 2;
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci#endif
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic inline int is_ftrace_nop(struct ftrace_insn *insn)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci#ifdef CONFIG_FUNCTION_TRACER
688c2ecf20Sopenharmony_ci#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
698c2ecf20Sopenharmony_ci	if (insn->disp == 0)
708c2ecf20Sopenharmony_ci		return 1;
718c2ecf20Sopenharmony_ci#else
728c2ecf20Sopenharmony_ci	if (insn->disp == MCOUNT_INSN_SIZE / 2)
738c2ecf20Sopenharmony_ci		return 1;
748c2ecf20Sopenharmony_ci#endif
758c2ecf20Sopenharmony_ci#endif
768c2ecf20Sopenharmony_ci	return 0;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic inline void ftrace_generate_call_insn(struct ftrace_insn *insn,
808c2ecf20Sopenharmony_ci					     unsigned long ip)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci#ifdef CONFIG_FUNCTION_TRACER
838c2ecf20Sopenharmony_ci	unsigned long target;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	/* brasl r0,ftrace_caller */
868c2ecf20Sopenharmony_ci	target = is_module_addr((void *) ip) ? ftrace_plt : FTRACE_ADDR;
878c2ecf20Sopenharmony_ci	insn->opc = 0xc005;
888c2ecf20Sopenharmony_ci	insn->disp = (target - ip) / 2;
898c2ecf20Sopenharmony_ci#endif
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci/*
938c2ecf20Sopenharmony_ci * Even though the system call numbers are identical for s390/s390x a
948c2ecf20Sopenharmony_ci * different system call table is used for compat tasks. This may lead
958c2ecf20Sopenharmony_ci * to e.g. incorrect or missing trace event sysfs files.
968c2ecf20Sopenharmony_ci * Therefore simply do not trace compat system calls at all.
978c2ecf20Sopenharmony_ci * See kernel/trace/trace_syscalls.c.
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_ci#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
1008c2ecf20Sopenharmony_cistatic inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	return is_compat_task();
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
1068c2ecf20Sopenharmony_cistatic inline bool arch_syscall_match_sym_name(const char *sym,
1078c2ecf20Sopenharmony_ci					       const char *name)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	/*
1108c2ecf20Sopenharmony_ci	 * Skip __s390_ and __s390x_ prefix - due to compat wrappers
1118c2ecf20Sopenharmony_ci	 * and aliasing some symbols of 64 bit system call functions
1128c2ecf20Sopenharmony_ci	 * may get the __s390_ prefix instead of the __s390x_ prefix.
1138c2ecf20Sopenharmony_ci	 */
1148c2ecf20Sopenharmony_ci	return !strcmp(sym + 7, name) || !strcmp(sym + 8, name);
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
1188c2ecf20Sopenharmony_ci#endif /* _ASM_S390_FTRACE_H */
119