0
     'Å0Ç¿Ñ     )ˆÐÏ„e÷sÎ¿Ñ ?÷     )/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Ftrace header.  For implementation details beyond the random comments
 * scattered below, see: Documentation/trace/ftrace-design.rst
 */

#ifndef _LINUX_FTRACE_H
#define _LINUX_FTRACE_H

#include <linux/trace_recursion.h>
#include <linux/trace_clock.h>
#include <linux/kallsyms.h>
#include <linux/linkage.h>
#include <linux/bitops.h>
#include <linux/ptrace.h>
#include <linux/ktime.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/fs.h>

#include <asm/ftrace.h>

/*
 * If the arch supports passing the variable contents of
 * function_trace_op as the third parameter back from the
 * mcount call, then the arch should define this as 1.
 */
#ifndef ARCH_SUPPORTS_FTRACE_OPS
#define ARCH_SUPPORTS_FTRACE_OPS 0
#endif

struct ftrace_ops;
struct ftrace_regs;
struct dyn_ftrace;

#ifdef CONFIG_FUNCTION_TRACER
/*
 * If the arch's mcount caller does not support all of ftrace's
 * features, then it must call an indirect function that
 * does. Or at least does enough to prevent any unwelcome side effects.
 *
 * Also define the function prototype that these architectures use
 * to call the ftrace_ops_list_func().
 */
#if !ARCH_SUPPORTS_FTRACE_OPS
# define FTRACE_FORCE_LIST_FUNC 1
void arch_ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip);
#else
# define FTRACE_FORCE_LIST_FUNC 0
void arch_ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
			       struct ftrace_ops *op, struct ftrace_regs *fregs);
#endif
extern const struct ftrace_ops ftrace_nop_ops;
extern const struct ftrace_ops ftrace_list_ops;
struct ftrace_ops *ftrace_find_unique_ops(struct dyn_ftrace *rec);
#endif /* CONFIG_FUNCTION_TRACER */

/* Main tracing buffer and events set up */
#ifdef CONFIG_TRACING
void trace_init(void);
void early_trace_init(void);
#else
static inline void trace_init(void) { }
static inline void early_trace_init(void) { }
#endif

struct module;
struct ftrace_hash;

#if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_MODULES) && \
	defined(CONFIG_DYNAMIC_FTRACE)
const char *
ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
		   unsigned long *off, char **modname, char *sym);
#else
static inline const char *
ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
		   unsigned long *off, char **modname, char *sym)
{
	return NULL;
}
#endif

#if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_DYNAMIC_FTRACE)
int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value,
			   char *type, char *name,
			   char *module_name, int *exported);
#else
static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value,
					 char *type, char *name,
					 char *module_name, int *exported)
{
	return -1;
}
#endif

#ifdef CONFIG_FUNCTION_TRACER

extern int ftrace_enabled;
extern int
ftrace_enable_sysctl(struct ctl_table *table, int write,
		     void *buffer, size_t *lenp, loff_t *ppos);

#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS

struct ftrace_regs {
	struct pt_regs		regs;
};
#define arch_ftrace_get_regs(fregs) (&(fregs)->regs)

/*
 * ftrace_regs_set_instruction_pointer() is to be defined by the architecture
 * if to allow setting of the instruction pointer from the ftrace_regs when
 * HAVE_DYNAMIC_FTRACE_WITH_ARGS is set and it supports live kernel patching.
 */
#define ftrace_regs_set_instruction_pointer(fregs, ip) do { } while (0)
#endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS */

static __always_inline struct pt_regs *ftrace_get_regs(struct ftrace_regs *fregs)
{
	if (!fregs)
		return NULL;

	return arch_ftrace_get_regs(fregs);
}

/*
 * When true, the ftrace_regs_{get,set}_*() functions may be used on fregs.
 * Note: this can be true even when ftrace_get_regs() cannot provide a pt_regs.
 */
static __always_inline bool ftrace_regs_has_args(struct ftrace_regs *fregs)
{
	if (IS_ENABLED(CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS))
		return true;

	return ftrace_get_regs(fregs) != NULL;
}

#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
#define ftrace_regs_get_