tracing: Updates for 5.5
Subsystems (11)
Steven Rostedt
maintainercover tracing: Updates for 5.5
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
for-next
Head SHA1: 9b4712044d059e7842aaeeafd7c7a7ee88c589db
Andy Shevchenko (3):
lib/sort: Move swap, cmp and cmp_r function types for wider use lib/bsearch: Use generic type for comparator function
tracing: Use generic type for comparator function
Ben Dooks (1):
tracing: Make internal ftrace events static
Borislav Petkov (1):
tracing: Remove stray tab in TRACE_EVAL_MAP_FILE's help text
Divya Indi (3):
tracing: Declare newly exported APIs in include/linux/trace.h
tracing: Verify if trace array exists before destroying it.
tracing: Adding NULL checks for trace_array descriptor pointer
Joe Lawrence (2):
selftests/livepatch: Make dynamic debug setup and restore generic selftests/livepatch: Test interaction with ftrace_enabled
Josh Poimboeuf (1):
ftrace/x86: Tell objtool to ignore nondeterministic ftrace stack layout
Masami Hiramatsu (1):
tracing/kprobe: Check whether the non-suffixed symbol is notrace
Miroslav Benes (1):
ftrace: Introduce PERMANENT ftrace_ops flag
Piotr Maziarz (2):
seq_buf: Add printing formatted hex dumps
tracing: Use seq_buf_hex_dump() to dump buffers
Sebastian Andrzej Siewior (1):
tracing: Use CONFIG_PREEMPTION
Srivatsa S. Bhat (VMware) (1):
tracing/hwlat: Fix a few trivial nits
Steven Rostedt (VMware) (13):
ftrace: Separate out the copying of a ftrace_hash from __ftrace_hash_move()
ftrace: Separate out functionality from ftrace_location_range()
ftrace: Add register_ftrace_direct()
ftrace: Add ftrace_find_direct_func()
ftrace: Add sample module that uses register_ftrace_direct() ftrace/selftest: Add tests to test register_ftrace_direct()
ftrace: Add another example of register_ftrace_direct() use case ftrace/selftests: Update the direct call selftests to test two direct calls ftrace/x86: Add register_ftrace_direct() for custom trampolines ftrace/x86: Add a counter to test function_graph with direct
ftrace: Add information on number of page groups allocated
fgraph: Fix function type mismatches of ftrace_graph_return using ftrace_stub tracing/selftests: Turn off timeout setting
Viktor Rosendahl (BMW) (2):
ftrace: Implement fs notification for tracing_max_latency
preemptirq_delay_test: Add the burst feature and a sysfs trigger
Yuming Han (1):
tracing: use kvcalloc for tgid_map array allocation
----
Documentation/trace/ftrace-uses.rst | 10 +- Documentation/trace/ftrace.rst | 4 +- arch/sh/boot/compressed/misc.c | 5 + arch/x86/Kconfig | 1 + arch/x86/include/asm/ftrace.h | 13 + arch/x86/include/asm/unwind_hints.h | 8 + arch/x86/kernel/ftrace.c | 14 + arch/x86/kernel/ftrace_64.S | 42 +- include/asm-generic/vmlinux.lds.h | 17 +- include/linux/bsearch.h | 2 +- include/linux/ftrace.h | 53 ++- include/linux/seq_buf.h | 3 + include/linux/sort.h | 8 +- include/linux/trace.h | 7 + include/linux/trace_events.h | 5 + include/linux/trace_seq.h | 4 + include/linux/types.h | 5 + include/trace/trace_events.h | 6 + kernel/livepatch/patch.c | 3 +- kernel/module.c | 6 +- kernel/trace/Kconfig | 18 +- kernel/trace/fgraph.c | 11 +- kernel/trace/ftrace.c | 466 +++++++++++++++++++-- kernel/trace/preemptirq_delay_test.c | 144 ++++++- kernel/trace/trace.c | 118 +++++- kernel/trace/trace.h | 24 +- kernel/trace/trace_branch.c | 8 +- kernel/trace/trace_events.c | 2 + kernel/trace/trace_export.c | 4 +- kernel/trace/trace_hwlat.c | 15 +- kernel/trace/trace_kprobe.c | 27 +- kernel/trace/trace_output.c | 15 + kernel/trace/trace_seq.c | 30 ++ kernel/trace/trace_stat.c | 6 +- kernel/trace/trace_stat.h | 2 +- lib/bsearch.c | 2 +- lib/seq_buf.c | 62 +++ lib/sort.c | 15 +- samples/Kconfig | 8 + samples/Makefile | 1 + samples/ftrace/Makefile | 4 + samples/ftrace/ftrace-direct-too.c | 51 +++ samples/ftrace/ftrace-direct.c | 45 ++ tools/testing/selftests/ftrace/settings | 1 + .../ftrace/test.d/direct/ftrace-direct.tc | 69 +++ .../ftrace/test.d/direct/kprobe-direct.tc | 84 ++++ tools/testing/selftests/livepatch/Makefile | 3 +- tools/testing/selftests/livepatch/functions.sh | 34 +- .../testing/selftests/livepatch/test-callbacks.sh | 2 +- tools/testing/selftests/livepatch/test-ftrace.sh | 65 +++ .../testing/selftests/livepatch/test-livepatch.sh | 2 +- .../selftests/livepatch/test-shadow-vars.sh | 2 +- 52 files changed, 1410 insertions(+), 146 deletions(-) create mode 100644 samples/ftrace/Makefile create mode 100644 samples/ftrace/ftrace-direct-too.c create mode 100644 samples/ftrace/ftrace-direct.c create mode 100644 tools/testing/selftests/ftrace/settings create mode 100644 tools/testing/selftests/ftrace/test.d/direct/ftrace-direct.tc create mode 100644 tools/testing/selftests/ftrace/test.d/direct/kprobe-direct.tc create mode 100755 tools/testing/selftests/livepatch/test-ftrace.sh
Steven Rostedt
maintainerPATCH 1/33 ftrace: Introduce PERMANENT ftrace_ops flag
From: Miroslav Benes <[email protected]>
Livepatch uses ftrace for redirection to new patched functions. It means that if ftrace is disabled, all live patched functions are disabled as well. Toggling global 'ftrace_enabled' sysctl thus affect it directly. It is not a problem per se, because only administrator can set sysctl values, but it still may be surprising.
Introduce PERMANENT ftrace_ops flag to amend this. If the FTRACE_OPS_FL_PERMANENT is set on any ftrace ops, the tracing cannot be disabled by disabling ftrace_enabled. Equally, a callback with the flag set cannot be registered if ftrace_enabled is disabled.
--- Documentation/trace/ftrace-uses.rst | 8 ++++++++ Documentation/trace/ftrace.rst | 4 +++- include/linux/ftrace.h | 3 +++ kernel/livepatch/patch.c | 3 ++- kernel/trace/ftrace.c | 23 +++++++++++++++++++++-- 5 files changed, 37 insertions(+), 4 deletions(-)
Documentation/trace/ftrace-uses.rst +8 -0
@@ -170,6 +170,14 @@ FTRACE_OPS_FL_RCU a callback may be executed and RCU synchronization will not protect it. +FTRACE_OPS_FL_PERMANENT + If this is set on any ftrace ops, then the tracing cannot disabled by + writing 0 to the proc sysctl ftrace_enabled. Equally, a callback with + the flag set cannot be registered if ftrace_enabled is 0. + + Livepatch uses it not to lose the function redirection, so the system + stays protected. + Filtering which functions to trace ==================================
Documentation/trace/ftrace.rst +3 -1
@@ -2976,7 +2976,9 @@ Note, the proc sysctl ftrace_enable is a big on/off switch for the function tracer. By default it is enabled (when function tracing is enabled in the kernel). If it is disabled, all function tracing is disabled. This includes not only the function tracers for ftrace, but -also for any other uses (perf, kprobes, stack tracing, profiling, etc). +also for any other uses (perf, kprobes, stack tracing, profiling, etc). It +cannot be disabled if there is a callback with FTRACE_OPS_FL_PERMANENT set +registered. Please disable this with care.
include/linux/ftrace.h +3 -0
@@ -142,6 +142,8 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);* PID - Is affected by set_ftrace_pid (allows filtering on those pids) * RCU - Set when the ops can only be called when RCU is watching. * TRACE_ARRAY - The ops->private points to a trace_array descriptor. +* PERMANENT - Set when the ops is permanent and should not be affected by +* ftrace_enabled. */ enum {FTRACE_OPS_FL_ENABLED =1 <<0 ,
@@ -160,6 +162,7 @@ enum {FTRACE_OPS_FL_PID =1 <<13 ,FTRACE_OPS_FL_RCU =1 <<14 ,FTRACE_OPS_FL_TRACE_ARRAY =1 <<15 , + FTRACE_OPS_FL_PERMANENT = 1 << 16, };#ifdef CONFIG_DYNAMIC_FTRACE
kernel/livepatch/patch.c +2 -1
@@ -196,7 +196,8 @@ static int klp_patch_func(struct klp_func *func) ops->fops.func = klp_ftrace_handler; ops->fops.flags =FTRACE_OPS_FL_SAVE_REGS |FTRACE_OPS_FL_DYNAMIC | -FTRACE_OPS_FL_IPMODIFY ; +FTRACE_OPS_FL_IPMODIFY | +FTRACE_OPS_FL_PERMANENT ;list_add (&ops->node, &klp_ops);
kernel/trace/ftrace.c +21 -2
@@ -326,6 +326,8 @@ int __register_ftrace_function(struct ftrace_ops *ops)if (ops->flags &FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED ) ops->flags |=FTRACE_OPS_FL_SAVE_REGS ;#endif +if (!ftrace_enabled && (ops->flags &FTRACE_OPS_FL_PERMANENT )) +return -EBUSY ;if (!core_kernel_data ((unsigned long )ops)) ops->flags |=FTRACE_OPS_FL_DYNAMIC ;
@@ -6754,6 +6756,18 @@ int unregister_ftrace_function(struct ftrace_ops *ops) }EXPORT_SYMBOL_GPL (unregister_ftrace_function); +static bool is_permanent_ops_registered (void ) +{ +struct ftrace_ops *op; + +do_for_each_ftrace_op (op, ftrace_ops_list) { +if (op->flags &FTRACE_OPS_FL_PERMANENT ) +return true; + }while_for_each_ftrace_op (op); + +return false; +} + int ftrace_enable_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *lenp,
@@ -6771,8 +6785,6 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) goto out; - last_ftrace_enabled = !!ftrace_enabled; -if (ftrace_enabled) {/* we are starting ftrace again */
@@ -6783,12 +6795,19 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,ftrace_startup_sysctl (); }else { +if (is_permanent_ops_registered ()) { + ftrace_enabled = true; + ret = -EBUSY ; + goto out; + } +/* stopping ftrace calls (just send to ftrace_stub) */ ftrace_trace_function = ftrace_stub;ftrace_shutdown_sysctl (); } + last_ftrace_enabled = !!ftrace_enabled; out:mutex_unlock (&ftrace_lock);return ret;
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 2/33 selftests/livepatch: Make dynamic debug setup and restore generic
In reply to Steven RostedtFrom: Joe Lawrence <[email protected]>
Livepatch selftests currently save the current dynamic debug config and tweak it for the selftests. The config is restored at the end. Make the infrastructure generic, so that more variables can be saved and restored.
--- .../testing/selftests/livepatch/functions.sh | 22 +++++++++++-------- .../selftests/livepatch/test-callbacks.sh | 2 +- .../selftests/livepatch/test-livepatch.sh | 2 +- .../selftests/livepatch/test-shadow-vars.sh | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-)
tools/testing/selftests/livepatch/functions.sh +13 -9
@@ -29,29 +29,33 @@ function die() { exit 1 } -function push_dynamic_debug() { - DYNAMIC_DEBUG=$(grep '^kernel/livepatch' /sys/kernel/debug/dynamic_debug/control | \ - awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}') +function push_config() { + DYNAMIC_DEBUG=$(grep '^kernel/livepatch' /sys/kernel/debug/dynamic_debug/control | \ + awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}') } -function pop_dynamic_debug() { +function pop_config() { if [[ -n "$DYNAMIC_DEBUG" ]]; then echo -n "$DYNAMIC_DEBUG" > /sys/kernel/debug/dynamic_debug/control fi } -# set_dynamic_debug() - save the current dynamic debug config and tweak -# it for the self-tests. Set a script exit trap -# that restores the original config. function set_dynamic_debug() { - push_dynamic_debug - trap pop_dynamic_debug EXIT INT TERM HUP cat <<-EOF > /sys/kernel/debug/dynamic_debug/control file kernel/livepatch/* +p func klp_try_switch_task -p EOF } +# setup_config - save the current config and set a script exit trap that +# restores the original config. Setup the dynamic debug +# for verbose livepatching output. +function setup_config() { + push_config + set_dynamic_debug + trap pop_config EXIT INT TERM HUP +} + # loop_until(cmd) - loop a command until it is successful or $MAX_RETRIES, # sleep $RETRY_INTERVAL between attempts # cmd - command and its arguments to run
tools/testing/selftests/livepatch/test-callbacks.sh +1 -1
@@ -9,7 +9,7 @@ MOD_LIVEPATCH2=test_klp_callbacks_demo2 MOD_TARGET=test_klp_callbacks_mod MOD_TARGET_BUSY=test_klp_callbacks_busy -set_dynamic_debug +setup_config # TEST: target module before livepatch
tools/testing/selftests/livepatch/test-livepatch.sh +1 -1
@@ -7,7 +7,7 @@ MOD_LIVEPATCH=test_klp_livepatch MOD_REPLACE=test_klp_atomic_replace -set_dynamic_debug +setup_config # TEST: basic function patching
tools/testing/selftests/livepatch/test-shadow-vars.sh +1 -1
@@ -6,7 +6,7 @@ MOD_TEST=test_klp_shadow_vars -set_dynamic_debug +setup_config # TEST: basic shadow variable API
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 3/33 selftests/livepatch: Test interaction with ftrace_enabled
In reply to Steven RostedtFrom: Joe Lawrence <[email protected]>
Since livepatching depends upon ftrace handlers to implement "patched" code functionality, verify that the ftrace_enabled sysctl value interacts with livepatch registration as expected. At the same time, ensure that ftrace_enabled is set and part of the test environment configuration that is saved and restored when running the selftests.
--- tools/testing/selftests/livepatch/Makefile | 3 +- .../testing/selftests/livepatch/functions.sh | 14 +++- .../selftests/livepatch/test-ftrace.sh | 65 +++++++++++++++++++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100755 tools/testing/selftests/livepatch/test-ftrace.sh
tools/testing/selftests/livepatch/Makefile +2 -1
@@ -4,6 +4,7 @@ TEST_PROGS_EXTENDED := functions.sh TEST_PROGS := \ test-livepatch.sh \ test-callbacks.sh \ - test-shadow-vars.sh + test-shadow-vars.sh \ + test-ftrace.sh include ../lib.mk
tools/testing/selftests/livepatch/functions.sh +13 -1
@@ -32,12 +32,16 @@ function die() { function push_config() { DYNAMIC_DEBUG=$(grep '^kernel/livepatch' /sys/kernel/debug/dynamic_debug/control | \ awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}') + FTRACE_ENABLED=$(sysctl --values kernel.ftrace_enabled) } function pop_config() { if [[ -n "$DYNAMIC_DEBUG" ]]; then echo -n "$DYNAMIC_DEBUG" > /sys/kernel/debug/dynamic_debug/control fi + if [[ -n "$FTRACE_ENABLED" ]]; then + sysctl kernel.ftrace_enabled="$FTRACE_ENABLED" &> /dev/null + fi } function set_dynamic_debug() {
@@ -47,12 +51,20 @@ function set_dynamic_debug() { EOF } +function set_ftrace_enabled() { + local sysctl="$1" + result=$(sysctl kernel.ftrace_enabled="$1" 2>&1 | paste --serial --delimiters=' ') + echo "livepatch: $result" > /dev/kmsg +} + # setup_config - save the current config and set a script exit trap that # restores the original config. Setup the dynamic debug -# for verbose livepatching output. +# for verbose livepatching output and turn on +# the ftrace_enabled sysctl. function setup_config() { push_config set_dynamic_debug + set_ftrace_enabled 1 trap pop_config EXIT INT TERM HUP }
tools/testing/selftests/livepatch/test-ftrace.sh new file +65 -0
65 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 4/33 ftrace: Separate out the copying of a ftrace_hash from __ftrace_hash_move()
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
Most of the functionality of __ftrace_hash_move() can be reused, but not all of it. That is, __ftrace_hash_move() is used to simply make a new hash from an existing one, using the same size as the original. Creating a dup_hash(), where we can specify a new size will be useful when we want to create a hash with a default size, or simply copy the old one.
--- kernel/trace/ftrace.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)
kernel/trace/ftrace.c +17 -12
@@ -1372,23 +1372,15 @@ ftrace_hash_rec_enable_modify(struct ftrace_ops *ops, int filter_hash);static int ftrace_hash_ipmodify_update (struct ftrace_ops *ops,struct ftrace_hash *new_hash); -static struct ftrace_hash * -__ftrace_hash_move (struct ftrace_hash *src) +static struct ftrace_hash *dup_hash (struct ftrace_hash *src,int size) {struct ftrace_func_entry *entry; -struct hlist_node *tn; -struct hlist_head *hhd;struct ftrace_hash *new_hash; -int size = src->count; +struct hlist_head *hhd; +struct hlist_node *tn;int bits =0 ;int i; -/* -* If the new source is empty, just return the empty_hash. -*/ -if (ftrace_hash_empty (src)) -return EMPTY_HASH ; -/* * Make the hash size about 1/2 the # found */
@@ -1413,10 +1405,23 @@ __ftrace_hash_move(struct ftrace_hash *src)__add_hash_entry (new_hash, entry); } } -return new_hash; } +static struct ftrace_hash * +__ftrace_hash_move (struct ftrace_hash *src) +{ +int size = src->count; + +/* +* If the new source is empty, just return the empty_hash. +*/ +if (ftrace_hash_empty (src)) +return EMPTY_HASH ; + +return dup_hash (src, size); +} +static int ftrace_hash_move (struct ftrace_ops *ops,int enable,struct ftrace_hash **dst,struct ftrace_hash *src)
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 5/33 ftrace: Separate out functionality from ftrace_location_range()
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
Create a new function called lookup_rec() from the functionality of ftrace_location_range(). The difference between lookup_rec() is that it returns the record that it finds, where as ftrace_location_range() returns only if it found a match or not.
The lookup_rec() is static, and can be used for new functionality where ftrace needs to find a record of a specific address.
--- kernel/trace/ftrace.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-)
kernel/trace/ftrace.c +23 -15
@@ -1541,6 +1541,26 @@ static int ftrace_cmp_recs(const void *a, const void *b)return 0 ; } +static struct dyn_ftrace *lookup_rec (unsigned long start,unsigned long end) +{ +struct ftrace_page *pg; +struct dyn_ftrace *rec =NULL ; +struct dyn_ftrace key; + + key.ip = start; + key.flags = end;/* overload flags, as it is unsigned long */ + +for (pg = ftrace_pages_start; pg; pg = pg->next) { +if (end < pg->records[0 ].ip || + start >= (pg->records[pg->index -1 ].ip +MCOUNT_INSN_SIZE )) +continue ; + rec =bsearch (&key, pg->records, pg->index, +sizeof (struct dyn_ftrace ), + ftrace_cmp_recs); + } +return rec; +} +/** * ftrace_location_range - return the first address of a traced location * if it touches the given ip range
@@ -1555,23 +1575,11 @@ static int ftrace_cmp_recs(const void *a, const void *b)*/ unsigned long ftrace_location_range (unsigned long start,unsigned long end) { -struct ftrace_page *pg;struct dyn_ftrace *rec; -struct dyn_ftrace key; - key.ip = start; - key.flags = end;/* overload flags, as it is unsigned long */ - -for (pg = ftrace_pages_start; pg; pg = pg->next) { -if (end < pg->records[0 ].ip || - start >= (pg->records[pg->index -1 ].ip +MCOUNT_INSN_SIZE )) -continue ; - rec =bsearch (&key, pg->records, pg->index, -sizeof (struct dyn_ftrace ), - ftrace_cmp_recs); -if (rec) -return rec->ip; - } + rec =lookup_rec (start, end); +if (rec) +return rec->ip;return 0 ; }
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 6/33 ftrace: Add register_ftrace_direct()
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
Add the start of the functionality to allow other trampolines to use the ftrace mcount/fentry/nop location. This adds two new functions:
register_ftrace_direct() and unregister_ftrace_direct()
Both take two parameters: the first is the instruction address of where the mcount/fentry/nop exists, and the second is the trampoline to have that location called.
This will handle cases where ftrace is already used on that same location, and will make it still work, where the registered direct called trampoline will get called after all the registered ftrace callers are handled.
Currently, it will not allow for IP_MODIFY functions to be called at the same locations, which include some kprobes and live kernel patching.
At this point, no architecture supports this. This is only the start of implementing the framework.
--- include/linux/ftrace.h | 36 +++++- kernel/trace/Kconfig | 8 ++ kernel/trace/ftrace.c | 269 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 306 insertions(+), 7 deletions(-)
include/linux/ftrace.h +34 -2
@@ -144,6 +144,8 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);* TRACE_ARRAY - The ops->private points to a trace_array descriptor. * PERMANENT - Set when the ops is permanent and should not be affected by * ftrace_enabled. +* DIRECT - Used by the direct ftrace_ops helper for direct functions +* (internal ftrace only, should not be used by others) */ enum {FTRACE_OPS_FL_ENABLED =1 <<0 ,
@@ -163,6 +165,7 @@ enum {FTRACE_OPS_FL_RCU =1 <<14 ,FTRACE_OPS_FL_TRACE_ARRAY =1 <<15 ,FTRACE_OPS_FL_PERMANENT =1 <<16 , + FTRACE_OPS_FL_DIRECT = 1 << 17, };#ifdef CONFIG_DYNAMIC_FTRACE
@@ -242,6 +245,32 @@ static inline void ftrace_free_init_mem(void) { }static inline void ftrace_free_mem (struct module *mod,void *start,void *end) { }#endif /* CONFIG_FUNCTION_TRACER */ +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS +int register_ftrace_direct (unsigned long ip,unsigned long addr); +int unregister_ftrace_direct (unsigned long ip,unsigned long addr); +#else +static inline int register_ftrace_direct (unsigned long ip,unsigned long addr) +{ +return -ENODEV ; +} +static inline int unregister_ftrace_direct (unsigned long ip,unsigned long addr) +{ +return -ENODEV ; +} +#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ + +#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS +/* +* This must be implemented by the architecture. +* It is the way the ftrace direct_ops helper, when called +* via ftrace (because there's other callbacks besides the +* direct call), can inform the architecture's trampoline that this +* routine has a direct caller, and what the caller is. +*/ +static inline void arch_ftrace_set_direct_caller (struct pt_regs *regs, +unsigned long addr) { } +#endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ +#ifdef CONFIG_STACK_TRACER extern int stack_tracer_enabled;
@@ -333,6 +362,7 @@ bool is_ftrace_trampoline(unsigned long addr);* REGS_EN - the function is set up to save regs. * IPMODIFY - the record allows for the IP address to be changed. * DISABLED - the record is not ready to be touched yet +* DIRECT - there is a direct function to call * * When a new ftrace_ops is registered and wants a function to save * pt_regs, the rec->flag REGS is set. When the function has been
@@ -348,10 +378,12 @@ enum {FTRACE_FL_TRAMP_EN = (1UL <<27 ),FTRACE_FL_IPMODIFY = (1UL <<26 ),FTRACE_FL_DISABLED = (1UL <<25 ), +FTRACE_FL_DIRECT = (1UL <<24 ), + FTRACE_FL_DIRECT_EN = (1UL << 23), }; -#define FTRACE_REF_MAX_SHIFT 25 -#define FTRACE_FL_BITS 7 +#define FTRACE_REF_MAX_SHIFT 23 +#define FTRACE_FL_BITS 9#define FTRACE_FL_MASKED_BITS ((1UL << FTRACE_FL_BITS) - 1)#define FTRACE_FL_MASK (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)#define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1)
kernel/trace/Kconfig +8 -0
@@ -33,6 +33,9 @@ config HAVE_DYNAMIC_FTRACE config HAVE_DYNAMIC_FTRACE_WITH_REGS bool +config HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS + bool + config HAVE_FTRACE_MCOUNT_RECORD bool help
@@ -557,6 +560,11 @@ config DYNAMIC_FTRACE_WITH_REGS depends on DYNAMIC_FTRACE depends on HAVE_DYNAMIC_FTRACE_WITH_REGS +config DYNAMIC_FTRACE_WITH_DIRECT_CALLS + def_bool y + depends on DYNAMIC_FTRACE + depends on HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS + config FUNCTION_PROFILER bool "Kernel function profiler" depends on FUNCTION_TRACER
kernel/trace/ftrace.c +264 -5
350 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 7/33 ftrace: Add ftrace_find_direct_func()
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
As function_graph tracer modifies the return address to insert a trampoline to trace the return of a function, it must be aware of a direct caller, as when it gets called, the function's return address may not be at on the stack where it expects. It may have to see if that return address points to the a direct caller and adjust if it is.
--- include/linux/ftrace.h | 6 ++++ kernel/trace/ftrace.c | 79 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-)
include/linux/ftrace.h +6 -0
@@ -51,6 +51,7 @@ static inline void early_trace_init(void) { }struct module ;struct ftrace_hash ; +struct ftrace_direct_func ;#if defined(CONFIG_FUNCTION_TRACER ) && defined(CONFIG_MODULES ) && \ defined(CONFIG_DYNAMIC_FTRACE )
@@ -248,6 +249,7 @@ static inline void ftrace_free_mem(struct module *mod, void *start, void *end) {#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS int register_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);#else static inline int register_ftrace_direct (unsigned long ip,unsigned long addr) {
@@ -257,6 +259,10 @@ static inline int unregister_ftrace_direct(unsigned long ip, unsigned long addr) {return -ENODEV ; } +static inline struct ftrace_direct_func *ftrace_find_direct_func (unsigned long addr) +{ +return NULL ; +}#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ #ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
kernel/trace/ftrace.c +78 -1
116 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 8/33 ftrace: Add sample module that uses register_ftrace_direct()
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
Add a sample module that shows a simple use case for regsiter_ftrace_direct(), and how to use it.
--- samples/Kconfig | 8 ++++++ samples/Makefile | 1 + samples/ftrace/Makefile | 3 +++ samples/ftrace/ftrace-direct.c | 45 ++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 samples/ftrace/Makefile create mode 100644 samples/ftrace/ftrace-direct.c
samples/Kconfig +8 -0
@@ -19,6 +19,14 @@ config SAMPLE_TRACE_PRINTK This builds a module that calls trace_printk() and can be used to test various trace_printk() calls from a module. +config SAMPLE_FTRACE_DIRECT + tristate "Build register_ftrace_direct() example" + depends on DYNAMIC_FTRACE_WITH_DIRECT_CALLS && m + depends on X86_64 # has x86_64 inlined asm + help + This builds an ftrace direct function example + that hooks to wake_up_process and prints the parameters. + config SAMPLE_KOBJECT tristate "Build kobject examples" help
samples/Makefile +1 -0
@@ -17,6 +17,7 @@ obj-$(CONFIG_SAMPLE_RPMSG_CLIENT) += rpmsg/ subdir-$(CONFIG_SAMPLE_SECCOMP) += seccomp obj-$(CONFIG_SAMPLE_TRACE_EVENTS) += trace_events/ obj-$(CONFIG_SAMPLE_TRACE_PRINTK) += trace_printk/ +obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace/ obj-$(CONFIG_VIDEO_PCI_SKELETON) += v4l/ obj-y += vfio-mdev/ subdir-$(CONFIG_SAMPLE_VFS) += vfs
samples/ftrace/Makefile new file +3 -0
@@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct.o
samples/ftrace/ftrace-direct.c new file +45 -0
45 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 9/33 ftrace/selftest: Add tests to test register_ftrace_direct()
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
Add two test cases that test the new ftrace direct functionality if the ftrace-direct sample module is available. One test case tests against each available tracer (function, function_graph, mmiotrace, etc), and the other test tests against a kprobe at the same location as the direct caller. Both tests follow the same pattern of testing combinations:
enable test (either the tracer or the kprobe)
load direct function module
unload direct function module
disable test
enable test
load direct function module
disable test
unload direct function module
load direct function module
enable test
disable test
unload direct function module
load direct function module
enable test
unload direct function module
disable test
As most the bugs in development happened with various ways of enabling or disabling the direct calls with function tracer in one of these combinations.
--- .../ftrace/test.d/direct/ftrace-direct.tc | 53 ++++++++++++++ .../ftrace/test.d/direct/kprobe-direct.tc | 71 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/direct/ftrace-direct.tc create mode 100644 tools/testing/selftests/ftrace/test.d/direct/kprobe-direct.tc
tools/testing/selftests/ftrace/test.d/direct/ftrace-direct.tc new file +53 -0
@@ -0,0 +1,53 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Test ftrace direct functions against tracers + +rmmod ftrace-direct ||: +if ! modprobe ftrace-direct ; then + echo "No ftrace-direct sample module - please make CONFIG_SAMPLE_FTRACE_DIRECT=m" + exit_unresolved; +fi + +echo "Let the module run a little" +sleep 1 + +grep -q "my_direct_func: wakeing up" trace + +rmmod ftrace-direct + +test_tracer() { + tracer=$1 + + # tracer -> direct -> no direct > no tracer + echo $tracer > current_tracer + modprobe ftrace-direct + rmmod ftrace-direct + echo nop > current_tracer + + # tracer -> direct -> no tracer > no direct + echo $tracer > current_tracer + modprobe ftrace-direct + echo nop > current_tracer + rmmod ftrace-direct + + # direct -> tracer -> no tracer > no direct + modprobe ftrace-direct + echo $tracer > current_tracer + echo nop > current_tracer + rmmod ftrace-direct + + # direct -> tracer -> no direct > no notracer + modprobe ftrace-direct + echo $tracer > current_tracer + rmmod ftrace-direct + echo nop > current_tracer +} + +for t in `cat available_tracers`; do + if [ "$t" != "nop" ]; then + test_tracer $t + fi +done + +echo nop > current_tracer +rmmod ftrace-direct ||:
tools/testing/selftests/ftrace/test.d/direct/kprobe-direct.tc new file +71 -0
71 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 10/33 ftrace: Add another example of register_ftrace_direct() use case
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
Add another module sample that registers a direct trampoline to a function via register_ftrace_direct(). Having another module that does this allows to test the use case of multiple direct callers registered, as more than one direct caller goes into another path, and is needed to perform proper testing of the register_ftrace_direct() call.
--- samples/ftrace/Makefile | 1 + samples/ftrace/ftrace-direct-too.c | 51 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 samples/ftrace/ftrace-direct-too.c
samples/ftrace/Makefile +1 -0
@@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct.o +obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-too.o
samples/ftrace/ftrace-direct-too.c new file +51 -0
51 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 11/33 ftrace/selftests: Update the direct call selftests to test two direct calls
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
The register_ftrace_direct() takes a different path if there's already a direct call registered, but this was not tested in the self tests. Now that there's a second direct caller test module, we can use this to test not only one direct caller, but two.
--- .../ftrace/test.d/direct/ftrace-direct.tc | 16 +++++ .../ftrace/test.d/direct/kprobe-direct.tc | 59 +++++++++++-------- 2 files changed, 52 insertions(+), 23 deletions(-)
tools/testing/selftests/ftrace/test.d/direct/ftrace-direct.tc +16 -0
@@ -51,3 +51,19 @@ done echo nop > current_tracer rmmod ftrace-direct ||: + +# Now do the same thing with another direct function registered +echo "Running with another ftrace direct function" + +rmmod ftrace-direct-too ||: +modprobe ftrace-direct-too + +for t in `cat available_tracers`; do + if [ "$t" != "nop" ]; then + test_tracer $t + fi +done + +echo nop > current_tracer +rmmod ftrace-direct ||: +rmmod ftrace-direct-too ||:
tools/testing/selftests/ftrace/test.d/direct/kprobe-direct.tc +36 -23
64 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 12/33 ftrace/x86: Add register_ftrace_direct() for custom trampolines
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
Enable x86 to allow for register_ftrace_direct(), where a custom trampoline may be called directly from an ftrace mcount/fentry location.
--- arch/x86/Kconfig | 1 + arch/x86/include/asm/ftrace.h | 13 +++++++++++++ arch/x86/kernel/ftrace.c | 12 ++++++++++++ arch/x86/kernel/ftrace_64.S | 34 +++++++++++++++++++++++++++------- include/linux/ftrace.h | 6 ++++++ 5 files changed, 59 insertions(+), 7 deletions(-)
arch/x86/Kconfig +1 -0
@@ -158,6 +158,7 @@ config X86 select HAVE_DMA_CONTIGUOUS select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE_WITH_REGS + select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_EBPF_JIT select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_EISA
arch/x86/include/asm/ftrace.h +13 -0
@@ -28,6 +28,19 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)return addr; } +/* +* When a ftrace registered caller is tracing a function that is +* also set by a register_ftrace_direct() call, it needs to be +* differentiated in the ftrace_caller trampoline. To do this, we +* place the direct caller in the ORIG_AX part of pt_regs. This +* tells the ftrace_caller that there's a direct caller. +*/ +static inline void arch_ftrace_set_direct_caller (struct pt_regs *regs,unsigned long addr) +{ +/* Emulate a call */ + regs->orig_ax = addr; +} +#ifdef CONFIG_DYNAMIC_FTRACE struct dyn_arch_ftrace {
arch/x86/kernel/ftrace.c +12 -0
@@ -1042,6 +1042,18 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,if (unlikely (atomic_read (¤t->tracing_graph_pause)))return ; +/* +* If the return location is actually pointing directly to +* the start of a direct trampoline (if we trace the trampoline +* it will still be offset by MCOUNT_INSN_SIZE), then the +* return address is actually off by one word, and we +* need to adjust for that. +*/ +if (ftrace_find_direct_func (self_addr +MCOUNT_INSN_SIZE )) { + self_addr = *parent; + parent++; + } +/* * Protect against fault, even if it shouldn't * happen. This tool is too much intrusive to
arch/x86/kernel/ftrace_64.S +27 -7
@@ -88,6 +88,7 @@ EXPORT_SYMBOL(__fentry__) movq %rdi, RDI(%rsp) movq %r8, R8(%rsp) movq %r9, R9(%rsp) + movq $0, ORIG_RAX(%rsp) /* * Save the original RBP. Even though the mcount ABI does not * require this, it helps out callers.
@@ -114,7 +115,11 @@ EXPORT_SYMBOL(__fentry__) subq $MCOUNT_INSN_SIZE, %rdi .endm -.macro restore_mcount_regs +.macro restore_mcount_regs save=0 + + /* ftrace_regs_caller or frame pointers require this */ + movq RBP(%rsp), %rbp + movq R9(%rsp), %r9 movq R8(%rsp), %r8 movq RDI(%rsp), %rdi
@@ -123,10 +128,7 @@ EXPORT_SYMBOL(__fentry__) movq RCX(%rsp), %rcx movq RAX(%rsp), %rax - /* ftrace_regs_caller can modify %rbp */ - movq RBP(%rsp), %rbp - - addq $MCOUNT_REG_SIZE, %rsp + addq $MCOUNT_REG_SIZE-\save, %rsp .endm
@@ -228,10 +230,28 @@ GLOBAL(ftrace_regs_call) movq R10(%rsp), %r10 movq RBX(%rsp), %rbx - restore_mcount_regs + movq ORIG_RAX(%rsp), %rax + movq %rax, MCOUNT_REG_SIZE-8(%rsp) + + /* If ORIG_RAX is anything but zero, make this a call to that */ + movq ORIG_RAX(%rsp), %rax + cmpq $0, %rax + je 1f + + /* Swap the flags with orig_rax */ + movq MCOUNT_REG_SIZE(%rsp), %rdi + movq %rdi, MCOUNT_REG_SIZE-8(%rsp) + movq %rax, MCOUNT_REG_SIZE(%rsp) + + restore_mcount_regs 8 + + jmp 2f + +1: restore_mcount_regs + /* Restore flags */ - popfq +2: popfq /* * As this jmp to ftrace_epilogue can be a short jump
include/linux/ftrace.h +6 -0
@@ -272,6 +272,12 @@ static inline struct ftrace_direct_func *ftrace_find_direct_func(unsigned long a* via ftrace (because there's other callbacks besides the * direct call), can inform the architecture's trampoline that this * routine has a direct caller, and what the caller is. +* +* For example, in x86, it returns the direct caller +* callback function via the regs->orig_ax parameter. +* Then in the ftrace trampoline, if this is set, it makes +* the return from the trampoline jump to the direct caller +* instead of going back to the function it just traced. */ static inline void arch_ftrace_set_direct_caller (struct pt_regs *regs,unsigned long addr) { }
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 13/33 ftrace/x86: Add a counter to test function_graph with direct
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
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.
--- arch/x86/kernel/ftrace.c | 8 +++++--- include/linux/ftrace.h | 2 ++ kernel/trace/ftrace.c | 4 ++++ 3 files changed, 11 insertions(+), 3 deletions(-)
arch/x86/kernel/ftrace.c +5 -3
@@ -1049,9 +1049,11 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,* return address is actually off by one word, and we * need to adjust for that. */ -if (ftrace_find_direct_func (self_addr +MCOUNT_INSN_SIZE )) { - self_addr = *parent; - parent++; +if (ftrace_direct_func_count) { +if (ftrace_find_direct_func (self_addr +MCOUNT_INSN_SIZE )) { + self_addr = *parent; + parent++; + } }/*
include/linux/ftrace.h +2 -0
@@ -247,10 +247,12 @@ static inline void ftrace_free_mem(struct module *mod, void *start, void *end) {#endif /* CONFIG_FUNCTION_TRACER */ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS +extern int ftrace_direct_func_count;int register_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);#else +# define ftrace_direct_func_count 0static inline int register_ftrace_direct (unsigned long ip,unsigned long addr) {return -ENODEV ;
kernel/trace/ftrace.c +4 -0
@@ -2364,6 +2364,7 @@ ftrace_find_tramp_ops_new(struct dyn_ftrace *rec)/* Protected by rcu_tasks for reading, and direct_mutex for writing */ static struct ftrace_hash *direct_functions =EMPTY_HASH ;static DEFINE_MUTEX (direct_mutex); +int ftrace_direct_func_count;/* * 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) direct->addr = addr; direct->count =0 ;list_add_rcu (&direct->next, &ftrace_direct_funcs); + ftrace_direct_func_count++; } entry->ip = ip;
@@ -5081,6 +5083,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)if (free_hash)free_ftrace_hash (free_hash); free_hash =NULL ; + ftrace_direct_func_count--; } }else {if (!direct->count)
@@ -5141,6 +5144,7 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr)list_del_rcu (&direct->next);synchronize_rcu_tasks ();kfree (direct); + ftrace_direct_func_count--; } } out_unlock:
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 14/33 ftrace/x86: Tell objtool to ignore nondeterministic ftrace stack layout
In reply to Steven RostedtFrom: Josh Poimboeuf <[email protected]>
Objtool complains about the new ftrace direct trampoline code:
arch/x86/kernel/ftrace_64.o: warning: objtool: ftrace_regs_caller()+0x190: stack state mismatch: cfa1=7+16 cfa2=7+24
Typically, code has a deterministic stack layout, such that at a given instruction address, the stack frame size is always the same.
That's not the case for the new ftrace_regs_caller() code after it adjusts the stack for the direct case. Just plead ignorance and assume it's always the non-direct path. Note this creates a tiny window for ORC to get confused.
--- arch/x86/include/asm/unwind_hints.h | 8 ++++++++ arch/x86/kernel/ftrace_64.S | 12 +++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-)
arch/x86/include/asm/unwind_hints.h +8 -0
@@ -86,6 +86,14 @@ UNWIND_HINT sp_offset=\sp_offset .endm +.macro UNWIND_HINT_SAVE + UNWIND_HINT type=UNWIND_HINT_TYPE_SAVE +.endm + +.macro UNWIND_HINT_RESTORE + UNWIND_HINT type=UNWIND_HINT_TYPE_RESTORE +.endm +#else /* !__ASSEMBLY__ */ #define UNWIND_HINT (sp_reg, sp_offset, type, end) \
arch/x86/kernel/ftrace_64.S +11 -1
@@ -178,6 +178,8 @@ ENTRY(ftrace_regs_caller) /* Save the current flags before any operations that can change them */ pushfq + UNWIND_HINT_SAVE + /* added 8 bytes to save flags */ save_mcount_regs 8 /* save_mcount_regs fills in first two parameters */
@@ -250,8 +252,16 @@ GLOBAL(ftrace_regs_call) 1: restore_mcount_regs +2: + /* + * The stack layout is nondetermistic here, depending on which path was + * taken. This confuses objtool and ORC, rightfully so. For now, + * pretend the stack always looks like the non-direct case. + */ + UNWIND_HINT_RESTORE + /* Restore flags */ -2: popfq + popfq /* * As this jmp to ftrace_epilogue can be a short jump
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 15/33 ftrace: Add information on number of page groups allocated
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
Looking for ways to shrink the size of the dyn_ftrace structure, knowing the information about how many pages and the number of groups of those pages, is useful in working out the best ways to save on memory.
This adds one info print on how many groups of pages were used to allocate the ftrace dyn_ftrace structures, and also shows the number of pages and groups in the dyn_ftrace_total_info (which is used for debugging).
--- kernel/trace/ftrace.c | 14 ++++++++++++++ kernel/trace/trace.c | 21 +++++++++++++++------ kernel/trace/trace.h | 2 ++ 3 files changed, 31 insertions(+), 6 deletions(-)
kernel/trace/ftrace.c +14 -0
@@ -2991,6 +2991,8 @@ static void ftrace_shutdown_sysctl(void)static u64 ftrace_update_time;unsigned long ftrace_update_tot_cnt; +unsigned long ftrace_number_of_pages; +unsigned long ftrace_number_of_groups;static inline int ops_traces_mod (struct ftrace_ops *ops) {
@@ -3115,6 +3117,9 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count) goto again; } + ftrace_number_of_pages +=1 << order; + ftrace_number_of_groups++; + cnt = (PAGE_SIZE << order) /ENTRY_SIZE ; pg->size = cnt;
@@ -3170,6 +3175,8 @@ ftrace_allocate_pages(unsigned long num_to_init) start_pg = pg->next;kfree (pg); pg = start_pg; + ftrace_number_of_pages -=1 << order; + ftrace_number_of_groups--; }pr_info ("ftrace: FAILED to allocate memory for functions\n" );return NULL ;
@@ -6173,6 +6180,8 @@ void ftrace_release_mod(struct module *mod)free_pages ((unsigned long )pg->records, order); tmp_page = pg->next;kfree (pg); + ftrace_number_of_pages -=1 << order; + ftrace_number_of_groups--; } }
@@ -6514,6 +6523,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) *last_pg = pg->next; order =get_count_order (pg->size /ENTRIES_PER_PAGE );free_pages ((unsigned long )pg->records, order); + ftrace_number_of_pages -=1 << order; + ftrace_number_of_groups--;kfree (pg); pg = container_of(last_pg, struct ftrace_page, next);if (!(*last_pg))
@@ -6569,6 +6580,9 @@ void __init ftrace_init(void) __start_mcount_loc, __stop_mcount_loc); +pr_info ("ftrace: allocated %ld pages with %ld groups\n" , + ftrace_number_of_pages, ftrace_number_of_groups); +set_ftrace_early_filters ();return ;
kernel/trace/trace.c +15 -6
@@ -7583,14 +7583,23 @@ static ssize_t tracing_read_dyn_info(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { - unsigned long *p = filp->private_data; -char buf[64 ];/* Not too big for a shallow stack */ + ssize_t ret; +char *buf;int r; - r =scnprintf (buf,63 ,"%ld" , *p); - buf[r++] ='\n' ; +/* 256 should be plenty to hold the amount needed */ + buf =kmalloc (256 ,GFP_KERNEL ); +if (!buf) +return -ENOMEM ; -return simple_read_from_buffer (ubuf, cnt, ppos, buf, r); + r =scnprintf (buf,256 ,"%ld pages:%ld groups: %ld\n" , + ftrace_update_tot_cnt, + ftrace_number_of_pages, + ftrace_number_of_groups); + + ret =simple_read_from_buffer (ubuf, cnt, ppos, buf, r); +kfree (buf); +return ret; } static const struct file_operations tracing_dyn_info_fops = {
@@ -8782,7 +8791,7 @@ static __init int tracer_init_tracefs(void)#ifdef CONFIG_DYNAMIC_FTRACE trace_create_file ("dyn_ftrace_total_info" ,0444 , d_tracer, - &ftrace_update_tot_cnt, &tracing_dyn_info_fops); +NULL , &tracing_dyn_info_fops);#endif create_trace_instances (d_tracer);
kernel/trace/trace.h +2 -0
@@ -804,6 +804,8 @@ extern void trace_event_follow_fork(struct trace_array *tr, bool enable);#ifdef CONFIG_DYNAMIC_FTRACE extern unsigned long ftrace_update_tot_cnt; +extern unsigned long ftrace_number_of_pages; +extern unsigned long ftrace_number_of_groups;void ftrace_init_trace_array (struct trace_array *tr);#else static inline void ftrace_init_trace_array (struct trace_array *tr) { }
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 16/33 ftrace: Implement fs notification for tracing_max_latency
In reply to Steven RostedtFrom: "Viktor Rosendahl (BMW)" <[email protected]>
This patch implements the feature that the tracing_max_latency file, e.g. /sys/kernel/debug/tracing/tracing_max_latency will receive notifications through the fsnotify framework when a new latency is available.
One particularly interesting use of this facility is when enabling threshold tracing, through /sys/kernel/debug/tracing/tracing_thresh, together with the preempt/irqsoff tracers. This makes it possible to implement a user space program that can, with equal probability, obtain traces of latencies that occur immediately after each other in spite of the fact that the preempt/irqsoff tracers operate in overwrite mode.
This facility works with the hwlat, preempt/irqsoff, and wakeup tracers.
The tracers may call the latency_fsnotify() from places such as __schedule() or do_idle(); this makes it impossible to call queue_work() directly without risking a deadlock. The same would happen with a softirq, kernel thread or tasklet. For this reason we use the irq_work mechanism to call queue_work().
This patch creates a new workqueue. The reason for doing this is that I wanted to use the WQ_UNBOUND and WQ_HIGHPRI flags. My thinking was that WQ_UNBOUND might help with the latency in some important cases.
If we use:
queue_work(system_highpri_wq, &tr->fsnotify_work);
then the work will (almost) always execute on the same CPU but if we are unlucky that CPU could be too busy while there could be another CPU in the system that would be able to process the work soon enough.
queue_work_on() could be used to queue the work on another CPU but it seems difficult to select the right CPU.
--- kernel/trace/trace.c | 75 +++++++++++++++++++++++++++++++++++++- kernel/trace/trace.h | 18 +++++++++ kernel/trace/trace_hwlat.c | 11 ++++-- 3 files changed, 98 insertions(+), 6 deletions(-)
kernel/trace/trace.c +73 -2
@@ -45,6 +45,9 @@#include <linux/trace.h> #include <linux/sched/clock.h> #include <linux/sched/rt.h> +#include <linux/fsnotify.h> +#include <linux/irq_work.h> +#include <linux/workqueue.h> #include "trace.h" #include "trace_output.h"
@@ -1497,6 +1500,74 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt) }unsigned long __read_mostly tracing_thresh; +static const struct file_operations tracing_max_lat_fops; + +#if (defined(CONFIG_TRACER_MAX_TRACE ) || defined(CONFIG_HWLAT_TRACER )) && \ + defined(CONFIG_FSNOTIFY ) + +static struct workqueue_struct *fsnotify_wq; + +static void latency_fsnotify_workfn (struct work_struct *work) +{ + struct trace_array *tr = container_of(work, struct trace_array, + fsnotify_work); +fsnotify (tr->d_max_latency->d_inode,FS_MODIFY , + tr->d_max_latency->d_inode,FSNOTIFY_EVENT_INODE ,NULL ,0 ); +} + +static void latency_fsnotify_workfn_irq (struct irq_work *iwork) +{ + struct trace_array *tr = container_of(iwork, struct trace_array, + fsnotify_irqwork); +queue_work (fsnotify_wq, &tr->fsnotify_work); +} + +static void trace_create_maxlat_file (struct trace_array *tr, +struct dentry *d_tracer) +{ +INIT_WORK (&tr->fsnotify_work, latency_fsnotify_workfn); +init_irq_work (&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq); + tr->d_max_latency =trace_create_file ("tracing_max_latency" ,0644 , + d_tracer, &tr->max_latency, + &tracing_max_lat_fops); +} + +__init static int latency_fsnotify_init (void ) +{ + fsnotify_wq =alloc_workqueue ("tr_max_lat_wq" , +WQ_UNBOUND |WQ_HIGHPRI ,0 ); +if (!fsnotify_wq) { +pr_err ("Unable to allocate tr_max_lat_wq\n" ); +return -ENOMEM ; + } +return 0 ; +} + +late_initcall_sync (latency_fsnotify_init); + +void latency_fsnotify (struct trace_array *tr) +{ +if (!fsnotify_wq) +return ; +/* +* We cannot call queue_work(&tr->fsnotify_work) from here because it's +* possible that we are called from __schedule() or do_idle(), which +* could cause a deadlock. +*/ +irq_work_queue (&tr->fsnotify_irqwork); +} + +/* +* (defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER)) && \ +* defined(CONFIG_FSNOTIFY) +*/ +#else + +#define trace_create_maxlat_file (tr, d_tracer) \ + trace_create_file("tracing_max_latency", 0644, d_tracer, \ + &tr->max_latency, &tracing_max_lat_fops) + +#endif #ifdef CONFIG_TRACER_MAX_TRACE /*
@@ -1536,6 +1607,7 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)/* record this tasks comm */ tracing_record_cmdline (tsk); +latency_fsnotify (tr); }/**
@@ -8594,8 +8666,7 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)create_trace_options_dir (tr);#if defined(CONFIG_TRACER_MAX_TRACE ) || defined(CONFIG_HWLAT_TRACER ) -trace_create_file ("tracing_max_latency" ,0644 , d_tracer, - &tr->max_latency, &tracing_max_lat_fops); +trace_create_maxlat_file (tr, d_tracer);#endif if (ftrace_create_function_files (tr, d_tracer))
kernel/trace/trace.h +18 -0
@@ -16,6 +16,8 @@#include <linux/trace_events.h> #include <linux/compiler.h> #include <linux/glob.h> +#include <linux/irq_work.h> +#include <linux/workqueue.h> #ifdef CONFIG_FTRACE_SYSCALLS #include <asm/unistd.h> /* For NR_SYSCALLS */
@@ -264,6 +266,11 @@ struct trace_array {#endif #if defined(CONFIG_TRACER_MAX_TRACE ) || defined(CONFIG_HWLAT_TRACER )unsigned long max_latency; +#ifdef CONFIG_FSNOTIFY +struct dentry *d_max_latency; +struct work_struct fsnotify_work; +struct irq_work fsnotify_irqwork; +#endif #endif struct trace_pid_list __rcu *filtered_pids;/*
@@ -786,6 +793,17 @@ void update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu);#endif /* CONFIG_TRACER_MAX_TRACE */ +#if (defined(CONFIG_TRACER_MAX_TRACE ) || defined(CONFIG_HWLAT_TRACER )) && \ + defined(CONFIG_FSNOTIFY ) + +void latency_fsnotify (struct trace_array *tr); + +#else + +static void latency_fsnotify (struct trace_array *tr) { } + +#endif +#ifdef CONFIG_STACKTRACE void __trace_stack (struct trace_array *tr,unsigned long flags,int skip,int pc);
kernel/trace/trace_hwlat.c +7 -4
@@ -237,6 +237,7 @@ static int get_sample(void)/* If we exceed the threshold value, we have found a hardware latency */ if (sample > thresh || outer_sample > thresh) {struct hwlat_sample s; +u64 latency; ret =1 ;
@@ -253,11 +254,13 @@ static int get_sample(void) s.nmi_count = nmi_count;trace_hwlat_sample (&s); + latency =max (sample, outer_sample); +/* Keep a running maximum ever recorded hardware latency */ -if (sample > tr->max_latency) - tr->max_latency = sample; -if (outer_sample > tr->max_latency) - tr->max_latency = outer_sample; +if (latency > tr->max_latency) { + tr->max_latency = latency; +latency_fsnotify (tr); + } } out:
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 17/33 preemptirq_delay_test: Add the burst feature and a sysfs trigger
In reply to Steven RostedtFrom: "Viktor Rosendahl (BMW)" <[email protected]>
This burst feature enables the user to generate a burst of preempt/irqsoff latencies. This makes it possible to test whether we are able to detect latencies that systematically occur very close to each other.
The maximum burst size is 10. We also create 10 identical test functions, so that we get 10 different backtraces; this is useful when we want to test whether we can detect all the latencies in a burst. Otherwise, there would be no easy way of differentiating between which latency in a burst was captured by the tracer.
In addition, there is a sysfs trigger, so that it's not necessary to reload the module to repeat the test. The trigger will appear as /sys/kernel/preemptirq_delay_test/trigger in sysfs.
--- kernel/trace/Kconfig | 6 +- kernel/trace/preemptirq_delay_test.c | 144 +++++++++++++++++++++++---- 2 files changed, 128 insertions(+), 22 deletions(-)
kernel/trace/Kconfig +3 -3
@@ -760,9 +760,9 @@ config PREEMPTIRQ_DELAY_TEST configurable delay. The module busy waits for the duration of the critical section. - For example, the following invocation forces a one-time irq-disabled - critical section for 500us: - modprobe preemptirq_delay_test test_mode=irq delay=500000 + For example, the following invocation generates a burst of three + irq-disabled critical sections for 500us: + modprobe preemptirq_delay_test test_mode=irq delay=500 burst_size=3 If unsure, say N
kernel/trace/preemptirq_delay_test.c +125 -19
180 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 18/33 tracing: Use CONFIG_PREEMPTION
In reply to Steven RostedtFrom: Sebastian Andrzej Siewior <[email protected]>
CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. Both PREEMPT and PREEMPT_RT require the same functionality which today depends on CONFIG_PREEMPT.
Add additional header output for PREEMPT_RT.
--- Documentation/trace/ftrace-uses.rst | 2 +- kernel/trace/trace.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
Documentation/trace/ftrace-uses.rst +1 -1
@@ -146,7 +146,7 @@ FTRACE_OPS_FL_RECURSION_SAFE itself or any nested functions that those functions call. If this flag is set, it is possible that the callback will also - be called with preemption enabled (when CONFIG_PREEMPT is set), + be called with preemption enabled (when CONFIG_PREEMPTION is set), but this is not guaranteed. FTRACE_OPS_FL_IPMODIFY
kernel/trace/trace.c +2 -0
@@ -3726,6 +3726,8 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter) "desktop",#elif defined(CONFIG_PREEMPT ) "preempt", +#elif defined(CONFIG_PREEMPT_RT ) + "preempt_rt", #else "unknown",#endif
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 19/33 tracing: Make internal ftrace events static
In reply to Steven RostedtFrom: Ben Dooks <[email protected]>
The event_class_ftrace_##call and event_##call do not seem to be used outside of trace_export.c so make them both static to avoid a number of sparse warnings:
kernel/trace/trace_entries.h:59:1: warning: symbol 'event_class_ftrace_function' was not declared. Should it be static? kernel/trace/trace_entries.h:59:1: warning: symbol '__event_function' was not declared. Should it be static? kernel/trace/trace_entries.h:77:1: warning: symbol 'event_class_ftrace_funcgraph_entry' was not declared. Should it be static? kernel/trace/trace_entries.h:77:1: warning: symbol '__event_funcgraph_entry' was not declared. Should it be static? kernel/trace/trace_entries.h:93:1: warning: symbol 'event_class_ftrace_funcgraph_exit' was not declared. Should it be static? kernel/trace/trace_entries.h:93:1: warning: symbol '__event_funcgraph_exit' was not declared. Should it be static? kernel/trace/trace_entries.h:129:1: warning: symbol 'event_class_ftrace_context_switch' was not declared. Should it be static? kernel/trace/trace_entries.h:129:1: warning: symbol '__event_context_switch' was not declared. Should it be static? kernel/trace/trace_entries.h:149:1: warning: symbol 'event_class_ftrace_wakeup' was not declared. Should it be static? kernel/trace/trace_entries.h:149:1: warning: symbol '__event_wakeup' was not declared. Should it be static? kernel/trace/trace_entries.h:171:1: warning: symbol 'event_class_ftrace_kernel_stack' was not declared. Should it be static? kernel/trace/trace_entries.h:171:1: warning: symbol '__event_kernel_stack' was not declared. Should it be static? kernel/trace/trace_entries.h:191:1: warning: symbol 'event_class_ftrace_user_stack' was not declared. Should it be static? kernel/trace/trace_entries.h:191:1: warning: symbol '__event_user_stack' was not declared. Should it be static? kernel/trace/trace_entries.h:214:1: warning: symbol 'event_class_ftrace_bprint' was not declared. Should it be static? kernel/trace/trace_entries.h:214:1: warning: symbol '__event_bprint' was not declared. Should it be static? kernel/trace/trace_entries.h:230:1: warning: symbol 'event_class_ftrace_print' was not declared. Should it be static? kernel/trace/trace_entries.h:230:1: warning: symbol '__event_print' was not declared. Should it be static? kernel/trace/trace_entries.h:247:1: warning: symbol 'event_class_ftrace_raw_data' was not declared. Should it be static? kernel/trace/trace_entries.h:247:1: warning: symbol '__event_raw_data' was not declared. Should it be static? kernel/trace/trace_entries.h:262:1: warning: symbol 'event_class_ftrace_bputs' was not declared. Should it be static? kernel/trace/trace_entries.h:262:1: warning: symbol '__event_bputs' was not declared. Should it be static? kernel/trace/trace_entries.h:277:1: warning: symbol 'event_class_ftrace_mmiotrace_rw' was not declared. Should it be static? kernel/trace/trace_entries.h:277:1: warning: symbol '__event_mmiotrace_rw' was not declared. Should it be static? kernel/trace/trace_entries.h:298:1: warning: symbol 'event_class_ftrace_mmiotrace_map' was not declared. Should it be static? kernel/trace/trace_entries.h:298:1: warning: symbol '__event_mmiotrace_map' was not declared. Should it be static? kernel/trace/trace_entries.h:322:1: warning: symbol 'event_class_ftrace_branch' was not declared. Should it be static? kernel/trace/trace_entries.h:322:1: warning: symbol '__event_branch' was not declared. Should it be static? kernel/trace/trace_entries.h:343:1: warning: symbol 'event_class_ftrace_hwlat' was not declared. Should it be static? kernel/trace/trace_entries.h:343:1: warning: symbol '__event_hwlat' was not declared. Should it be static?
--- kernel/trace/trace_export.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/trace_export.c +2 -2
@@ -171,7 +171,7 @@ ftrace_define_fields_##name(struct trace_event_call *event_call) \#define FTRACE_ENTRY_REG (call, struct_name, etype, tstruct, print, filter,\ regfn) \ \ -struct trace_event_class __refdata event_class_ftrace_##call = { \ +static struct trace_event_class __refdata event_class_ftrace_##call = { \ .system = __stringify(TRACE_SYSTEM), \ .define_fields = ftrace_define_fields_##call, \ .fields = LIST_HEAD_INIT(event_class_ftrace_##call.fields),\
@@ -187,7 +187,7 @@ struct trace_event_call __used event_##call = { \ .print_fmt = print, \ .flags = TRACE_EVENT_FL_IGNORE_ENABLE, \ }; \ -struct trace_event_call __used \ +static struct trace_event_call __used \ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;#undef FTRACE_ENTRY
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 20/33 tracing: Declare newly exported APIs in include/linux/trace.h
In reply to Steven RostedtFrom: Divya Indi <[email protected]>
Declare the newly introduced and exported APIs in the header file - include/linux/trace.h. Moving previous declarations from kernel/trace/trace.h to include/linux/trace.h.
--- include/linux/trace.h | 7 +++++++ kernel/trace/trace.h | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-)
include/linux/trace.h +7 -0
@@ -24,6 +24,13 @@ struct trace_export {int register_ftrace_export (struct trace_export *export);int unregister_ftrace_export (struct trace_export *export); +struct trace_array ; + +void trace_printk_init_buffers (void ); +int trace_array_printk (struct trace_array *tr,unsigned long ip, +const char *fmt, ...); +struct trace_array *trace_array_create (const char *name); +int trace_array_destroy (struct trace_array *tr);#endif /* CONFIG_TRACING */ #endif /* _LINUX_TRACE_H */
kernel/trace/trace.h +1 -3
@@ -11,6 +11,7 @@#include <linux/mmiotrace.h> #include <linux/tracepoint.h> #include <linux/ftrace.h> +#include <linux/trace.h> #include <linux/hw_breakpoint.h> #include <linux/trace_seq.h> #include <linux/trace_events.h>
@@ -873,8 +874,6 @@ trace_vprintk(unsigned long ip, const char *fmt, va_list args);extern int trace_array_vprintk (struct trace_array *tr,unsigned long ip,const char *fmt,va_list args); -int trace_array_printk (struct trace_array *tr, -unsigned long ip,const char *fmt, ...);int trace_array_printk_buf (struct ring_buffer *buffer,unsigned long ip,const char *fmt, ...);void trace_printk_seq (struct trace_seq *s);
@@ -1890,7 +1889,6 @@ extern const char *__start___tracepoint_str[];extern const char *__stop___tracepoint_str[];void trace_printk_control (bool enabled); -void trace_printk_init_buffers (void );void trace_printk_start_comm (void );int trace_keep_overwrite (struct tracer *tracer,u32 mask,int set);int set_tracer_flag (struct trace_array *tr,unsigned int mask,int enabled);
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 21/33 tracing: Verify if trace array exists before destroying it.
In reply to Steven RostedtFrom: Divya Indi <[email protected]>
A trace array can be destroyed from userspace or kernel. Verify if the trace array exists before proceeding to destroy/remove it.
--- kernel/module.c | 6 +++++- kernel/trace/trace.c | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-)
kernel/module.c +5 -1
@@ -3728,7 +3728,6 @@ static int complete_formation(struct module *mod, struct load_info *info)module_enable_ro (mod, false);module_enable_nx (mod); -module_enable_x (mod);/* Mark state as coming so strong_try_module_get() ignores us, * but kallsyms etc. can see us. */
@@ -3751,6 +3750,11 @@ static int prepare_coming_module(struct module *mod)if (err)return err; +/* Make module executable after ftrace is enabled */ +mutex_lock (&module_mutex); +module_enable_x (mod); +mutex_unlock (&module_mutex); +blocking_notifier_call_chain (&module_notify_list,MODULE_STATE_COMING , mod);return 0 ;
kernel/trace/trace.c +12 -3
@@ -8556,17 +8556,26 @@ static int __remove_instance(struct trace_array *tr)return 0 ; } -int trace_array_destroy (struct trace_array *tr) +int trace_array_destroy (struct trace_array *this_tr) { +struct trace_array *tr;int ret; -if (!tr) +if (!this_tr)return -EINVAL ;mutex_lock (&event_mutex);mutex_lock (&trace_types_lock); - ret =__remove_instance (tr); + ret = -ENODEV ; + +/* Making sure trace array exists before destroying it. */ +list_for_each_entry (tr, &ftrace_trace_arrays, list) { +if (tr == this_tr) { + ret =__remove_instance (tr); +break ; + } + }mutex_unlock (&trace_types_lock);mutex_unlock (&event_mutex);
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 22/33 tracing: Adding NULL checks for trace_array descriptor pointer
In reply to Steven RostedtFrom: Divya Indi <[email protected]>
As part of commit f45d1225adb0 ("tracing: Kernel access to Ftrace instances") we exported certain functions. Here, we are adding some additional NULL checks to ensure safe usage by users of these APIs.
--- kernel/trace/trace.c | 3 +++ kernel/trace/trace_events.c | 2 ++ 2 files changed, 5 insertions(+)
kernel/trace/trace.c +3 -0
@@ -3297,6 +3297,9 @@ int trace_array_printk(struct trace_array *tr,if (!(global_trace.trace_flags &TRACE_ITER_PRINTK ))return 0 ; +if (!tr) +return -ENOENT ; +va_start (ap, fmt); ret =trace_array_vprintk (tr, ip, fmt, ap);va_end (ap);
kernel/trace/trace_events.c +2 -0
@@ -793,6 +793,8 @@ int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)char *event =NULL , *sub =NULL , *match;int ret; +if (!tr) +return -ENOENT ;/* * The buf format can be <subsystem>:<event-name> * *:<event-name> means any event by that name.
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 23/33 fgraph: Fix function type mismatches of ftrace_graph_return using ftrace_stub
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
The C compiler is allowing more checks to make sure that function pointers are assigned to the correct prototype function. Unfortunately, the function graph tracer uses a special name with its assigned ftrace_graph_return function pointer that maps to a stub function used by the function tracer (ftrace_stub). The ftrace_graph_return variable is compared to the ftrace_stub in some archs to know if the function graph tracer is enabled or not. This means we can not just simply create a new function stub that compares it without modifying all the archs.
Instead, have the linker script create a function_graph_stub that maps to ftrace_stub, and this way we can define the prototype for it to match the prototype of ftrace_graph_return, and make the compiler checks all happy!
--- arch/sh/boot/compressed/misc.c | 5 +++++ include/asm-generic/vmlinux.lds.h | 17 ++++++++++++++--- kernel/trace/fgraph.c | 11 ++++++++--- 3 files changed, 27 insertions(+), 6 deletions(-)
arch/sh/boot/compressed/misc.c +5 -0
@@ -111,6 +111,11 @@ void __stack_chk_fail(void)error ("stack-protector: Kernel stack is corrupted\n" ); } +/* Needed because vmlinux.lds.h references this */ +void ftrace_stub (void ) +{ +} +#ifdef CONFIG_SUPERH64 #define stackalign 8#else
include/asm-generic/vmlinux.lds.h +14 -3
@@ -111,18 +111,29 @@#ifdef CONFIG_FTRACE_MCOUNT_RECORD #ifdef CC_USING_PATCHABLE_FUNCTION_ENTRY +/* +* Need to also make ftrace_graph_stub point to ftrace_stub +* so that the same stub location may have different protocols +* and not mess up with C verifiers. +*/ #define MCOUNT_REC () . = ALIGN(8); \ __start_mcount_loc = .; \ KEEP(*(__patchable_function_entries)) \ - __stop_mcount_loc = .; + __stop_mcount_loc = .; \ + ftrace_graph_stub = ftrace_stub;#else #define MCOUNT_REC () . = ALIGN(8); \ __start_mcount_loc = .; \ KEEP(*(__mcount_loc)) \ - __stop_mcount_loc = .; + __stop_mcount_loc = .; \ + ftrace_graph_stub = ftrace_stub;#endif #else -#define MCOUNT_REC () +# ifdef CONFIG_FUNCTION_TRACER +# define MCOUNT_REC () ftrace_graph_stub = ftrace_stub; +# else +# define MCOUNT_REC () +# endif #endif #ifdef CONFIG_TRACE_BRANCH_PROFILING
kernel/trace/fgraph.c +8 -2
@@ -332,9 +332,14 @@ int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)return 0 ; } +/* +* Simply points to ftrace_stub, but with the proper protocol. +* Defined by the linker script in linux/vmlinux.lds.h +*/ +extern void ftrace_graph_stub (struct ftrace_graph_ret *); +/* The callbacks that hook a function */ -trace_func_graph_ret_t ftrace_graph_return - (trace_func_graph_ret_t)ftrace_stub; +trace_func_graph_ret_t ftrace_graph_return = ftrace_graph_stub;trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;static trace_func_graph_ent_t __ftrace_graph_entry = ftrace_graph_entry_stub;
@@ -614,7 +619,7 @@ void unregister_ftrace_graph(struct fgraph_ops *gops) goto out; ftrace_graph_active--; - ftrace_graph_return = (trace_func_graph_ret_t )ftrace_stub; + ftrace_graph_return = ftrace_graph_stub; ftrace_graph_entry = ftrace_graph_entry_stub; __ftrace_graph_entry = ftrace_graph_entry_stub;ftrace_shutdown (&graph_ops,FTRACE_STOP_FUNC_RET );
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 24/33 tracing/selftests: Turn off timeout setting
In reply to Steven RostedtFrom: "Steven Rostedt (VMware)" <[email protected]>
As the ftrace selftests can run for a long period of time, disable the timeout that the general selftests have. If a selftest hangs, then it probably means the machine will hang too.
--- tools/testing/selftests/ftrace/settings | 1 + 1 file changed, 1 insertion(+) create mode 100644 tools/testing/selftests/ftrace/settings
tools/testing/selftests/ftrace/settings new file +1 -0
@@ -0,0 +1 @@ +timeout=0
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 25/33 lib/sort: Move swap, cmp and cmp_r function types for wider use
In reply to Steven RostedtFrom: Andy Shevchenko <[email protected]>
The function types for swap, cmp and cmp_r functions are already being in use by modules.
Move them to types.h that everybody in kernel will be able to use generic types instead of custom ones.
This adds more sense to the comment in bsearch() later on.
--- include/linux/sort.h | 8 ++++---- include/linux/types.h | 5 +++++ lib/sort.c | 15 +++++---------- 3 files changed, 14 insertions(+), 14 deletions(-)
include/linux/sort.h +4 -4
@@ -5,12 +5,12 @@#include <linux/types.h> void sort_r (void *base,size_t num,size_t size, -int (*cmp)(const void *,const void *,const void *), -void (*swap)(void *,void *,int ), +cmp_r_func_t cmp_func, +swap_func_t swap_func,const void *priv);void sort (void *base,size_t num,size_t size, -int (*cmp)(const void *,const void *), -void (*swap)(void *,void *,int )); +cmp_func_t cmp_func, +swap_func_t swap_func);#endif
include/linux/types.h +5 -0
@@ -225,5 +225,10 @@ struct callback_head {typedef void (*rcu_callback_t )(struct rcu_head *head);typedef void (*call_rcu_func_t )(struct rcu_head *head,rcu_callback_t func); +typedef void (*swap_func_t )(void *a,void *b,int size); + +typedef int (*cmp_r_func_t )(const void *a,const void *b,const void *priv); +typedef int (*cmp_func_t )(const void *a,const void *b); +#endif /* __ASSEMBLY__ */ #endif /* _LINUX_TYPES_H */
lib/sort.c +5 -10
@@ -117,8 +117,6 @@ static void swap_bytes(void *a, void *b, size_t n) }while (n); } -typedef void (*swap_func_t )(void *a,void *b,int size); -/* * The values are arbitrary as long as they can't be confused with * a pointer, but small integers make for the smallest compare
@@ -144,12 +142,9 @@ static void do_swap(void *a, void *b, size_t size, swap_func_t swap_func)swap_func (a, b, (int )size); } -typedef int (*cmp_func_t )(const void *,const void *); -typedef int (*cmp_r_func_t )(const void *,const void *,const void *);#define _CMP_WRAPPER ((cmp_r_func_t)0L) -static int do_cmp (const void *a,const void *b, -cmp_r_func_t cmp,const void *priv) +static int do_cmp (const void *a,const void *b,cmp_r_func_t cmp,const void *priv) {if (cmp == _CMP_WRAPPER)return ((cmp_func_t)(priv))(a, b);
@@ -202,8 +197,8 @@ static size_t parent(size_t i, unsigned int lsbit, size_t size)* it less suitable for kernel use. */ void sort_r (void *base,size_t num,size_t size, -int (*cmp_func)(const void *,const void *,const void *), -void (*swap_func)(void *,void *,int size), +cmp_r_func_t cmp_func, +swap_func_t swap_func,const void *priv) {/* pre-scale counters for performance */
@@ -269,8 +264,8 @@ void sort_r(void *base, size_t num, size_t size,EXPORT_SYMBOL (sort_r);void sort (void *base,size_t num,size_t size, -int (*cmp_func)(const void *,const void *), -void (*swap_func)(void *,void *,int size)) +cmp_func_t cmp_func, +swap_func_t swap_func) {return sort_r (base, num, size, _CMP_WRAPPER, swap_func, cmp_func); }
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 26/33 lib/bsearch: Use generic type for comparator function
In reply to Steven RostedtFrom: Andy Shevchenko <[email protected]>
Comparator function type, cmp_func_t, is defined in the types.h, use it in bsearch() and, thus, add more sense to the corresponding comment in the code.
--- include/linux/bsearch.h | 2 +- lib/bsearch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/linux/bsearch.h +1 -1
@@ -5,6 +5,6 @@#include <linux/types.h> void *bsearch (const void *key,const void *base,size_t num,size_t size, -int (*cmp)(const void *key,const void *elt)); +cmp_func_t cmp);#endif /* _LINUX_BSEARCH_H */
lib/bsearch.c +1 -1
@@ -29,7 +29,7 @@* the same comparison function for both sort() and bsearch(). */ void *bsearch (const void *key,const void *base,size_t num,size_t size, -int (*cmp)(const void *key,const void *elt)) +cmp_func_t cmp) {const char *pivot;int result;
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 27/33 tracing: Use generic type for comparator function
In reply to Steven RostedtFrom: Andy Shevchenko <[email protected]>
Comparator function type, cmp_func_t, is defined in the types.h, use it in the code.
--- kernel/trace/ftrace.c | 12 ++++++------ kernel/trace/trace_branch.c | 8 ++++---- kernel/trace/trace_stat.c | 6 ++---- kernel/trace/trace_stat.h | 2 +- 4 files changed, 13 insertions(+), 15 deletions(-)
kernel/trace/ftrace.c +6 -6
@@ -465,10 +465,10 @@ static void *function_stat_start(struct tracer_stat *trace)#ifdef CONFIG_FUNCTION_GRAPH_TRACER /* function graph compares on total time */ -static int function_stat_cmp (void *p1,void *p2) +static int function_stat_cmp (const void *p1,const void *p2) { -struct ftrace_profile *a = p1; -struct ftrace_profile *b = p2; +const struct ftrace_profile *a = p1; +const struct ftrace_profile *b = p2;if (a->time < b->time)return -1 ;
@@ -479,10 +479,10 @@ static int function_stat_cmp(void *p1, void *p2) }#else /* not function graph compares against hits */ -static int function_stat_cmp (void *p1,void *p2) +static int function_stat_cmp (const void *p1,const void *p2) { -struct ftrace_profile *a = p1; -struct ftrace_profile *b = p2; +const struct ftrace_profile *a = p1; +const struct ftrace_profile *b = p2;if (a->counter < b->counter)return -1 ;
kernel/trace/trace_branch.c +4 -4
@@ -244,7 +244,7 @@ static int annotated_branch_stat_headers(struct seq_file *m)return 0 ; } -static inline long get_incorrect_percent (struct ftrace_branch_data *p) +static inline long get_incorrect_percent (const struct ftrace_branch_data *p) {long percent;
@@ -332,10 +332,10 @@ annotated_branch_stat_next(void *v, int idx)return p; } -static int annotated_branch_stat_cmp (void *p1,void *p2) +static int annotated_branch_stat_cmp (const void *p1,const void *p2) { -struct ftrace_branch_data *a = p1; -struct ftrace_branch_data *b = p2; +const struct ftrace_branch_data *a = p1; +const struct ftrace_branch_data *b = p2;long percent_a, percent_b;
kernel/trace/trace_stat.c +2 -4
@@ -72,9 +72,7 @@ static void destroy_session(struct stat_session *session)kfree (session); } -typedef int (*cmp_stat_t )(void *,void *); - -static int insert_stat (struct rb_root *root,void *stat,cmp_stat_t cmp) +static int insert_stat (struct rb_root *root,void *stat,cmp_func_t cmp) {struct rb_node **new = &(root->rb_node), *parent =NULL ;struct stat_node *data;
@@ -112,7 +110,7 @@ static int insert_stat(struct rb_root *root, void *stat, cmp_stat_t cmp)* This one will force an insertion as right-most node * in the rbtree. */ -static int dummy_cmp (void *p1,void *p2) +static int dummy_cmp (const void *p1,const void *p2) {return -1 ; }
kernel/trace/trace_stat.h +1 -1
@@ -16,7 +16,7 @@ struct tracer_stat {void *(*stat_start)(struct tracer_stat *trace);void *(*stat_next)(void *prev,int idx);/* Compare two entries for stats sorting */ -int (*stat_cmp)(void *p1,void *p2); +cmp_func_t stat_cmp;/* Print a stat entry */ int (*stat_show)(struct seq_file *s,void *p);/* Release an entry */
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 28/33 tracing/hwlat: Fix a few trivial nits
In reply to Steven RostedtFrom: "Srivatsa S. Bhat (VMware)" <[email protected]>
Update the source file name in the comments, and fix a grammatical error.
--- kernel/trace/trace_hwlat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/trace_hwlat.c +2 -2
@@ -1,6 +1,6 @@// SPDX-License-Identifier: GPL-2.0 /* -* trace_hwlatdetect.c - A simple Hardware Latency detector. +* trace_hwlat.c - A simple Hardware Latency detector. * * Use this tracer to detect large system latencies induced by the behavior of * certain underlying system hardware or firmware, independent of Linux itself.
@@ -279,7 +279,7 @@ static void move_to_next_cpu(void)return ;/* * If for some reason the user modifies the CPU affinity -* of this thread, than stop migrating for the duration +* of this thread, then stop migrating for the duration * of the current test. */ if (!cpumask_equal (current_mask, current->cpus_ptr))
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 29/33 tracing: use kvcalloc for tgid_map array allocation
In reply to Steven RostedtFrom: Yuming Han <[email protected]>
Fail to allocate memory for tgid_map, because it requires order-6 page. detail as:
c3 sh: page allocation failure: order:6,
mode:0x140c0c0(GFP_KERNEL), nodemask=(null)
c3 sh cpuset=/ mems_allowed=0
c3 CPU: 3 PID: 5632 Comm: sh Tainted: G W O 4.14.133+ #10
c3 Hardware name: Generic DT based system
c3 Backtrace:
c3 [<c010bdbc>] (dump_backtrace) from [<c010c08c>](show_stack+0x18/0x1c) c3 [<c010c074>] (show_stack) from [<c0993c54>](dump_stack+0x84/0xa4)
c3 [<c0993bd0>] (dump_stack) from [<c0229858>](warn_alloc+0xc4/0x19c)
c3 [<c0229798>] (warn_alloc) from [<c022a6e4>](__alloc_pages_nodemask+0xd18/0xf28) c3 [<c02299cc>] (__alloc_pages_nodemask) from [<c0248344>](kmalloc_order+0x20/0x38) c3 [<c0248324>] (kmalloc_order) from [<c0248380>](kmalloc_order_trace+0x24/0x108) c3 [<c024835c>] (kmalloc_order_trace) from [<c01e6078>](set_tracer_flag+0xb0/0x158) c3 [<c01e5fc8>] (set_tracer_flag) from [<c01e6404>](trace_options_core_write+0x7c/0xcc) c3 [<c01e6388>] (trace_options_core_write) from [<c0278b1c>](__vfs_write+0x40/0x14c) c3 [<c0278adc>] (__vfs_write) from [<c0278e10>](vfs_write+0xc4/0x198)
c3 [<c0278d4c>] (vfs_write) from [<c027906c>](SyS_write+0x6c/0xd0)
c3 [<c0279000>] (SyS_write) from [<c01079a0>](ret_fast_syscall+0x0/0x54)
Switch to use kvcalloc to avoid unexpected allocation failures.
--- kernel/trace/trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace.c +1 -1
@@ -4686,7 +4686,7 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)if (mask ==TRACE_ITER_RECORD_TGID ) {if (!tgid_map) - tgid_map =kcalloc (PID_MAX_DEFAULT +1 , + tgid_map =kvcalloc (PID_MAX_DEFAULT +1 ,sizeof (*tgid_map),GFP_KERNEL );if (!tgid_map) {
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 30/33 tracing/kprobe: Check whether the non-suffixed symbol is notrace
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Check whether the non-suffixed symbol is notrace, since suffixed symbols are generated by the compilers for optimization. Based on these suffixed symbols, notrace check might not work because some of them are just a partial code of the original function. (e.g. cold-cache (unlikely) code is separated from original
function as FUNCTION.cold.XX)
For example, without this fix,
# echo p device_add.cold.67 > /sys/kernel/debug/tracing/kprobe_events sh: write error: Invalid argument
# cat /sys/kernel/debug/tracing/error_log
[ 135.491035] trace_kprobe: error: Failed to register probe event
Command: p device_add.cold.67
^
# dmesg | tail -n 1
[ 135.488599] trace_kprobe: Could not probe notrace function device_add.cold.67With this,
# echo p device_add.cold.66 > /sys/kernel/debug/tracing/kprobe_events # cat /sys/kernel/debug/kprobes/list ffffffff81599de9 k device_add.cold.66+0x0 [DISABLED]
Actually, kprobe blacklist already did similar thing, see within_kprobe_blacklist().
--- kernel/trace/trace_kprobe.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-)
kernel/trace/trace_kprobe.c +24 -3
@@ -435,11 +435,10 @@ static int disable_trace_kprobe(struct trace_event_call *call,#if defined(CONFIG_KPROBES_ON_FTRACE ) && \ !defined(CONFIG_KPROBE_EVENTS_ON_NOTRACE ) -static bool within_notrace_func (struct trace_kprobe *tk) +static bool __within_notrace_func (unsigned long addr) { -unsigned long offset, size, addr; +unsigned long offset, size; - addr =trace_kprobe_address (tk);if (!addr || !kallsyms_lookup_size_offset (addr, &size, &offset))return false;
@@ -452,6 +451,28 @@ static bool within_notrace_func(struct trace_kprobe *tk)*/ return !ftrace_location_range(addr, addr + size - 1); } + +static bool within_notrace_func (struct trace_kprobe *tk) +{ +unsigned long addr = addr =trace_kprobe_address (tk); +char symname[KSYM_NAME_LEN ], *p; + +if (!__within_notrace_func (addr)) +return false; + +/* Check if the address is on a suffixed-symbol */ +if (!lookup_symbol_name (addr, symname)) { + p =strchr (symname,'.' ); +if (!p) +return true; + *p ='\0' ; + addr = (unsigned long )kprobe_lookup_name (symname,0 ); +if (addr) +return __within_notrace_func (addr); + } + +return true; +}#else #define within_notrace_func (tk) (false)#endif
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 31/33 seq_buf: Add printing formatted hex dumps
In reply to Steven RostedtFrom: Piotr Maziarz <[email protected]>
Provided function is an analogue of print_hex_dump().
Implementing this function in seq_buf allows using for multiple purposes (e.g. for tracing) and therefore prevents from code duplication in every layer that uses seq_buf.
print_hex_dump() is an essential part of logging data to dmesg. Adding similar capability for other purposes is beneficial to all users.
Example usage:
seq_buf_hex_dump(seq, "", DUMP_PREFIX_OFFSET, 16, 4, buf,
ARRAY_SIZE(buf), true); Example output: 00000000: 00000000 ffffff10 ffffff32 ffff3210 ........2....2.. 00000010: ffff3210 83d00437 c0700000 00000000 .2..7.....p..... 00000020: 02010004 0000000f 0000000f 00004002 .............@.. 00000030: 00000fff 00000000 ........
--- include/linux/seq_buf.h | 3 ++ lib/seq_buf.c | 62 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+)
include/linux/seq_buf.h +3 -0
@@ -125,6 +125,9 @@ extern int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len);extern int seq_buf_putmem_hex (struct seq_buf *s,const void *mem,unsigned int len);extern int seq_buf_path (struct seq_buf *s,const struct path *path,const char *esc); +extern int seq_buf_hex_dump (struct seq_buf *s,const char *prefix_str, +int prefix_type,int rowsize,int groupsize, +const void *buf,size_t len,bool ascii);#ifdef CONFIG_BINARY_PRINTF extern int
lib/seq_buf.c +62 -0
65 lines not on this page · raw message
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 32/33 tracing: Use seq_buf_hex_dump() to dump buffers
In reply to Steven RostedtFrom: Piotr Maziarz <[email protected]>
Without this, buffers can be printed with __print_array macro that has no formatting options and can be hard to read. The other way is to mimic formatting capability with multiple calls of trace event with one call per row which gives performance impact and different timestamp in each row.
--- include/linux/trace_events.h | 5 +++++ include/linux/trace_seq.h | 4 ++++ include/trace/trace_events.h | 6 ++++++ kernel/trace/trace_output.c | 15 +++++++++++++++ kernel/trace/trace_seq.c | 30 ++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+)
include/linux/trace_events.h +5 -0
@@ -45,6 +45,11 @@ const char *trace_print_array_seq(struct trace_seq *p, const void *buf, int count, size_t el_size); +const char * +trace_print_hex_dump_seq (struct trace_seq *p,const char *prefix_str, +int prefix_type,int rowsize,int groupsize, +const void *buf,size_t len,bool ascii); +struct trace_iterator ;struct trace_event ;
include/linux/trace_seq.h +4 -0
@@ -92,6 +92,10 @@ extern int trace_seq_path(struct trace_seq *s, const struct path *path);extern void trace_seq_bitmask (struct trace_seq *s,const unsigned long *maskp,int nmaskbits); +extern int trace_seq_hex_dump (struct trace_seq *s,const char *prefix_str, +int prefix_type,int rowsize,int groupsize, +const void *buf,size_t len,bool ascii); +#else /* CONFIG_TRACING */ static inline void trace_seq_printf (struct trace_seq *s,const char *fmt, ...) {
include/trace/trace_events.h +6 -0
@@ -340,6 +340,12 @@ TRACE_MAKE_SYSTEM_STR();trace_print_array_seq (p, array, count, el_size); \ }) +#undef __print_hex_dump +#define __print_hex_dump (prefix_str, prefix_type, \ + rowsize, groupsize, buf, len, ascii) \ + trace_print_hex_dump_seq(p, prefix_str, prefix_type, \ + rowsize, groupsize, buf, len, ascii) +#undef DECLARE_EVENT_CLASS#define DECLARE_EVENT_CLASS (call, proto, args, tstruct, assign, print) \ static notrace enum print_line_t \
kernel/trace/trace_output.c +15 -0
@@ -274,6 +274,21 @@ trace_print_array_seq(struct trace_seq *p, const void *buf, int count, }EXPORT_SYMBOL (trace_print_array_seq); +const char * +trace_print_hex_dump_seq (struct trace_seq *p,const char *prefix_str, +int prefix_type,int rowsize,int groupsize, +const void *buf,size_t len,bool ascii) +{ +const char *ret =trace_seq_buffer_ptr (p); + +trace_seq_putc (p,'\n' ); +trace_seq_hex_dump (p, prefix_str, prefix_type, + rowsize, groupsize, buf, len, ascii); +trace_seq_putc (p,0 ); +return ret; +} +EXPORT_SYMBOL (trace_print_hex_dump_seq); +int trace_raw_output_prep (struct trace_iterator *iter,struct trace_event *trace_event) {
kernel/trace/trace_seq.c +30 -0
@@ -376,3 +376,33 @@ int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)return seq_buf_to_user (&s->seq, ubuf, cnt); }EXPORT_SYMBOL_GPL (trace_seq_to_user); + +int trace_seq_hex_dump (struct trace_seq *s,const char *prefix_str, +int prefix_type,int rowsize,int groupsize, +const void *buf,size_t len,bool ascii) +{ +unsigned int save_len = s->seq.len; + +if (s->full) +return 0 ; + +__trace_seq_init (s); + +if (TRACE_SEQ_BUF_LEFT (s) <1 ) { + s->full =1 ; +return 0 ; + } + +seq_buf_hex_dump (&(s->seq), prefix_str, + prefix_type, rowsize, groupsize, + buf, len, ascii); + +if (unlikely (seq_buf_has_overflowed (&s->seq))) { + s->seq.len = save_len; + s->full =1 ; +return 0 ; + } + +return 1 ; +} +EXPORT_SYMBOL (trace_seq_hex_dump);
Signature · 1 line
2.23.0
Steven Rostedt
maintainerPATCH 33/33 tracing: Remove stray tab in TRACE_EVAL_MAP_FILEs help text
In reply to Steven RostedtFrom: Borislav Petkov <[email protected]>
There was a stray tab in the help text of the aforementioned config option which showed like this:
The "print fmt" of the trace events will show the enum/sizeof names
instead of their values. This can cause problems for user space tools
...
in menuconfig. Remove it and end a sentence with a fullstop.
No functional changes.
--- kernel/trace/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/Kconfig +2 -2
@@ -771,7 +771,7 @@ config TRACE_EVAL_MAP_FILE depends on TRACING help The "print fmt" of the trace events will show the enum/sizeof names - instead of their values. This can cause problems for user space tools + instead of their values. This can cause problems for user space tools that use this string to parse the raw data as user space does not know how to convert the string to its value.
@@ -792,7 +792,7 @@ config TRACE_EVAL_MAP_FILE they are needed for the "eval_map" file. Enabling this option will increase the memory footprint of the running kernel. - If unsure, say N + If unsure, say N. config GCOV_PROFILE_FTRACE bool "Enable GCOV profiling on ftrace subsystem"
Signature · 1 line
2.23.0