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