aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorCheng Jian <cj.chengjian@huawei.com>2019-05-04 07:39:39 -0400
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2019-05-25 23:04:43 -0400
commita124692b698b00026a58d89831ceda2331b2e1d0 (patch)
tree1634d4db5c810306171db808559b7c59637dcfcf /kernel/trace/ftrace.c
parentb6399cc789341fc49a0603fb7d388a4e50aca212 (diff)
ftrace: Enable trampoline when rec count returns back to one
Custom trampolines can only be enabled if there is only a single ops attached to it. If there's only a single callback registered to a function, and the ops has a trampoline registered for it, then we can call the trampoline directly. This is very useful for improving the performance of ftrace and livepatch. If more than one callback is registered to a function, the general trampoline is used, and the custom trampoline is not restored back to the direct call even if all the other callbacks were unregistered and we are back to one callback for the function. To fix this, set FTRACE_FL_TRAMP flag if rec count is decremented to one, and the ops that left has a trampoline. Testing After this patch : insmod livepatch_unshare_files.ko cat /sys/kernel/debug/tracing/enabled_functions unshare_files (1) R I tramp: 0xffffffffc0000000(klp_ftrace_handler+0x0/0xa0) ->ftrace_ops_assist_func+0x0/0xf0 echo unshare_files > /sys/kernel/debug/tracing/set_ftrace_filter echo function > /sys/kernel/debug/tracing/current_tracer cat /sys/kernel/debug/tracing/enabled_functions unshare_files (2) R I ->ftrace_ops_list_func+0x0/0x150 echo nop > /sys/kernel/debug/tracing/current_tracer cat /sys/kernel/debug/tracing/enabled_functions unshare_files (1) R I tramp: 0xffffffffc0000000(klp_ftrace_handler+0x0/0xa0) ->ftrace_ops_assist_func+0x0/0xf0 Link: http://lkml.kernel.org/r/1556969979-111047-1-git-send-email-cj.chengjian@huawei.com Signed-off-by: Cheng Jian <cj.chengjian@huawei.com> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 4f2c26bebe2a..5c3eadb143ed 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1622,6 +1622,11 @@ static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec)
1622 return keep_regs; 1622 return keep_regs;
1623} 1623}
1624 1624
1625static struct ftrace_ops *
1626ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
1627static struct ftrace_ops *
1628ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
1629
1625static bool __ftrace_hash_rec_update(struct ftrace_ops *ops, 1630static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
1626 int filter_hash, 1631 int filter_hash,
1627 bool inc) 1632 bool inc)
@@ -1750,15 +1755,17 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
1750 } 1755 }
1751 1756
1752 /* 1757 /*
1753 * If the rec had TRAMP enabled, then it needs to 1758 * The TRAMP needs to be set only if rec count
1754 * be cleared. As TRAMP can only be enabled iff 1759 * is decremented to one, and the ops that is
1755 * there is only a single ops attached to it. 1760 * left has a trampoline. As TRAMP can only be
1756 * In otherwords, always disable it on decrementing. 1761 * enabled if there is only a single ops attached
1757 * In the future, we may set it if rec count is 1762 * to it.
1758 * decremented to one, and the ops that is left
1759 * has a trampoline.
1760 */ 1763 */
1761 rec->flags &= ~FTRACE_FL_TRAMP; 1764 if (ftrace_rec_count(rec) == 1 &&
1765 ftrace_find_tramp_ops_any(rec))
1766 rec->flags |= FTRACE_FL_TRAMP;
1767 else
1768 rec->flags &= ~FTRACE_FL_TRAMP;
1762 1769
1763 /* 1770 /*
1764 * flags will be cleared in ftrace_check_record() 1771 * flags will be cleared in ftrace_check_record()
@@ -1951,11 +1958,6 @@ static void print_ip_ins(const char *fmt, const unsigned char *p)
1951 printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]); 1958 printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
1952} 1959}
1953 1960
1954static struct ftrace_ops *
1955ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
1956static struct ftrace_ops *
1957ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
1958
1959enum ftrace_bug_type ftrace_bug_type; 1961enum ftrace_bug_type ftrace_bug_type;
1960const void *ftrace_expected; 1962const void *ftrace_expected;
1961 1963