Commit dbaccb61 authored by Florent Revest's avatar Florent Revest Committed by Steven Rostedt (Google)
Browse files

ftrace: Store direct called addresses in their ops

All direct calls are now registered using the register_ftrace_direct API
so each ops can jump to only one direct-called trampoline.

By storing the direct called trampoline address directly in the ops we
can save one hashmap lookup in the direct call ops and implement arm64
direct calls on top of call ops.

Link: https://lkml.kernel.org/r/20230321140424.345218-6-revest@chromium.org



Signed-off-by: default avatarFlorent Revest <revest@chromium.org>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent da8bdfbd
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -321,6 +321,9 @@ struct ftrace_ops {
	unsigned long			trampoline_size;
	unsigned long			trampoline_size;
	struct list_head		list;
	struct list_head		list;
	ftrace_ops_func_t		ops_func;
	ftrace_ops_func_t		ops_func;
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
	unsigned long			direct_call;
#endif
#endif
#endif
};
};


+5 −2
Original line number Original line Diff line number Diff line
@@ -2583,9 +2583,8 @@ ftrace_add_rec_direct(unsigned long ip, unsigned long addr,
static void call_direct_funcs(unsigned long ip, unsigned long pip,
static void call_direct_funcs(unsigned long ip, unsigned long pip,
			      struct ftrace_ops *ops, struct ftrace_regs *fregs)
			      struct ftrace_ops *ops, struct ftrace_regs *fregs)
{
{
	unsigned long addr;
	unsigned long addr = READ_ONCE(ops->direct_call);


	addr = ftrace_find_rec_direct(ip);
	if (!addr)
	if (!addr)
		return;
		return;


@@ -5381,6 +5380,7 @@ int register_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
	ops->func = call_direct_funcs;
	ops->func = call_direct_funcs;
	ops->flags = MULTI_FLAGS;
	ops->flags = MULTI_FLAGS;
	ops->trampoline = FTRACE_REGS_ADDR;
	ops->trampoline = FTRACE_REGS_ADDR;
	ops->direct_call = addr;


	err = register_ftrace_function_nolock(ops);
	err = register_ftrace_function_nolock(ops);


@@ -5455,6 +5455,7 @@ __modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
	/* Enable the tmp_ops to have the same functions as the direct ops */
	/* Enable the tmp_ops to have the same functions as the direct ops */
	ftrace_ops_init(&tmp_ops);
	ftrace_ops_init(&tmp_ops);
	tmp_ops.func_hash = ops->func_hash;
	tmp_ops.func_hash = ops->func_hash;
	tmp_ops.direct_call = addr;


	err = register_ftrace_function_nolock(&tmp_ops);
	err = register_ftrace_function_nolock(&tmp_ops);
	if (err)
	if (err)
@@ -5476,6 +5477,8 @@ __modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
			entry->direct = addr;
			entry->direct = addr;
		}
		}
	}
	}
	/* Prevent store tearing if a trampoline concurrently accesses the value */
	WRITE_ONCE(ops->direct_call, addr);


	mutex_unlock(&ftrace_lock);
	mutex_unlock(&ftrace_lock);