ftrace/kprobes: Setting up ftrace for kprobes
Subsystems (4)
Steven Rostedt
maintainerv3 cover ftrace/kprobes: Setting up ftrace for kprobes
This is the (hopefully) final round of RFCs, for having kprobes use ftrace as optimization. This round, I did not include Masami's patches that are on top of this, simply because I posted them twice before with no changes. I have them still on top of this series, but I'm only posting my set. The final pull request will also include Masami's.
If you are interested in Masami's changes, you can find them here:
http://marc.info/?l=linux-kernel&m=133954203218870&w=2
Patches 7 - 13 are mostly Masami's and some are mine. But none were changed in this release. I may post them again after these are reviewed.
This round, I only did the updates that Masami recommended. I did not modify the ones that he gave his 'Reviewed-by' tag, except to change the change log to have that tag.
What was changed were:
Patch 3:
Moved out the x86 changes into patch 5
Added a SAVED_REGS_IF_SUPPORTED flag, that can be set if the callback
can handle the regs parameter being NULL. If the ftrace_ops only has SAVED_REGS set, it will fail the registering if the arch does not support saving regs.
Patch 5:
Incorporated x86 changes from the previous patch 3.
Patch 6:
Have i386 restore flags on return of a function trace that saves regs.
Masami,
Can you review those patches (I believe the rest have your Reviewed-by already). Then I'll add that tag and push for a pull request.
Thanks!
-- Steve
Steven Rostedt (6):
ftrace: Pass ftrace_ops as third parameter to function trace callback
ftrace: Consolidate arch dependent functions with 'list' function
ftrace: Return pt_regs to function trace callback ftrace/x86_32: Push ftrace_ops in as 3rd parameter to function tracer ftrace/x86: Add separate function to save regs ftrace/x86: Add save_regs for i386 function calls
----
arch/x86/include/asm/ftrace.h | 47 +++++--- arch/x86/kernel/entry_32.S | 56 +++++++++ arch/x86/kernel/entry_64.S | 89 ++++++++++++-- arch/x86/kernel/ftrace.c | 73 +++++++++++- include/linux/ftrace.h | 138 ++++++++++++++++++++-- kernel/trace/ftrace.c | 236 +++++++++++++++++++++++++------------ kernel/trace/trace_event_perf.c | 3 +- kernel/trace/trace_events.c | 3 +- kernel/trace/trace_functions.c | 10 +- kernel/trace/trace_irqsoff.c | 3 +- kernel/trace/trace_sched_wakeup.c | 3 +- kernel/trace/trace_selftest.c | 20 +++- kernel/trace/trace_stack.c | 3 +- 13 files changed, 557 insertions(+), 127 deletions(-)
Steven Rostedt
maintainerPATCH v3 1/6 ftrace: Pass ftrace_ops as third parameter to function trace callback
From: Steven Rostedt <[email protected]>
Currently the function trace callback receives only the ip and parent_ip of the function that it traced. It would be more powerful to also return the ops that registered the function as well. This allows the same function to act differently depending on what ftrace_ops registered it.
--- arch/x86/include/asm/ftrace.h | 4 ++ arch/x86/kernel/entry_64.S | 1 + include/linux/ftrace.h | 16 +++++- kernel/trace/ftrace.c | 101 +++++++++++++++++++++++++------------ kernel/trace/trace_event_perf.c | 3 +- kernel/trace/trace_events.c | 3 +- kernel/trace/trace_functions.c | 9 ++-- kernel/trace/trace_irqsoff.c | 3 +- kernel/trace/trace_sched_wakeup.c | 2 +- kernel/trace/trace_selftest.c | 15 ++++-- kernel/trace/trace_stack.c | 2 +- 11 files changed, 113 insertions(+), 46 deletions(-)
arch/x86/include/asm/ftrace.h +4 -0
@@ -32,6 +32,10 @@#define MCOUNT_ADDR ((long)(mcount))#define MCOUNT_INSN_SIZE 5/* sizeof mcount call */ +#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 ) +#define ARCH_SUPPORTS_FTRACE_OPS 1 +#endif +#ifndef __ASSEMBLY__extern void mcount (void );extern atomic_t modifying_ftrace_code;
arch/x86/kernel/entry_64.S +1 -0
@@ -79,6 +79,7 @@ ENTRY(ftrace_caller) MCOUNT_SAVE_FRAME + leaq function_trace_op, %rdx movq 0x38(%rsp), %rdi movq 8(%rbp), %rsi subq $MCOUNT_INSN_SIZE, %rdi
include/linux/ftrace.h +14 -2
@@ -18,6 +18,15 @@#include <asm/ftrace.h> +/* +* If the arch supports passing the variable contents of +* function_trace_op as the third parameter back from the +* mcount call, then the arch should define this as 1. +*/ +#ifndef ARCH_SUPPORTS_FTRACE_OPS +#define ARCH_SUPPORTS_FTRACE_OPS 0 +#endif +struct module ;struct ftrace_hash ;
@@ -29,7 +38,10 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); -typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip); +struct ftrace_ops ; + +typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op);/* * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are
@@ -163,7 +175,7 @@ static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) return *this_cpu_ptr(ops->disabled); } -extern void ftrace_stub (unsigned long a0,unsigned long a1); +extern void ftrace_stub (unsigned long a0,unsigned long a1,struct ftrace_ops *op);#else /* !CONFIG_FUNCTION_TRACER */ /*
kernel/trace/ftrace.c +70 -31
216 lines not on this page · raw message
kernel/trace/trace_event_perf.c +2 -1
@@ -258,7 +258,8 @@ EXPORT_SYMBOL_GPL(perf_trace_buf_prepare);#ifdef CONFIG_FUNCTION_TRACER static void -perf_ftrace_function_call (unsigned long ip,unsigned long parent_ip) +perf_ftrace_function_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *ops) {struct ftrace_entry *entry;struct hlist_head *head;
kernel/trace/trace_events.c +2 -1
@@ -1681,7 +1681,8 @@ static __init void event_trace_self_tests(void) static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable);static void -function_test_events_call (unsigned long ip,unsigned long parent_ip) +function_test_events_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct ring_buffer_event *event;struct ring_buffer *buffer;
kernel/trace/trace_functions.c +6 -3
@@ -48,7 +48,8 @@ static void function_trace_start(struct trace_array *tr) }static void -function_trace_call_preempt_only (unsigned long ip,unsigned long parent_ip) +function_trace_call_preempt_only (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -75,7 +76,8 @@ function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip) }static void -function_trace_call (unsigned long ip,unsigned long parent_ip) +function_trace_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -106,7 +108,8 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) }static void -function_stack_trace_call (unsigned long ip,unsigned long parent_ip) +function_stack_trace_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
kernel/trace/trace_irqsoff.c +2 -1
@@ -136,7 +136,8 @@ static int func_prolog_dec(struct trace_array *tr,* irqsoff uses its own tracer function to keep the overhead down: */ static void -irqsoff_tracer_call (unsigned long ip,unsigned long parent_ip) +irqsoff_tracer_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct trace_array *tr = irqsoff_trace;struct trace_array_cpu *data;
kernel/trace/trace_sched_wakeup.c +1 -1
@@ -108,7 +108,7 @@ out_enable:* wakeup uses its own tracer function to keep the overhead down: */ static void -wakeup_tracer_call (unsigned long ip,unsigned long parent_ip) +wakeup_tracer_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) {struct trace_array *tr = wakeup_trace;struct trace_array_cpu *data;
kernel/trace/trace_selftest.c +10 -5
@@ -103,35 +103,40 @@ static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret)static int trace_selftest_test_probe1_cnt;static void trace_selftest_test_probe1_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_probe1_cnt++; }static int trace_selftest_test_probe2_cnt;static void trace_selftest_test_probe2_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_probe2_cnt++; }static int trace_selftest_test_probe3_cnt;static void trace_selftest_test_probe3_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_probe3_cnt++; }static int trace_selftest_test_global_cnt;static void trace_selftest_test_global_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_global_cnt++; }static int trace_selftest_test_dyn_cnt;static void trace_selftest_test_dyn_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_dyn_cnt++; }
kernel/trace/trace_stack.c +1 -1
@@ -111,7 +111,7 @@ static inline void check_stack(void) }static void -stack_trace_call (unsigned long ip,unsigned long parent_ip) +stack_trace_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) {int cpu;
Signature · 1 line
1.7.10
Steven Rostedt
maintainerPATCH v3 2/6 ftrace: Consolidate arch dependent functions with list function
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
As the function tracer starts to get more features, the support for theses features will spread out throughout the different architectures over time. These features boil down to what each arch does in the mcount trampoline (the ftrace_caller).
Currently there's two features that are not the same throughout the archs.
1) Support to stop function tracing before the callback
2) passing of the ftrace ops
Both of these require placing an indirect function to support the features if the mcount trampoline does not.
On a side note, for all architectures, when more than one callback is registered to the function tracer, an intermediate 'list' function is called by the mcount trampoline to iterate through the callbacks that are registered.
Instead of making a separate function for each of these features, and requiring several indirect calls, just use the single 'list' function as the intermediate, to handle all cases. If an arch does not support the 'stop function tracing' or the passing of ftrace ops, just force it to use the list function that will handle the features required.
This makes the code cleaner and simpler and removes a lot of
#ifdefs in the code.
--- include/linux/ftrace.h | 13 +++++++++++++ kernel/trace/ftrace.c | 45 ++++----------------------------------------- 2 files changed, 17 insertions(+), 41 deletions(-)
include/linux/ftrace.h +13 -0
@@ -27,6 +27,19 @@#define ARCH_SUPPORTS_FTRACE_OPS 0#endif +/* +* If the arch's mcount caller does not support all of ftrace's +* features, then it must call an indirect function that +* does. Or at least does enough to prevent any unwelcomed side effects. +*/ +#if !defined(CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST ) || \ + !ARCH_SUPPORTS_FTRACE_OPS +# define FTRACE_FORCE_LIST_FUNC 1 +#else +# define FTRACE_FORCE_LIST_FUNC 0 +#endif + +struct module ;struct ftrace_hash ;
kernel/trace/ftrace.c +4 -41
85 lines not on this page · raw message
Signature · 1 line
1.7.10
Steven Rostedt
maintainerPATCH v3 3/6 ftrace: Return pt_regs to function trace callback
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Return as the 4th paramater to the function tracer callback the pt_regs.
Later patches that implement regs passing for the architectures will require having the ftrace_ops set the SAVE_REGS flag, which will tell the arch to take the time to pass a full set of pt_regs to the ftrace_ops callback function. If the arch does not support it then it should pass NULL.
If an arch can pass full regs, then it should define:
ARCH_SUPPORTS_FTRACE_SAVE_REGS to 1
--- include/linux/ftrace.h | 6 ++++-- kernel/trace/ftrace.c | 37 ++++++++++++++++++++++--------------- kernel/trace/trace_event_perf.c | 2 +- kernel/trace/trace_events.c | 2 +- kernel/trace/trace_functions.c | 7 ++++--- kernel/trace/trace_irqsoff.c | 2 +- kernel/trace/trace_sched_wakeup.c | 3 ++- kernel/trace/trace_selftest.c | 15 ++++++++++----- kernel/trace/trace_stack.c | 3 ++- 9 files changed, 47 insertions(+), 30 deletions(-)
include/linux/ftrace.h +4 -2
@@ -10,6 +10,7 @@#include <linux/kallsyms.h> #include <linux/linkage.h> #include <linux/bitops.h> +#include <linux/ptrace.h> #include <linux/ktime.h> #include <linux/sched.h> #include <linux/types.h>
@@ -54,7 +55,7 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,struct ftrace_ops ;typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op); +struct ftrace_ops *op,struct pt_regs *regs);/* * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are
@@ -188,7 +189,8 @@ static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) return *this_cpu_ptr(ops->disabled); } -extern void ftrace_stub (unsigned long a0,unsigned long a1,struct ftrace_ops *op); +extern void ftrace_stub (unsigned long a0,unsigned long a1, +struct ftrace_ops *op,struct pt_regs *regs);#else /* !CONFIG_FUNCTION_TRACER */ /*
kernel/trace/ftrace.c +22 -15
@@ -103,7 +103,7 @@ static struct ftrace_ops control_ops;#if ARCH_SUPPORTS_FTRACE_OPS static void ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op); +struct ftrace_ops *op,struct pt_regs *regs);#else /* See comment below, where ftrace_ops_list_func is defined */ static void ftrace_ops_no_ops (unsigned long ip,unsigned long parent_ip);
@@ -121,7 +121,7 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);*/ static void ftrace_global_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (unlikely (trace_recursion_test (TRACE_GLOBAL_BIT )))return ;
@@ -129,19 +129,19 @@ ftrace_global_list_func(unsigned long ip, unsigned long parent_ip,trace_recursion_set (TRACE_GLOBAL_BIT ); op =rcu_dereference_raw (ftrace_global_list);/*see above*/ while (op != &ftrace_list_end) { - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next);/*see above*/ };trace_recursion_clear (TRACE_GLOBAL_BIT ); }static void ftrace_pid_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (!test_tsk_trace_trace (current))return ; -ftrace_pid_function (ip, parent_ip, op); +ftrace_pid_function (ip, parent_ip, op, regs); }static void set_ftrace_pid_function (ftrace_func_t func)
@@ -763,7 +763,7 @@ ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip)static void function_profile_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ops) +struct ftrace_ops *ops,struct pt_regs *regs) {struct ftrace_profile_stat *stat;struct ftrace_profile *rec;
@@ -793,7 +793,7 @@ function_profile_call(unsigned long ip, unsigned long parent_ip,#ifdef CONFIG_FUNCTION_GRAPH_TRACER static int profile_graph_entry (struct ftrace_graph_ent *trace) { -function_profile_call (trace->func,0 ,NULL ); +function_profile_call (trace->func,0 ,NULL ,NULL );return 1 ; }
@@ -2771,7 +2771,7 @@ static int __init ftrace_mod_cmd_init(void)device_initcall (ftrace_mod_cmd_init);static void function_trace_probe_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct ftrace_func_probe *entry;struct hlist_head *hhd;
@@ -3923,7 +3923,7 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)static void ftrace_ops_control_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (unlikely (trace_recursion_test (TRACE_CONTROL_BIT )))return ;
@@ -3938,7 +3938,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,while (op != &ftrace_list_end) {if (!ftrace_function_local_disabled (op) &&ftrace_ops_test (op, ip)) - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next); };
@@ -3952,7 +3952,7 @@ static struct ftrace_ops control_ops = {static inline void __ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ignored) +struct ftrace_ops *ignored,struct pt_regs *regs) {struct ftrace_ops *op;
@@ -3971,7 +3971,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, op =rcu_dereference_raw (ftrace_ops_list);while (op != &ftrace_list_end) {if (ftrace_ops_test (op, ip)) - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next); };preempt_enable_notrace ();
@@ -3983,17 +3983,24 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,* the list function ignores the op parameter, we do not want any * C side effects, where a function is called without the caller * sending a third parameter. +* Archs are to support both the regs and ftrace_ops at the same time. +* If they support ftrace_ops, it is assumed they support regs. +* If call backs want to use regs, they must either check for regs +* being NULL, or ARCH_SUPPORTS_FTRACE_SAVE_REGS. +* Note, ARCH_SUPPORT_SAVE_REGS expects a full regs to be saved. +* An architecture can pass partial regs with ftrace_ops and still +* set the ARCH_SUPPORT_FTARCE_OPS. */ #if ARCH_SUPPORTS_FTRACE_OPS static void ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) { -__ftrace_ops_list_func (ip, parent_ip,NULL ); +__ftrace_ops_list_func (ip, parent_ip,NULL , regs); }#else static void ftrace_ops_no_ops (unsigned long ip,unsigned long parent_ip) { -__ftrace_ops_list_func (ip, parent_ip,NULL ); +__ftrace_ops_list_func (ip, parent_ip,NULL ,NULL ); }#endif
kernel/trace/trace_event_perf.c +1 -1
@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(perf_trace_buf_prepare);#ifdef CONFIG_FUNCTION_TRACER static void perf_ftrace_function_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ops) +struct ftrace_ops *ops,struct pt_regs *pt_regs) {struct ftrace_entry *entry;struct hlist_head *head;
kernel/trace/trace_events.c +1 -1
@@ -1682,7 +1682,7 @@ static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable);static void function_test_events_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct ring_buffer_event *event;struct ring_buffer *buffer;
kernel/trace/trace_functions.c +4 -3
@@ -49,7 +49,7 @@ static void function_trace_start(struct trace_array *tr)static void function_trace_call_preempt_only (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -77,7 +77,8 @@ function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip,static void function_trace_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) + {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -109,7 +110,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,static void function_stack_trace_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
kernel/trace/trace_irqsoff.c +1 -1
@@ -137,7 +137,7 @@ static int func_prolog_dec(struct trace_array *tr,*/ static void irqsoff_tracer_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = irqsoff_trace;struct trace_array_cpu *data;
kernel/trace/trace_sched_wakeup.c +2 -1
@@ -108,7 +108,8 @@ out_enable:* wakeup uses its own tracer function to keep the overhead down: */ static void -wakeup_tracer_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) +wakeup_tracer_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = wakeup_trace;struct trace_array_cpu *data;
kernel/trace/trace_selftest.c +10 -5
@@ -104,7 +104,8 @@ static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret)static int trace_selftest_test_probe1_cnt;static void trace_selftest_test_probe1_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe1_cnt++; }
@@ -112,7 +113,8 @@ static void trace_selftest_test_probe1_func(unsigned long ip,static int trace_selftest_test_probe2_cnt;static void trace_selftest_test_probe2_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe2_cnt++; }
@@ -120,7 +122,8 @@ static void trace_selftest_test_probe2_func(unsigned long ip,static int trace_selftest_test_probe3_cnt;static void trace_selftest_test_probe3_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe3_cnt++; }
@@ -128,7 +131,8 @@ static void trace_selftest_test_probe3_func(unsigned long ip,static int trace_selftest_test_global_cnt;static void trace_selftest_test_global_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_global_cnt++; }
@@ -136,7 +140,8 @@ static void trace_selftest_test_global_func(unsigned long ip,static int trace_selftest_test_dyn_cnt;static void trace_selftest_test_dyn_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_dyn_cnt++; }
kernel/trace/trace_stack.c +2 -1
@@ -111,7 +111,8 @@ static inline void check_stack(void) }static void -stack_trace_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) +stack_trace_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) {int cpu;
Signature · 1 line
1.7.10
Re: [PATCH 3/6] ftrace: Return pt_regs to function trace callback
Quoted 9 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Return as the 4th paramater to the function tracer callback the
pt_regs.Later patches that implement regs passing for the architectures will require having the
ftrace_opsset theSAVE_REGSflag, which will tell the arch to take the time to pass a full set ofpt_regsto theftrace_opscallback function. If the arch does not support it then it should pass NULL.
This looks good for me:)
Quoted 2 lines
If an arch can pass full regs, then it should define:
ARCH_SUPPORTS_FTRACE_SAVE_REGSto 1
I just think this would better be commented on 5/6, since actual arch-independent parts of that feature is not implemented yet on this patch.(just interface is changed)
Quoted 335 lines
Signed-off-by Steven Rostedt <[email protected]>--- include/linux/ftrace.h | 6 ++++-- kernel/trace/ftrace.c | 37 ++++++++++++++++++++++--------------- kernel/trace/trace_event_perf.c | 2 +- kernel/trace/trace_events.c | 2 +- kernel/trace/trace_functions.c | 7 ++++--- kernel/trace/trace_irqsoff.c | 2 +- kernel/trace/trace_sched_wakeup.c | 3 ++- kernel/trace/trace_selftest.c | 15 ++++++++++----- kernel/trace/trace_stack.c | 3 ++- 9 files changed, 47 insertions(+), 30 deletions(-)include/linux/ftrace.h +4
-2@@ -10,6 +10,7 @@#include <linux/kallsyms.h> #include <linux/linkage.h> #include <linux/bitops.h> +#include <linux/ptrace.h> #include <linux/ktime.h> #include <linux/sched.h> #include <linux/types.h> @@ -54,7 +55,7 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,struct ftrace_ops ;typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op); +struct ftrace_ops *op,struct pt_regs *regs);/* * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are @@ -188,7 +189,8 @@ static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) return *this_cpu_ptr(ops->disabled); } -extern void ftrace_stub (unsigned long a0,unsigned long a1,struct ftrace_ops *op); +extern void ftrace_stub (unsigned long a0,unsigned long a1, +struct ftrace_ops *op,struct pt_regs *regs);#else /* !CONFIG_FUNCTION_TRACER */ /* kernel/trace/ftrace.c +22
-15@@ -103,7 +103,7 @@ static struct ftrace_ops control_ops;#if ARCH_SUPPORTS_FTRACE_OPS static void ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op); +struct ftrace_ops *op,struct pt_regs *regs);#else /* See comment below, where ftrace_ops_list_func is defined */ static void ftrace_ops_no_ops (unsigned long ip,unsigned long parent_ip);@@ -121,7 +121,7 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);*/ static void ftrace_global_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (unlikely (trace_recursion_test (TRACE_GLOBAL_BIT )))return ;@@ -129,19 +129,19 @@ ftrace_global_list_func(unsigned long ip, unsigned long parent_ip,trace_recursion_set (TRACE_GLOBAL_BIT ); op =rcu_dereference_raw (ftrace_global_list);/*see above*/ while (op != &ftrace_list_end) { - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next);/*see above*/ };trace_recursion_clear (TRACE_GLOBAL_BIT ); }static void ftrace_pid_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (!test_tsk_trace_trace (current))return ; -ftrace_pid_function (ip, parent_ip, op); +ftrace_pid_function (ip, parent_ip, op, regs); }static void set_ftrace_pid_function (ftrace_func_t func)@@ -763,7 +763,7 @@ ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip)static void function_profile_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ops) +struct ftrace_ops *ops,struct pt_regs *regs) {struct ftrace_profile_stat *stat;struct ftrace_profile *rec;@@ -793,7 +793,7 @@ function_profile_call(unsigned long ip, unsigned long parent_ip,#ifdef CONFIG_FUNCTION_GRAPH_TRACER static int profile_graph_entry (struct ftrace_graph_ent *trace) { -function_profile_call (trace->func,0 ,NULL ); +function_profile_call (trace->func,0 ,NULL ,NULL );return 1 ; }@@ -2771,7 +2771,7 @@ static int __init ftrace_mod_cmd_init(void)device_initcall (ftrace_mod_cmd_init);static void function_trace_probe_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct ftrace_func_probe *entry;struct hlist_head *hhd;@@ -3923,7 +3923,7 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)static void ftrace_ops_control_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (unlikely (trace_recursion_test (TRACE_CONTROL_BIT )))return ;@@ -3938,7 +3938,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,while (op != &ftrace_list_end) {if (!ftrace_function_local_disabled (op) &&ftrace_ops_test (op, ip)) - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next); };@@ -3952,7 +3952,7 @@ static struct ftrace_ops control_ops = {static inline void __ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ignored) +struct ftrace_ops *ignored,struct pt_regs *regs) {struct ftrace_ops *op;@@ -3971,7 +3971,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, op =rcu_dereference_raw (ftrace_ops_list);while (op != &ftrace_list_end) {if (ftrace_ops_test (op, ip)) - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next); };preempt_enable_notrace ();@@ -3983,17 +3983,24 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,* the list function ignores the op parameter, we do not want any * C side effects, where a function is called without the caller * sending a third parameter. +* Archs are to support both the regs and ftrace_ops at the same time. +* If they support ftrace_ops, it is assumed they support regs. +* If call backs want to use regs, they must either check for regs +* being NULL, or ARCH_SUPPORTS_FTRACE_SAVE_REGS. +* Note, ARCH_SUPPORT_SAVE_REGS expects a full regs to be saved. +* An architecture can pass partial regs with ftrace_ops and still +* set the ARCH_SUPPORT_FTARCE_OPS. */ #if ARCH_SUPPORTS_FTRACE_OPS static void ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) { -__ftrace_ops_list_func (ip, parent_ip,NULL ); +__ftrace_ops_list_func (ip, parent_ip,NULL , regs); }#else static void ftrace_ops_no_ops (unsigned long ip,unsigned long parent_ip) { -__ftrace_ops_list_func (ip, parent_ip,NULL ); +__ftrace_ops_list_func (ip, parent_ip,NULL ,NULL ); }#endif kernel/trace/trace_event_perf.c +1
-1@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(perf_trace_buf_prepare);#ifdef CONFIG_FUNCTION_TRACER static void perf_ftrace_function_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ops) +struct ftrace_ops *ops,struct pt_regs *pt_regs) {struct ftrace_entry *entry;struct hlist_head *head;kernel/trace/trace_events.c +1
-1@@ -1682,7 +1682,7 @@ static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable);static void function_test_events_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct ring_buffer_event *event;struct ring_buffer *buffer;kernel/trace/trace_functions.c +4
-3@@ -49,7 +49,7 @@ static void function_trace_start(struct trace_array *tr)static void function_trace_call_preempt_only (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;@@ -77,7 +77,8 @@ function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip,static void function_trace_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) + {struct trace_array *tr = func_trace;struct trace_array_cpu *data;@@ -109,7 +110,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,static void function_stack_trace_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;kernel/trace/trace_irqsoff.c +1
-1@@ -137,7 +137,7 @@ static int func_prolog_dec(struct trace_array *tr,*/ static void irqsoff_tracer_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = irqsoff_trace;struct trace_array_cpu *data;kernel/trace/trace_sched_wakeup.c +2
-1@@ -108,7 +108,8 @@ out_enable:* wakeup uses its own tracer function to keep the overhead down: */ static void -wakeup_tracer_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) +wakeup_tracer_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = wakeup_trace;struct trace_array_cpu *data;kernel/trace/trace_selftest.c +10
-5@@ -104,7 +104,8 @@ static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret)static int trace_selftest_test_probe1_cnt;static void trace_selftest_test_probe1_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe1_cnt++; }@@ -112,7 +113,8 @@ static void trace_selftest_test_probe1_func(unsigned long ip,static int trace_selftest_test_probe2_cnt;static void trace_selftest_test_probe2_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe2_cnt++; }@@ -120,7 +122,8 @@ static void trace_selftest_test_probe2_func(unsigned long ip,static int trace_selftest_test_probe3_cnt;static void trace_selftest_test_probe3_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe3_cnt++; }@@ -128,7 +131,8 @@ static void trace_selftest_test_probe3_func(unsigned long ip,static int trace_selftest_test_global_cnt;static void trace_selftest_test_global_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_global_cnt++; }@@ -136,7 +140,8 @@ static void trace_selftest_test_global_func(unsigned long ip,static int trace_selftest_test_dyn_cnt;static void trace_selftest_test_dyn_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_dyn_cnt++; }kernel/trace/trace_stack.c +2
-1@@ -111,7 +111,8 @@ static inline void check_stack(void) }static void -stack_trace_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) +stack_trace_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) {int cpu;
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: [PATCH 3/6] ftrace: Return pt_regs to function trace callback
Quoted 13 lines · Masami Hiramatsu
Quoted 9 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Return as the 4th paramater to the function tracer callback the
pt_regs.Later patches that implement regs passing for the architectures will require having the
ftrace_opsset theSAVE_REGSflag, which will tell the arch to take the time to pass a full set ofpt_regsto theftrace_opscallback function. If the arch does not support it then it should pass NULL.This looks good for me:)
Quoted 9 lines
Reviewed-by Masami Hiramatsu <[email protected]>Quoted 2 lines
If an arch can pass full regs, then it should define:
ARCH_SUPPORTS_FTRACE_SAVE_REGSto 1I just think this would better be commented on 5/6, since actual arch-independent parts of that feature is not implemented yet on this patch.(just interface is changed)
Sure, but this variable is referenced in this patch. Yes, no arch code is implemented, but documenting that it needs to be set for this change here does help. Other arch developers that look at these changes and want to know about it can see this change and investigate further.
But this is just the change log, I'm assuming the patch is fine as you gave your reviewed by tag.
Thanks,
-- Steve
[tip:perf/core] ftrace: Return pt_regs to function trace callback
In reply to Steven RostedtCommit-ID: a1e2e31d175a1349274eba3465d17616c6725f8c Gitweb: http://git.kernel.org/tip/a1e2e31d175a1349274eba3465d17616c6725f8c Author: Steven Rostedt <[email protected]> AuthorDate: Tue, 9 Aug 2011 12:50:46 -0400 Committer: Steven Rostedt <[email protected]> CommitDate: Thu, 19 Jul 2012 13:18:49 -0400
ftrace: Return pt_regs to function trace callback
Return as the 4th paramater to the function tracer callback the pt_regs.
Later patches that implement regs passing for the architectures will require having the ftrace_ops set the SAVE_REGS flag, which will tell the arch to take the time to pass a full set of pt_regs to the ftrace_ops callback function. If the arch does not support it then it should pass NULL.
If an arch can pass full regs, then it should define:
ARCH_SUPPORTS_FTRACE_SAVE_REGS to 1
--- include/linux/ftrace.h | 6 ++++-- kernel/trace/ftrace.c | 37 ++++++++++++++++++++++--------------- kernel/trace/trace_event_perf.c | 2 +- kernel/trace/trace_events.c | 2 +- kernel/trace/trace_functions.c | 7 ++++--- kernel/trace/trace_irqsoff.c | 2 +- kernel/trace/trace_sched_wakeup.c | 3 ++- kernel/trace/trace_selftest.c | 15 ++++++++++----- kernel/trace/trace_stack.c | 3 ++- 9 files changed, 47 insertions(+), 30 deletions(-)
include/linux/ftrace.h +4 -2
@@ -10,6 +10,7 @@#include <linux/kallsyms.h> #include <linux/linkage.h> #include <linux/bitops.h> +#include <linux/ptrace.h> #include <linux/ktime.h> #include <linux/sched.h> #include <linux/types.h>
@@ -54,7 +55,7 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,struct ftrace_ops ;typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op); +struct ftrace_ops *op,struct pt_regs *regs);/* * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are
@@ -188,7 +189,8 @@ static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) return *this_cpu_ptr(ops->disabled); } -extern void ftrace_stub (unsigned long a0,unsigned long a1,struct ftrace_ops *op); +extern void ftrace_stub (unsigned long a0,unsigned long a1, +struct ftrace_ops *op,struct pt_regs *regs);#else /* !CONFIG_FUNCTION_TRACER */ /*
kernel/trace/ftrace.c +22 -15
@@ -103,7 +103,7 @@ static struct ftrace_ops control_ops;#if ARCH_SUPPORTS_FTRACE_OPS static void ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op); +struct ftrace_ops *op,struct pt_regs *regs);#else /* See comment below, where ftrace_ops_list_func is defined */ static void ftrace_ops_no_ops (unsigned long ip,unsigned long parent_ip);
@@ -121,7 +121,7 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);*/ static void ftrace_global_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (unlikely (trace_recursion_test (TRACE_GLOBAL_BIT )))return ;
@@ -129,19 +129,19 @@ ftrace_global_list_func(unsigned long ip, unsigned long parent_ip,trace_recursion_set (TRACE_GLOBAL_BIT ); op =rcu_dereference_raw (ftrace_global_list);/*see above*/ while (op != &ftrace_list_end) { - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next);/*see above*/ };trace_recursion_clear (TRACE_GLOBAL_BIT ); }static void ftrace_pid_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (!test_tsk_trace_trace (current))return ; -ftrace_pid_function (ip, parent_ip, op); +ftrace_pid_function (ip, parent_ip, op, regs); }static void set_ftrace_pid_function (ftrace_func_t func)
@@ -763,7 +763,7 @@ ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip)static void function_profile_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ops) +struct ftrace_ops *ops,struct pt_regs *regs) {struct ftrace_profile_stat *stat;struct ftrace_profile *rec;
@@ -793,7 +793,7 @@ function_profile_call(unsigned long ip, unsigned long parent_ip,#ifdef CONFIG_FUNCTION_GRAPH_TRACER static int profile_graph_entry (struct ftrace_graph_ent *trace) { -function_profile_call (trace->func,0 ,NULL ); +function_profile_call (trace->func,0 ,NULL ,NULL );return 1 ; }
@@ -2771,7 +2771,7 @@ static int __init ftrace_mod_cmd_init(void)device_initcall (ftrace_mod_cmd_init);static void function_trace_probe_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct ftrace_func_probe *entry;struct hlist_head *hhd;
@@ -3923,7 +3923,7 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)static void ftrace_ops_control_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) {if (unlikely (trace_recursion_test (TRACE_CONTROL_BIT )))return ;
@@ -3938,7 +3938,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,while (op != &ftrace_list_end) {if (!ftrace_function_local_disabled (op) &&ftrace_ops_test (op, ip)) - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next); };
@@ -3952,7 +3952,7 @@ static struct ftrace_ops control_ops = {static inline void __ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ignored) +struct ftrace_ops *ignored,struct pt_regs *regs) {struct ftrace_ops *op;
@@ -3971,7 +3971,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, op =rcu_dereference_raw (ftrace_ops_list);while (op != &ftrace_list_end) {if (ftrace_ops_test (op, ip)) - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, regs); op =rcu_dereference_raw (op->next); };preempt_enable_notrace ();
@@ -3983,17 +3983,24 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,* the list function ignores the op parameter, we do not want any * C side effects, where a function is called without the caller * sending a third parameter. +* Archs are to support both the regs and ftrace_ops at the same time. +* If they support ftrace_ops, it is assumed they support regs. +* If call backs want to use regs, they must either check for regs +* being NULL, or ARCH_SUPPORTS_FTRACE_SAVE_REGS. +* Note, ARCH_SUPPORT_SAVE_REGS expects a full regs to be saved. +* An architecture can pass partial regs with ftrace_ops and still +* set the ARCH_SUPPORT_FTARCE_OPS. */ #if ARCH_SUPPORTS_FTRACE_OPS static void ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *regs) { -__ftrace_ops_list_func (ip, parent_ip,NULL ); +__ftrace_ops_list_func (ip, parent_ip,NULL , regs); }#else static void ftrace_ops_no_ops (unsigned long ip,unsigned long parent_ip) { -__ftrace_ops_list_func (ip, parent_ip,NULL ); +__ftrace_ops_list_func (ip, parent_ip,NULL ,NULL ); }#endif
kernel/trace/trace_event_perf.c +1 -1
@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(perf_trace_buf_prepare);#ifdef CONFIG_FUNCTION_TRACER static void perf_ftrace_function_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *ops) +struct ftrace_ops *ops,struct pt_regs *pt_regs) {struct ftrace_entry *entry;struct hlist_head *head;
kernel/trace/trace_events.c +1 -1
@@ -1682,7 +1682,7 @@ static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable);static void function_test_events_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct ring_buffer_event *event;struct ring_buffer *buffer;
kernel/trace/trace_functions.c +4 -3
@@ -49,7 +49,7 @@ static void function_trace_start(struct trace_array *tr)static void function_trace_call_preempt_only (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -77,7 +77,8 @@ function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip,static void function_trace_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) + {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -109,7 +110,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,static void function_stack_trace_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
kernel/trace/trace_irqsoff.c +1 -1
@@ -137,7 +137,7 @@ static int func_prolog_dec(struct trace_array *tr,*/ static void irqsoff_tracer_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = irqsoff_trace;struct trace_array_cpu *data;
kernel/trace/trace_sched_wakeup.c +2 -1
@@ -108,7 +108,8 @@ out_enable:* wakeup uses its own tracer function to keep the overhead down: */ static void -wakeup_tracer_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) +wakeup_tracer_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = wakeup_trace;struct trace_array_cpu *data;
kernel/trace/trace_selftest.c +10 -5
@@ -104,7 +104,8 @@ static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret)static int trace_selftest_test_probe1_cnt;static void trace_selftest_test_probe1_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe1_cnt++; }
@@ -112,7 +113,8 @@ static void trace_selftest_test_probe1_func(unsigned long ip,static int trace_selftest_test_probe2_cnt;static void trace_selftest_test_probe2_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe2_cnt++; }
@@ -120,7 +122,8 @@ static void trace_selftest_test_probe2_func(unsigned long ip,static int trace_selftest_test_probe3_cnt;static void trace_selftest_test_probe3_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe3_cnt++; }
@@ -128,7 +131,8 @@ static void trace_selftest_test_probe3_func(unsigned long ip,static int trace_selftest_test_global_cnt;static void trace_selftest_test_global_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_global_cnt++; }
@@ -136,7 +140,8 @@ static void trace_selftest_test_global_func(unsigned long ip,static int trace_selftest_test_dyn_cnt;static void trace_selftest_test_dyn_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_dyn_cnt++; }
kernel/trace/trace_stack.c +2 -1
@@ -111,7 +111,8 @@ static inline void check_stack(void) }static void -stack_trace_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) +stack_trace_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) {int cpu;
Steven Rostedt
maintainerPATCH v3 4/6 ftrace/x86_32: Push ftrace_ops in as 3rd parameter to function tracer
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Add support of passing the current ftrace_ops into the 3rd parameter of the callback to the function tracer.
--- arch/x86/include/asm/ftrace.h | 2 +- arch/x86/kernel/entry_32.S | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
arch/x86/include/asm/ftrace.h +1 -1
@@ -32,7 +32,7 @@#define MCOUNT_ADDR ((long)(mcount))#define MCOUNT_INSN_SIZE 5/* sizeof mcount call */ -#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 ) +#ifdef CONFIG_DYNAMIC_FTRACE #define ARCH_SUPPORTS_FTRACE_OPS 1#endif
arch/x86/kernel/entry_32.S +1 -0
@@ -1111,6 +1111,7 @@ ENTRY(ftrace_caller) pushl %edx movl 0xc(%esp), %eax movl 0x4(%ebp), %edx + leal function_trace_op, %ecx subl $MCOUNT_INSN_SIZE, %eax .globl ftrace_call
Signature · 1 line
1.7.10
Steven Rostedt
maintainerPATCH v3 5/6 ftrace/x86: Add separate function to save regs
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Add a way to have different functions calling different trampolines. If a ftrace_ops wants regs saved on the return, then have only the functions with ops registered to save regs. Functions registered by other ops would not be affected, unless the functions overlap.
If one ftrace_ops registered functions A, B and C and another ops registered fucntions to save regs on A, and D, then only functions A and D would be saving regs. Function B and C would work as normal. Although A is registered by both ops: normal and saves regs; this is fine as saving the regs is needed to satisfy one of the ops that calls it but the regs are ignored by the other ops function.
x86_64 implements the full regs saving, and i386 just passes a NULL for regs to satisfy the ftrace_ops passing. Where an arch must supply both regs and ftrace_ops parameters, even if regs is just NULL.
It is OK for an arch to pass NULL regs. All function trace users that require regs passing must add the flag FTRACE_OPS_FL_SAVE_REGS when registering the ftrace_ops. If the arch does not support saving regs then the ftrace_ops will fail to register. The flag FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED may be set that will prevent the ftrace_ops from failing to register. In this case, the handler may either check if regs is not NULL or check if ARCH_SUPPORTS_FTRACE_SAVE_REGS. If the arch supports passing regs it will set this macro and pass regs for ops that request them. All other archs will just pass NULL.
--- arch/x86/include/asm/ftrace.h | 45 ++++++++++------- arch/x86/kernel/entry_32.S | 2 + arch/x86/kernel/entry_64.S | 90 +++++++++++++++++++++++++++++++--- arch/x86/kernel/ftrace.c | 77 +++++++++++++++++++++++++++-- include/linux/ftrace.h | 107 ++++++++++++++++++++++++++++++++++++++--- kernel/trace/ftrace.c | 91 ++++++++++++++++++++++++++++++++--- 6 files changed, 367 insertions(+), 45 deletions(-)
arch/x86/include/asm/ftrace.h +27 -18
@@ -3,27 +3,33 @@#ifdef __ASSEMBLY__ - .macro MCOUNT_SAVE_FRAME - /* taken from glibc */ - subq $0x38, %rsp - movq %rax, (%rsp) - movq %rcx, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rsi, 24(%rsp) - movq %rdi, 32(%rsp) - movq %r8, 40(%rsp) - movq %r9, 48(%rsp) +/* skip is set if the stack was already partially adjusted */ + .macro MCOUNT_SAVE_FRAME skip=0 +/* +* We add enough stack to save all regs. + */ + subq $(SS+8-\skip), %rsp + movq %rax, RAX(%rsp) + movq %rcx, RCX(%rsp) + movq %rdx, RDX(%rsp) + movq %rsi, RSI(%rsp) + movq %rdi, RDI(%rsp) + movq %r8, R8(%rsp) + movq %r9, R9(%rsp) + /* Move RIP to its proper location */ + movq SS+8(%rsp), %rdx + movq %rdx, RIP(%rsp) .endm .macro MCOUNT_RESTORE_FRAME - movq 48(%rsp), %r9 - movq 40(%rsp), %r8 - movq 32(%rsp), %rdi - movq 24(%rsp), %rsi - movq 16(%rsp), %rdx - movq 8(%rsp), %rcx - movq (%rsp), %rax - addq $0x38, %rsp + movq R9(%rsp), %r9 + movq R8(%rsp), %r8 + movq RDI(%rsp), %rdi + movq RSI(%rsp), %rsi + movq RDX(%rsp), %rdx + movq RCX(%rsp), %rcx + movq RAX(%rsp), %rax + addq $(SS+8), %rsp .endm #endif
@@ -34,6 +40,9 @@#ifdef CONFIG_DYNAMIC_FTRACE #define ARCH_SUPPORTS_FTRACE_OPS 1 +#ifdef CONFIG_X86_64 +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS +#endif #endif #ifndef __ASSEMBLY__
arch/x86/kernel/entry_32.S +2 -0
@@ -1109,6 +1109,7 @@ ENTRY(ftrace_caller) pushl %eax pushl %ecx pushl %edx + pushl $0 /* Pass NULL as regs pointer */ movl 0xc(%esp), %eax movl 0x4(%ebp), %edx leal function_trace_op, %ecx
@@ -1118,6 +1119,7 @@ ENTRY(ftrace_caller) ftrace_call: call ftrace_stub + addl $4,%esp /* skip NULL pointer */ popl %edx popl %ecx popl %eax
arch/x86/kernel/entry_64.S +82 -8
123 lines not on this page · raw message
arch/x86/kernel/ftrace.c +73 -4
141 lines not on this page · raw message
include/linux/ftrace.h +100 -7
152 lines not on this page · raw message
kernel/trace/ftrace.c +83 -8
140 lines not on this page · raw message
Signature · 1 line
1.7.10
Re: [PATCH 5/6] ftrace/x86: Add separate function to save regs
Quoted 18 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Add a way to have different functions calling different trampolines. If a
ftrace_opswants regs saved on the return, then have only the functions with ops registered to save regs. Functions registered by other ops would not be affected, unless the functions overlap.If one
ftrace_opsregistered functions A, B and C and another ops registered fucntions to save regs on A, and D, then only functions A and D would be saving regs. Function B and C would work as normal. Although A is registered by both ops: normal and saves regs; this is fine as saving the regs is needed to satisfy one of the ops that calls it but the regs are ignored by the other ops function.
x86_64implements the full regs saving, and i386 just passes a NULL for regs to satisfy theftrace_opspassing. Where an arch must supply both regs andftrace_opsparameters, even if regs is just NULL.
Quoted 9 lines
It is OK for an arch to pass NULL regs. All function trace users that require regs passing must add the flag
FTRACE_OPS_FL_SAVE_REGSwhen registering theftrace_ops. If the arch does not support saving regs then theftrace_opswill fail to register. The flagFTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTEDmay be set that will prevent theftrace_opsfrom failing to register. In this case, the handler may either check if regs is not NULL or check ifARCH_SUPPORTS_FTRACE_SAVE_REGS. If the arch supports passing regs it will set this macro and pass regs for ops that request them. All other archs will just pass NULL.
This is nice for me :)
It helps me to maintain kprobes on ftrace.
[...]
Quoted 48 lines
arch/x86/kernel/entry_64.S +44
-0@@ -98,6 +111,67 @@ GLOBAL(ftrace_stub) retq END(ftrace_caller) +ENTRY(ftrace_regs_caller) + /* Save the current flags before compare (in SS location)*/ + pushfq + + /* Check if tracing was disabled (quick check) */ + cmpl $0, function_trace_stop + jne ftrace_restore_flags + + /* skip=8 to skip flags saved in SS */ + ftrace_caller_setup 8 + + /* Save the rest of pt_regs */ + movq %r15, R15(%rsp) + movq %r14, R14(%rsp) + movq %r13, R13(%rsp) + movq %r12, R12(%rsp) + movq %r11, R11(%rsp) + movq %r10, R10(%rsp) + movq %rbp, RBP(%rsp) + movq %rbx, RBX(%rsp) + /* Copy saved flags */ + movq SS(%rsp), %rcx + movq %rcx, EFLAGS(%rsp) + /* Kernel segments */ + movq $__KERNEL_DS, %rcx + movq %rcx, SS(%rsp) + movq $__KERNEL_CS, %rcx + movq %rcx, CS(%rsp) + /* Stack - skipping return address */ + leaq SS+16(%rsp), %rcx + movq %rcx, RSP(%rsp) + + /* regs go into 4th parameter */ + leaq (%rsp), %rcx + +GLOBAL(ftrace_regs_call) + call ftrace_stub + + /* restore the rest of pt_regs */ + movq R15(%rsp), %r15 + movq R14(%rsp), %r14 + movq R13(%rsp), %r13 + movq R12(%rsp), %r12 + movq R10(%rsp), %r10
arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 167
Quoted 10 lines
arch/x86/kernel/entry_64.S +8
-0+ movq RBP(%rsp), %rbp + movq RBX(%rsp), %rbx + + /* Restore flags */ + pushq EFLAGS(%rsp) + popfq + + MCOUNT_RESTORE_FRAME
Here, if MCOUNT_RESTORE_FRAME has skip too, I think you don't need to restore flags before restoring other registers, like below;
MCOUNT_RESTORE_FRAME 8
popfq
And also, this will prevent to modify flags before return by addq in MCOUNT_RESTORE_FRAME.
arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 173
Quoted 8 lines
arch/x86/kernel/entry_64.S +8
-0+ + jmp ftrace_return +ftrace_restore_flags: + popfq + jmp ftrace_stub + +END(ftrace_regs_caller) +
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: [PATCH 5/6] ftrace/x86: Add separate function to save regs
Quoted 11 lines · Masami Hiramatsu
arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 165
Quoted 6 lines
arch/x86/kernel/entry_64.S +5
-0+ /* Restore flags */ + pushq EFLAGS(%rsp) + popfq + + MCOUNT_RESTORE_FRAMEHere, if
MCOUNT_RESTORE_FRAMEhas skip too, I think you don't need to restore flags before restoring other registers, like below;
Quoted 5 lines
MCOUNT_RESTORE_FRAME8
popfqAnd also, this will prevent to modify flags before return by addq in
MCOUNT_RESTORE_FRAME.
Ah, because the addq will modify flags :-/
Grumble, I guess I should implement this, even though it will make it a little more complex. I thought it was better to restore flags explicitly, but that's not the case.
OK, I'll make the update. As MCOUNT_SAVE_FRAME has the skip, I guess it's not so bad to have restore have it too.
-- Steve
Quoted 13 lines
arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 173
Quoted 9 lines
arch/x86/kernel/entry_64.S +8
-0+ + jmp ftrace_return +ftrace_restore_flags: + popfq + jmp ftrace_stub + +END(ftrace_regs_caller) +Thank you,
Steven Rostedt
maintainerRe: [PATCH 5/6] ftrace/x86: Add separate function to save regs
Quoted 17 lines · Steven Rostedt
Quoted 14 lines · Masami Hiramatsu
arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 165
Quoted 6 lines
arch/x86/kernel/entry_64.S +5
-0+ /* Restore flags */ + pushq EFLAGS(%rsp) + popfq + + MCOUNT_RESTORE_FRAMEHere, if
MCOUNT_RESTORE_FRAMEhas skip too, I think you don't need to restore flags before restoring other registers, like below;
MCOUNT_RESTORE_FRAME8
popfq
Quoted 9 lines
Quoted 2 lines
And also, this will prevent to modify flags before return by addq in
MCOUNT_RESTORE_FRAME.Ah, because the addq will modify flags :-/
Grumble, I guess I should implement this, even though it will make it a little more complex. I thought it was better to restore flags explicitly, but that's not the case.
I know why I did this. Do you want kprobes to be able to modify flags? If so, then I need to add, before the restore:
movq EFLAGS(%rsp), %rax movq %rax, SS(%rsp)
-- Steve
Re: [PATCH 5/6] ftrace/x86: Add separate function to save regs
Quoted 28 lines · Steven Rostedt
Quoted 17 lines · Steven Rostedt
Quoted 14 lines · Masami Hiramatsu
arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 165
Quoted 6 lines
arch/x86/kernel/entry_64.S +5
-0+ /* Restore flags */ + pushq EFLAGS(%rsp) + popfq + + MCOUNT_RESTORE_FRAMEHere, if
MCOUNT_RESTORE_FRAMEhas skip too, I think you don't need to restore flags before restoring other registers, like below;
MCOUNT_RESTORE_FRAME8
popfqQuoted 9 lines
Quoted 2 lines
And also, this will prevent to modify flags before return by addq in
MCOUNT_RESTORE_FRAME.Ah, because the addq will modify flags :-/
Grumble, I guess I should implement this, even though it will make it a little more complex. I thought it was better to restore flags explicitly, but that's not the case.
Quoted 5 lines
I know why I did this. Do you want kprobes to be able to modify flags? If so, then I need to add, before the restore:
movq EFLAGS(%rsp), %rax movq %rax, SS(%rsp)
Yes, kprobes might be used for modifying flags, so, please :)
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Re: [PATCH 5/6] ftrace/x86: Add separate function to save regs
In reply to Steven RostedtQuoted 3 lines · Steven Rostedt
Email had 1 attachment:
+ 0005-ftrace-x86-Add-separate-function-to-save-regs.patch 23k (text/plain)
Hi Steven,
One thing that caught my eye...
arch/x86/kernel/entry_32.S ENTRY(ftrace_caller) · line 1113
Quoted 10 lines
arch/x86/kernel/entry_32.S +1
-0@@ -1109,6 +1109,7 @@ ENTRY(ftrace_caller) pushl %eax pushl %ecx pushl %edx + pushl $0 /* Pass NULL as regs pointer */ movl 0xc(%esp), %eax
This should now be changed to "0x10(%esp)", right?
Greetings,
Alexander
Quoted 10 lines
arch/x86/kernel/entry_32.S +1
-0movl 0x4(%ebp), %edx leal function_trace_op, %ecx@@ -1118,6 +1119,7 @@ ENTRY(ftrace_caller) ftrace_call: call ftrace_stub + addl $4,%esp /* skip NULL pointer */ popl %edx popl %ecx popl %eax
Steven Rostedt
maintainerRe: [PATCH 5/6] ftrace/x86: Add separate function to save regs
Quoted 9 lines · Alexander van Heukelum
Quoted 3 lines · Steven Rostedt
Email had 1 attachment:
+ 0005-ftrace-x86-Add-separate-function-to-save-regs.patch 23k (text/plain)Hi Steven,
One thing that caught my eye...
Quoted 12 lines
arch/x86/kernel/entry_32.S ENTRY(ftrace_caller) · line 1113
Quoted 10 lines
arch/x86/kernel/entry_32.S +1
-0@@ -1109,6 +1109,7 @@ ENTRY(ftrace_caller) pushl %eax pushl %ecx pushl %edx + pushl $0 /* Pass NULL as regs pointer */ movl 0xc(%esp), %eaxThis should now be changed to "0x10(%esp)", right?
Yeah, I think you're right. Actually, I think I originally had it as:
movl 0xc(%esp), %eax
+ pushl $0
But after a few other changes, it went to this. I haven't finished testing against x86_64, and haven't started the i386 tests. I'm sure this would have blown up then ;-)
Thanks,
-- Steve
Quoted 14 lines
Greetings,
AlexanderQuoted 10 lines
arch/x86/kernel/entry_32.S +1
-0movl 0x4(%ebp), %edx leal function_trace_op, %ecx@@ -1118,6 +1119,7 @@ ENTRY(ftrace_caller) ftrace_call: call ftrace_stub + addl $4,%esp /* skip NULL pointer */ popl %edx popl %ecx popl %eax
Steven Rostedt
maintainerPATCH v3 6/6 ftrace/x86: Add save_regs for i386 function calls
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Add saving full regs for function tracing on i386. The saving of regs was influenced by patches sent out by Masami Hiramatsu.
--- arch/x86/include/asm/ftrace.h | 2 -- arch/x86/kernel/entry_32.S | 53 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/ftrace.c | 4 ---- 3 files changed, 53 insertions(+), 6 deletions(-)
arch/x86/include/asm/ftrace.h +0 -2
@@ -40,10 +40,8 @@#ifdef CONFIG_DYNAMIC_FTRACE #define ARCH_SUPPORTS_FTRACE_OPS 1 -#ifdef CONFIG_X86_64 #define ARCH_SUPPORTS_FTRACE_SAVE_REGS #endif -#endif #ifndef __ASSEMBLY__extern void mcount (void );
arch/x86/kernel/entry_32.S +53 -0
65 lines not on this page · raw message
arch/x86/kernel/ftrace.c +0 -4
@@ -206,7 +206,6 @@ static int ftrace_modify_code(unsigned long ip, unsigned const char *old_code, unsigned const char *new_code); -#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS /* * Should never be called: * As it is only called by __ftrace_replace_code() which is called by
@@ -221,7 +220,6 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,WARN_ON (1 );return -EINVAL ; } -#endif int ftrace_update_ftrace_func (ftrace_func_t func) {
@@ -237,7 +235,6 @@ int ftrace_update_ftrace_func(ftrace_func_t func) ret =ftrace_modify_code (ip, old, new); -#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS /* Also update the regs callback function */ if (!ret) { ip = (unsigned long )(&ftrace_regs_call);
@@ -245,7 +242,6 @@ int ftrace_update_ftrace_func(ftrace_func_t func) new =ftrace_call_replace (ip, (unsigned long )func); ret =ftrace_modify_code (ip, old, new); } -#endif atomic_dec (&modifying_ftrace_code);
Signature · 1 line
1.7.10
Re: [PATCH 6/6] ftrace/x86: Add save_regs for i386 function calls
Quoted 70 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Add saving full regs for function tracing on i386. The saving of regs was influenced by patches sent out by Masami Hiramatsu.
Cc Masami Hiramatsu <[email protected]>Signed-off-by Steven Rostedt <[email protected]>--- arch/x86/include/asm/ftrace.h | 2 -- arch/x86/kernel/entry_32.S | 53 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/ftrace.c | 4 ---- 3 files changed, 53 insertions(+), 6 deletions(-)arch/x86/include/asm/ftrace.h +0
-2@@ -40,10 +40,8 @@#ifdef CONFIG_DYNAMIC_FTRACE #define ARCH_SUPPORTS_FTRACE_OPS 1 -#ifdef CONFIG_X86_64 #define ARCH_SUPPORTS_FTRACE_SAVE_REGS #endif -#endif #ifndef __ASSEMBLY__extern void mcount (void );arch/x86/kernel/entry_32.S +26
-0@@ -1123,6 +1123,7 @@ ftrace_call: popl %edx popl %ecx popl %eax +ftrace_ret: #ifdef CONFIG_FUNCTION_GRAPH_TRACER .globl ftrace_graph_call ftrace_graph_call:@@ -1134,6 +1135,58 @@ ftrace_stub: ret END(ftrace_caller) +ENTRY(ftrace_regs_caller) + pushf /* push flags before compare */ + cmpl $0, function_trace_stop + jne ftrace_exit + + subl $8, %esp /* skip ip and orig_ax */ + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl %eax + pushl %ebp + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + movl 14*4(%esp), %eax /* Load return address */ + pushl %eax /* Save return address (+4) */ + subl $MCOUNT_INSN_SIZE, %eax + movl %eax, 12*4+4(%esp) /* Store IP */ + movl 13*4+4(%esp), %edx /* Load flags */ + movl %edx, 14*4+4(%esp) /* Store flags */ + movl $__KERNEL_CS, %edx + movl %edx, 13*4+4(%esp) /* Store CS */
arch/x86/kernel/entry_32.S ftrace_stub: · line 1172
Quoted 10 lines
arch/x86/kernel/entry_32.S +10
-0+ + movl 0x4(%ebp), %edx + lea 4(%esp), %ecx + pushl %ecx /* Save pt_regs as 4th parameter */ + leal function_trace_op, %ecx + +GLOBAL(ftrace_regs_call) + call ftrace_stub + + addl $4,%esp /* Skip pt_regs */
Hmm, you need to restoring flags here, because
original flags is clobbered by KERNEL_CS.
movl 14*4+4(%esp), %edx movl %edx, 13*4+4(%esp)
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: [PATCH 6/6] ftrace/x86: Add save_regs for i386 function calls
Quoted 10 lines · Masami Hiramatsu
arch/x86/kernel/entry_32.S ftrace_stub: · line 1172
Quoted 4 lines · Steven Rostedt
arch/x86/kernel/entry_32.S +4
-0+GLOBAL(ftrace_regs_call) + call ftrace_stub + + addl $4,%esp /* Skip pt_regs */Hmm, you need to restoring flags here, because
original flags is clobbered byKERNEL_CS.
Quoted 2 lines
movl 14*4+4(%esp), %edx movl %edx, 13*4+4(%esp)
Ah, you're right. I'll update it. I need to make changes anyway, because I found that if I have a kprobe using ftrace and enable function graph tracer, the machine triple faults. I'm working on fixing that now.
Thanks!
-- Steve