@@ -191,7 +191,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
old = *parent;
*parent = return_hooker;
- if (function_graph_enter(old, self_addr, frame_pointer, NULL))
+ if (function_graph_enter(old, self_addr, frame_pointer, NULL, NULL))
*parent = old;
}
@@ -233,7 +233,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
*/
old = *parent;
- if (!function_graph_enter(old, self_addr, frame_pointer, NULL))
+ if (!function_graph_enter(old, self_addr, frame_pointer, NULL, NULL))
*parent = return_hooker;
}
@@ -148,7 +148,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
old = *parent;
if (!function_graph_enter(old, self_addr,
- *(unsigned long *)frame_pointer, parent)) {
+ *(unsigned long *)frame_pointer, parent, NULL)) {
/*
* For csky-gcc function has sub-call:
* subi sp, sp, 8
@@ -62,7 +62,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
return;
}
- if (function_graph_enter(old, self_addr, 0, NULL))
+ if (function_graph_enter(old, self_addr, 0, NULL, NULL))
*parent = old;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
@@ -378,7 +378,7 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
insns = core_kernel_text(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1;
self_ra -= (MCOUNT_INSN_SIZE * insns);
- if (function_graph_enter(old_parent_ra, self_ra, fp, NULL))
+ if (function_graph_enter(old_parent_ra, self_ra, fp, NULL, NULL))
*parent_ra_addr = old_parent_ra;
return;
out:
@@ -217,7 +217,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
old = *parent;
- if (!function_graph_enter(old, self_addr, frame_pointer, NULL))
+ if (!function_graph_enter(old, self_addr, frame_pointer, NULL, NULL))
*parent = return_hooker;
}
@@ -235,7 +235,8 @@ noinline void ftrace_graph_caller(void)
prepare_ftrace_return(parent_ip, selfpc, frame_pointer);
}
-extern unsigned long ftrace_return_to_handler(unsigned long frame_pointer);
+extern unsigned long ftrace_return_to_handler(unsigned long frame_pointer,
+ unsigned long retval);
void __naked return_to_handler(void)
{
__asm__ __volatile__ (
@@ -40,7 +40,7 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
old = *parent;
- if (!function_graph_enter(old, self_addr, 0, NULL))
+ if (!function_graph_enter(old, self_addr, 0, NULL, NULL))
/* activate parisc_return_to_handler() as return point */
*parent = (unsigned long) &parisc_return_to_handler;
}
@@ -956,7 +956,7 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip)
return_hooker = ppc_function_entry(return_to_handler);
- if (!function_graph_enter(parent, ip, 0, NULL))
+ if (!function_graph_enter(parent, ip, 0, NULL, NULL))
parent = return_hooker;
out:
return parent;
@@ -142,7 +142,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
*/
old = *parent;
- if (function_graph_enter(old, self_addr, frame_pointer, parent))
+ if (function_graph_enter(old, self_addr, frame_pointer, parent, NULL))
*parent = return_hooker;
}
@@ -209,7 +209,7 @@ unsigned long prepare_ftrace_return(unsigned long ra, unsigned long sp,
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
goto out;
ip -= MCOUNT_INSN_SIZE;
- if (!function_graph_enter(ra, ip, 0, (void *) sp))
+ if (!function_graph_enter(ra, ip, 0, (void *) sp), NULL)
ra = (unsigned long) return_to_handler;
out:
return ra;
@@ -364,7 +364,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
return;
}
- if (function_graph_enter(old, self_addr, 0, NULL))
+ if (function_graph_enter(old, self_addr, 0, NULL, NULL))
__raw_writel(old, parent);
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
@@ -130,7 +130,7 @@ unsigned long prepare_ftrace_return(unsigned long parent,
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
return parent + 8UL;
- if (function_graph_enter(parent, self_addr, frame_pointer, NULL))
+ if (function_graph_enter(parent, self_addr, frame_pointer, NULL, NULL))
return parent + 8UL;
return return_hooker;
@@ -1072,7 +1072,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
return;
}
- if (function_graph_enter(old, self_addr, frame_pointer, parent))
+ if (function_graph_enter(old, self_addr, frame_pointer, parent, NULL))
*parent = old;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
@@ -757,9 +757,12 @@ struct ftrace_graph_ret {
/* Type of the callback handlers for tracing function graph*/
typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */
-typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */
+/* @pt_regs is only available for CONFIG_FTRACE_FUNC_PROTOTYPE. */
+typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *,
+ struct pt_regs *); /* entry */
-extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
+int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace,
+ struct pt_regs *pt_regs);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -797,7 +800,8 @@ extern void return_to_handler(void);
extern int
function_graph_enter(unsigned long ret, unsigned long func,
- unsigned long frame_pointer, unsigned long *retp);
+ unsigned long frame_pointer, unsigned long *retp,
+ struct pt_regs *pt_regs);
struct ftrace_ret_stack *
ftrace_graph_get_ret_stack(struct task_struct *task, int idx);
@@ -96,8 +96,13 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func,
return 0;
}
+/*
+ * Called from arch specific code. @pt_regs is only available for
+ * CONFIG_FTRACE_FUNC_PROTOTYPE.
+ */
int function_graph_enter(unsigned long ret, unsigned long func,
- unsigned long frame_pointer, unsigned long *retp)
+ unsigned long frame_pointer, unsigned long *retp,
+ struct pt_regs *pt_regs)
{
struct ftrace_graph_ent trace;
@@ -108,7 +113,7 @@ int function_graph_enter(unsigned long ret, unsigned long func,
goto out;
/* Only trace if the calling function expects to */
- if (!ftrace_graph_entry(&trace))
+ if (!ftrace_graph_entry(&trace, pt_regs))
goto out_ret;
return 0;
@@ -204,9 +209,11 @@ static struct notifier_block ftrace_suspend_notifier = {
/*
* Send the trace to the ring-buffer.
+ * @retval is only available for CONFIG_FTRACE_FUNC_PROTOTYPE.
* @return the original return address.
*/
-unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
+unsigned long ftrace_return_to_handler(unsigned long frame_pointer,
+ unsigned long retval)
{
struct ftrace_graph_ret trace;
unsigned long ret;
@@ -327,7 +334,8 @@ void ftrace_graph_sleep_time_control(bool enable)
fgraph_sleep_time = enable;
}
-int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
+int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace,
+ struct pt_regs *pt_regs)
{
return 0;
}
@@ -417,11 +425,12 @@ ftrace_graph_probe_sched_switch(void *ignore, bool preempt,
next->ret_stack[index].calltime += timestamp;
}
-static int ftrace_graph_entry_test(struct ftrace_graph_ent *trace)
+static int ftrace_graph_entry_test(struct ftrace_graph_ent *trace,
+ struct pt_regs *pt_regs)
{
if (!ftrace_ops_test(&global_ops, trace->func, NULL))
return 0;
- return __ftrace_graph_entry(trace);
+ return __ftrace_graph_entry(trace, pt_regs);
}
/*
@@ -794,7 +794,9 @@ void ftrace_graph_graph_time_control(bool enable)
fgraph_graph_time = enable;
}
-static int profile_graph_entry(struct ftrace_graph_ent *trace)
+/* @pt_regs is only available for CONFIG_FTRACE_FUNC_PROTOTYPE. */
+static int profile_graph_entry(struct ftrace_graph_ent *trace,
+ struct pt_regs *pt_regs)
{
struct ftrace_ret_stack *ret_stack;
@@ -737,7 +737,7 @@ void print_trace_header(struct seq_file *m, struct trace_iterator *iter);
int trace_empty(struct trace_iterator *iter);
void trace_graph_return(struct ftrace_graph_ret *trace);
-int trace_graph_entry(struct ftrace_graph_ent *trace);
+int trace_graph_entry(struct ftrace_graph_ent *trace, struct pt_regs *pt_regs);
void set_graph_array(struct trace_array *tr);
void tracing_start_cmdline_record(void);
@@ -124,7 +124,7 @@ static inline int ftrace_graph_ignore_irqs(void)
return in_irq();
}
-int trace_graph_entry(struct ftrace_graph_ent *trace)
+int trace_graph_entry(struct ftrace_graph_ent *trace, struct pt_regs *pt_regs)
{
struct trace_array *tr = graph_array;
struct trace_array_cpu *data;
@@ -172,7 +172,8 @@ static int irqsoff_display_graph(struct trace_array *tr, int set)
return start_irqsoff_tracer(irqsoff_trace, set);
}
-static int irqsoff_graph_entry(struct ftrace_graph_ent *trace)
+static int irqsoff_graph_entry(struct ftrace_graph_ent *trace,
+ struct pt_regs *pt_regs)
{
struct trace_array *tr = irqsoff_trace;
struct trace_array_cpu *data;
@@ -112,7 +112,8 @@ static int wakeup_display_graph(struct trace_array *tr, int set)
return start_func_tracer(tr, set);
}
-static int wakeup_graph_entry(struct ftrace_graph_ent *trace)
+static int wakeup_graph_entry(struct ftrace_graph_ent *trace,
+ struct pt_regs *pt_regs)
{
struct trace_array *tr = wakeup_trace;
struct trace_array_cpu *data;
To record function parameter and return value, we need the arch specific code to pass the saved register context. It is only valid if the CONFIG_FTRACE_FUNC_PROTOTYPE feature is enabled. This patch only changes the interfaces, real implementation will be added later. Signed-off-by: Changbin Du <changbin.du@gmail.com> --- arch/arm/kernel/ftrace.c | 2 +- arch/arm64/kernel/ftrace.c | 2 +- arch/csky/kernel/ftrace.c | 2 +- arch/microblaze/kernel/ftrace.c | 2 +- arch/mips/kernel/ftrace.c | 2 +- arch/nds32/kernel/ftrace.c | 5 +++-- arch/parisc/kernel/ftrace.c | 2 +- arch/powerpc/kernel/trace/ftrace.c | 2 +- arch/riscv/kernel/ftrace.c | 2 +- arch/s390/kernel/ftrace.c | 2 +- arch/sh/kernel/ftrace.c | 2 +- arch/sparc/kernel/ftrace.c | 2 +- arch/x86/kernel/ftrace.c | 2 +- include/linux/ftrace.h | 10 +++++++--- kernel/trace/fgraph.c | 21 +++++++++++++++------ kernel/trace/ftrace.c | 4 +++- kernel/trace/trace.h | 2 +- kernel/trace/trace_functions_graph.c | 2 +- kernel/trace/trace_irqsoff.c | 3 ++- kernel/trace/trace_sched_wakeup.c | 3 ++- 20 files changed, 46 insertions(+), 28 deletions(-)