ftrace/x86: Add a counter to test function_graph with direct

As testing for direct calls from the function graph tracer adds a little
overhead (which is a lot when tracing every function), add a counter that
can be used to test if function_graph tracer needs to test for a direct
caller or not.

It would have been nicer if we could use a static branch, but the static
branch logic fails when used within the function graph tracer trampoline.
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent 562955fe
...@@ -1049,10 +1049,12 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent, ...@@ -1049,10 +1049,12 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
* return address is actually off by one word, and we * return address is actually off by one word, and we
* need to adjust for that. * need to adjust for that.
*/ */
if (ftrace_direct_func_count) {
if (ftrace_find_direct_func(self_addr + MCOUNT_INSN_SIZE)) { if (ftrace_find_direct_func(self_addr + MCOUNT_INSN_SIZE)) {
self_addr = *parent; self_addr = *parent;
parent++; parent++;
} }
}
/* /*
* Protect against fault, even if it shouldn't * Protect against fault, even if it shouldn't
......
...@@ -247,10 +247,12 @@ static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { ...@@ -247,10 +247,12 @@ static inline void ftrace_free_mem(struct module *mod, void *start, void *end) {
#endif /* CONFIG_FUNCTION_TRACER */ #endif /* CONFIG_FUNCTION_TRACER */
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
extern int ftrace_direct_func_count;
int register_ftrace_direct(unsigned long ip, unsigned long addr); int register_ftrace_direct(unsigned long ip, unsigned long addr);
int unregister_ftrace_direct(unsigned long ip, unsigned long addr); int unregister_ftrace_direct(unsigned long ip, unsigned long addr);
struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr); struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr);
#else #else
# define ftrace_direct_func_count 0
static inline int register_ftrace_direct(unsigned long ip, unsigned long addr) static inline int register_ftrace_direct(unsigned long ip, unsigned long addr)
{ {
return -ENODEV; return -ENODEV;
......
...@@ -2364,6 +2364,7 @@ ftrace_find_tramp_ops_new(struct dyn_ftrace *rec) ...@@ -2364,6 +2364,7 @@ ftrace_find_tramp_ops_new(struct dyn_ftrace *rec)
/* Protected by rcu_tasks for reading, and direct_mutex for writing */ /* Protected by rcu_tasks for reading, and direct_mutex for writing */
static struct ftrace_hash *direct_functions = EMPTY_HASH; static struct ftrace_hash *direct_functions = EMPTY_HASH;
static DEFINE_MUTEX(direct_mutex); static DEFINE_MUTEX(direct_mutex);
int ftrace_direct_func_count;
/* /*
* Search the direct_functions hash to see if the given instruction pointer * Search the direct_functions hash to see if the given instruction pointer
...@@ -5056,6 +5057,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr) ...@@ -5056,6 +5057,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
direct->addr = addr; direct->addr = addr;
direct->count = 0; direct->count = 0;
list_add_rcu(&direct->next, &ftrace_direct_funcs); list_add_rcu(&direct->next, &ftrace_direct_funcs);
ftrace_direct_func_count++;
} }
entry->ip = ip; entry->ip = ip;
...@@ -5081,6 +5083,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr) ...@@ -5081,6 +5083,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
if (free_hash) if (free_hash)
free_ftrace_hash(free_hash); free_ftrace_hash(free_hash);
free_hash = NULL; free_hash = NULL;
ftrace_direct_func_count--;
} }
} else { } else {
if (!direct->count) if (!direct->count)
...@@ -5141,6 +5144,7 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr) ...@@ -5141,6 +5144,7 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
list_del_rcu(&direct->next); list_del_rcu(&direct->next);
synchronize_rcu_tasks(); synchronize_rcu_tasks();
kfree(direct); kfree(direct);
ftrace_direct_func_count--;
} }
} }
out_unlock: out_unlock:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment