18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/* Copyright (C) 2017 Andes Technology Corporation */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#ifndef _ASM_RISCV_FTRACE_H
58c2ecf20Sopenharmony_ci#define _ASM_RISCV_FTRACE_H
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci/*
88c2ecf20Sopenharmony_ci * The graph frame test is not possible if CONFIG_FRAME_POINTER is not enabled.
98c2ecf20Sopenharmony_ci * Check arch/riscv/kernel/mcount.S for detail.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci#if defined(CONFIG_FUNCTION_GRAPH_TRACER) && defined(CONFIG_FRAME_POINTER)
128c2ecf20Sopenharmony_ci#define HAVE_FUNCTION_GRAPH_FP_TEST
138c2ecf20Sopenharmony_ci#endif
148c2ecf20Sopenharmony_ci#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/*
178c2ecf20Sopenharmony_ci * Clang prior to 13 had "mcount" instead of "_mcount":
188c2ecf20Sopenharmony_ci * https://reviews.llvm.org/D98881
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci#if defined(CONFIG_CC_IS_GCC) || CONFIG_CLANG_VERSION >= 130000
218c2ecf20Sopenharmony_ci#define MCOUNT_NAME _mcount
228c2ecf20Sopenharmony_ci#else
238c2ecf20Sopenharmony_ci#define MCOUNT_NAME mcount
248c2ecf20Sopenharmony_ci#endif
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define ARCH_SUPPORTS_FTRACE_OPS 1
278c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
288c2ecf20Sopenharmony_civoid MCOUNT_NAME(void);
298c2ecf20Sopenharmony_cistatic inline unsigned long ftrace_call_adjust(unsigned long addr)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	return addr;
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistruct dyn_arch_ftrace {
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci#endif
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#ifdef CONFIG_DYNAMIC_FTRACE
398c2ecf20Sopenharmony_ci/*
408c2ecf20Sopenharmony_ci * A general call in RISC-V is a pair of insts:
418c2ecf20Sopenharmony_ci * 1) auipc: setting high-20 pc-related bits to ra register
428c2ecf20Sopenharmony_ci * 2) jalr: setting low-12 offset to ra, jump to ra, and set ra to
438c2ecf20Sopenharmony_ci *          return address (original pc + 4)
448c2ecf20Sopenharmony_ci *
458c2ecf20Sopenharmony_ci * Dynamic ftrace generates probes to call sites, so we must deal with
468c2ecf20Sopenharmony_ci * both auipc and jalr at the same time.
478c2ecf20Sopenharmony_ci */
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define MCOUNT_ADDR		((unsigned long)MCOUNT_NAME)
508c2ecf20Sopenharmony_ci#define JALR_SIGN_MASK		(0x00000800)
518c2ecf20Sopenharmony_ci#define JALR_OFFSET_MASK	(0x00000fff)
528c2ecf20Sopenharmony_ci#define AUIPC_OFFSET_MASK	(0xfffff000)
538c2ecf20Sopenharmony_ci#define AUIPC_PAD		(0x00001000)
548c2ecf20Sopenharmony_ci#define JALR_SHIFT		20
558c2ecf20Sopenharmony_ci#define JALR_BASIC		(0x000080e7)
568c2ecf20Sopenharmony_ci#define AUIPC_BASIC		(0x00000097)
578c2ecf20Sopenharmony_ci#define NOP4			(0x00000013)
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define make_call(caller, callee, call)					\
608c2ecf20Sopenharmony_cido {									\
618c2ecf20Sopenharmony_ci	call[0] = to_auipc_insn((unsigned int)((unsigned long)callee -	\
628c2ecf20Sopenharmony_ci				(unsigned long)caller));		\
638c2ecf20Sopenharmony_ci	call[1] = to_jalr_insn((unsigned int)((unsigned long)callee -	\
648c2ecf20Sopenharmony_ci			       (unsigned long)caller));			\
658c2ecf20Sopenharmony_ci} while (0)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define to_jalr_insn(offset)						\
688c2ecf20Sopenharmony_ci	(((offset & JALR_OFFSET_MASK) << JALR_SHIFT) | JALR_BASIC)
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define to_auipc_insn(offset)						\
718c2ecf20Sopenharmony_ci	((offset & JALR_SIGN_MASK) ?					\
728c2ecf20Sopenharmony_ci	(((offset & AUIPC_OFFSET_MASK) + AUIPC_PAD) | AUIPC_BASIC) :	\
738c2ecf20Sopenharmony_ci	((offset & AUIPC_OFFSET_MASK) | AUIPC_BASIC))
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci/*
768c2ecf20Sopenharmony_ci * Let auipc+jalr be the basic *mcount unit*, so we make it 8 bytes here.
778c2ecf20Sopenharmony_ci */
788c2ecf20Sopenharmony_ci#define MCOUNT_INSN_SIZE 8
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
818c2ecf20Sopenharmony_cistruct dyn_ftrace;
828c2ecf20Sopenharmony_ciint ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
838c2ecf20Sopenharmony_ci#define ftrace_init_nop ftrace_init_nop
848c2ecf20Sopenharmony_ci#endif
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#endif /* CONFIG_DYNAMIC_FTRACE */
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci#endif /* _ASM_RISCV_FTRACE_H */
89