From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@elte.hu>,
Andrew Morton <akpm@linux-foundation.org>,
Thomas Gleixner <tglx@linutronix.de>,
Peter Zijlstra <peterz@infradead.org>,
Frederic Weisbecker <fweisbec@gmail.com>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
Arnaldo Carvalho de Melo <acme@redhat.com>,
Jason Baron <jbaron@redhat.com>
Subject: [PATCH 3/5][RFC] ftrace: Return pt_regs to function trace callback (x86_64 only so
Date: Wed, 10 Aug 2011 12:22:25 -0400 [thread overview]
Message-ID: <20110810163038.238028499@goodmis.org> (raw)
In-Reply-To: 20110810162222.017387055@goodmis.org
[-- Attachment #1: 0003-ftrace-Return-pt_regs-to-function-trace-callback-x86.patch far) --]
[-- Type: text/plain, Size: 14058 bytes --]
From: Steven Rostedt <srostedt@redhat.com>
Return as the 4th paramater to the function tracer callback the pt_regs.
So far this is only supported by x86_64. The ftrace_ops flag
FTRACE_OPS_FL_SAVE_REGS is added to tell the arch to save all regs
to the pt_regs, otherwise a minimum is just passed back (the same
regs that is saved by mcount itself).
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
arch/x86/include/asm/ftrace.h | 38 ++++++++++++++++++++----------------
arch/x86/kernel/entry_64.S | 23 +++++++++++++++++++++-
include/linux/ftrace.h | 15 ++++++++++++-
kernel/trace/ftrace.c | 29 ++++++++++++++++++---------
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 +-
10 files changed, 95 insertions(+), 42 deletions(-)
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index b3fcf16..0750c2a 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -4,26 +4,29 @@
#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)
+ /*
+ * We add enough stack to save all regs,
+ * and we what we need in the location of pt_regs.
+ */
+ subq $ORIG_RAX, %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)
.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 $ORIG_RAX, %rsp
.endm
#endif
@@ -34,6 +37,7 @@
#if defined(CONFIG_DYNAMIC_FTRACE) && defined(CONFIG_X86_64)
#define ARCH_SUPPORTS_FTRACE_OPS 1
+#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 1
#endif
#ifndef __ASSEMBLY__
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 27adc2b..b77f297 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -78,7 +78,16 @@ ENTRY(ftrace_caller)
MCOUNT_SAVE_FRAME
leaq function_trace_op, %rdx
- movq 0x38(%rsp), %rdi
+
+ cmpl $0, ftrace_save_regs
+ jne save_all_regs
+
+call_func:
+
+ /* regs go into 4th parameter */
+ leaq (%rsp), %rcx
+
+ movq ORIG_RAX(%rsp), %rdi
movq 8(%rbp), %rsi
subq $MCOUNT_INSN_SIZE, %rdi
@@ -96,6 +105,18 @@ GLOBAL(ftrace_stub)
retq
END(ftrace_caller)
+save_all_regs:
+ /* Save the rest of pt_regs */
+ movq %r15, R15(%rsp)
+ movq %r14, R14(%rsp)
+ movq %r13, R13(%rsp)
+ movq %r12, R12(%rsp)
+ movq %r10, R10(%rsp)
+ movq %rbp, RBP(%rsp)
+ movq %rbx, RBX(%rsp)
+ jmp call_func
+
+
#else /* ! CONFIG_DYNAMIC_FTRACE */
ENTRY(mcount)
cmpl $0, function_trace_stop
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index e1fe5be..14dcc98 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -11,6 +11,7 @@
#include <linux/linkage.h>
#include <linux/bitops.h>
#include <linux/module.h>
+#include <linux/ptrace.h>
#include <linux/ktime.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -28,6 +29,14 @@
#define ARCH_SUPPORTS_FTRACE_OPS 0
#endif
+/*
+ * If the arch supports saving the regs to the ftrace_ops
+ * then it should set this to 1.
+ */
+#ifndef ARCH_SUPPORTS_FTRACE_SAVE_REGS
+#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 0
+#endif
+
struct ftrace_hash;
#ifdef CONFIG_FUNCTION_TRACER
@@ -41,12 +50,13 @@ 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 *pt_regs);
enum {
FTRACE_OPS_FL_ENABLED = 1 << 0,
FTRACE_OPS_FL_GLOBAL = 1 << 1,
FTRACE_OPS_FL_DYNAMIC = 1 << 2,
+ FTRACE_OPS_FL_SAVE_REGS = 1 << 3,
};
struct ftrace_ops {
@@ -109,7 +119,8 @@ int register_ftrace_function(struct ftrace_ops *ops);
int unregister_ftrace_function(struct ftrace_ops *ops);
void clear_ftrace_function(void);
-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 *pt_regs);
#else /* !CONFIG_FUNCTION_TRACER */
/*
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 1d720cb..c92f433 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -74,6 +74,9 @@ int function_trace_stop __read_mostly;
/* Current function tracing op */
struct ftrace_ops *function_trace_op __read_mostly = &ftrace_list_end;
+/* If the arch supports it, return pt_regs to caller */
+int ftrace_save_regs __read_mostly;
+
/* List for set_ftrace_pid's pids. */
LIST_HEAD(ftrace_pids);
struct ftrace_pid {
@@ -98,7 +101,7 @@ ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
static struct ftrace_ops global_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 *pt_regs);
/*
* Traverse the ftrace_global_list, invoking all entries. The reason that we
@@ -111,7 +114,7 @@ static void ftrace_ops_list_func(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 *pt_regs)
{
if (unlikely(trace_recursion_test(TRACE_GLOBAL_BIT)))
return;
@@ -119,19 +122,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, pt_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 *pt_regs)
{
if (!test_tsk_trace_trace(current))
return;
- ftrace_pid_function(ip, parent_ip, op);
+ ftrace_pid_function(ip, parent_ip, op, pt_regs);
}
static void set_ftrace_pid_function(ftrace_func_t func)
@@ -162,12 +165,12 @@ void clear_ftrace_function(void)
* mcount call site, we need to do it from C.
*/
static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip,
- struct ftrace_ops *op)
+ struct ftrace_ops *op, struct pt_regs *pt_regs)
{
if (function_trace_stop)
return;
- __ftrace_trace_function(ip, parent_ip, op);
+ __ftrace_trace_function(ip, parent_ip, op, pt_regs);
}
#endif
@@ -285,6 +288,9 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
if (!core_kernel_data((unsigned long)ops))
ops->flags |= FTRACE_OPS_FL_DYNAMIC;
+ if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
+ ftrace_save_regs++;
+
if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
int first = ftrace_global_list == &ftrace_list_end;
add_ftrace_ops(&ftrace_global_list, ops);
@@ -313,6 +319,9 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
if (FTRACE_WARN_ON(ops == &global_ops))
return -EINVAL;
+ if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
+ ftrace_save_regs--;
+
if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
ret = remove_ftrace_ops(&ftrace_global_list, ops);
if (!ret && ftrace_global_list == &ftrace_list_end)
@@ -2527,7 +2536,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;
@@ -3575,7 +3584,7 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
static void
ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
- struct ftrace_ops *op)
+ struct ftrace_ops *op, struct pt_regs *pt_regs)
{
if (unlikely(trace_recursion_test(TRACE_INTERNAL_BIT)))
return;
@@ -3589,7 +3598,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, pt_regs);
op = rcu_dereference_raw(op->next);
};
preempt_enable_notrace();
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index d2a6f94..fe2c1ac 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1674,7 +1674,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;
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index fceb7a9..5675ebd 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -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;
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 7649609..009b3c4 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -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;
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index a311bfd..fdafb79 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -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;
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 9ae40c8..add37e0 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -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++;
}
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 456f262..d22ba11 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -108,7 +108,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;
--
1.7.5.4
next prev parent reply other threads:[~2011-08-10 16:31 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-10 16:22 [PATCH 0/5][RFC] kprobes/ftrace: Have kprobes use ftrace on ftrace nops Steven Rostedt
2011-08-10 16:22 ` [PATCH 1/5][RFC] tracing: Clean up tb_fmt to not give faulty compile warning Steven Rostedt
2011-08-10 16:22 ` [PATCH 2/5][RFC] ftrace: Pass ftrace_ops as third parameter to function trace Steven Rostedt
2011-08-10 16:22 ` Steven Rostedt [this message]
2011-08-11 5:55 ` [PATCH 3/5][RFC] ftrace: Return pt_regs to function trace callback (x86_64 only so Masami Hiramatsu
2011-08-11 12:59 ` Steven Rostedt
2011-08-12 0:55 ` Masami Hiramatsu
2011-08-12 13:05 ` Steven Rostedt
2011-08-10 16:22 ` [PATCH 4/5][RFC] kprobes: Inverse taking of module_mutex with kprobe_mutex Steven Rostedt
2011-08-10 16:22 ` [PATCH 5/5][RFC] kprobes: Use ftrace hooks when probing ftrace nops Steven Rostedt
2011-08-11 7:41 ` Masami Hiramatsu
2011-08-11 13:22 ` Steven Rostedt
2011-08-12 2:41 ` Masami Hiramatsu
2011-08-12 5:46 ` Ananth N Mavinakayanahalli
2011-08-12 13:14 ` Steven Rostedt
2011-08-11 0:21 ` [PATCH 0/5][RFC] kprobes/ftrace: Have kprobes use ftrace on " Masami Hiramatsu
2011-08-11 0:34 ` Steven Rostedt
2011-08-11 6:28 ` Masami Hiramatsu
2011-08-11 13:01 ` Steven Rostedt
2011-08-12 2:57 ` Masami Hiramatsu
2011-08-12 13:08 ` Steven Rostedt
2011-08-13 10:09 ` Masami Hiramatsu
2011-08-14 2:58 ` Steven Rostedt
2011-08-14 10:28 ` Masami Hiramatsu
2011-08-15 13:06 ` Steven Rostedt
2011-08-17 12:12 ` Masami Hiramatsu
2011-08-18 20:06 ` Steven Rostedt
2011-08-19 2:41 ` Masami Hiramatsu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110810163038.238028499@goodmis.org \
--to=rostedt@goodmis.org \
--cc=acme@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=fweisbec@gmail.com \
--cc=jbaron@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=mingo@elte.hu \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.