From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@elte.hu>,
Andrew Morton <akpm@linux-foundation.org>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
Frederic Weisbecker <fweisbec@gmail.com>,
Thomas Gleixner <tglx@linutronix.de>,
"H. Peter Anvin" <hpa@zytor.com>
Subject: [PATCH 11/19] ftrace: Add selftest to test function trace recursion protection
Date: Fri, 20 Jul 2012 22:19:54 -0400 [thread overview]
Message-ID: <20120721022109.652033022@goodmis.org> (raw)
In-Reply-To: 20120721021943.274162381@goodmis.org
[-- Attachment #1: Type: text/plain, Size: 6720 bytes --]
From: Steven Rostedt <srostedt@redhat.com>
Add selftests to test the function tracing recursion protection actually
does work. It also tests if a ftrace_ops states it will perform its own
protection. Although, even if the ftrace_ops states it will protect itself,
the ftrace infrastructure may still provide protection if the arch does
not support all features or another ftrace_ops is registered.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
include/linux/ftrace.h | 6 ++
kernel/trace/ftrace.c | 21 +++++++
kernel/trace/trace_selftest.c | 136 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 163 insertions(+)
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 65a14e4..9962e95 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -220,6 +220,10 @@ extern void ftrace_stub(unsigned long a0, unsigned long a1,
*/
#define register_ftrace_function(ops) ({ 0; })
#define unregister_ftrace_function(ops) ({ 0; })
+static inline int ftrace_nr_registered_ops(void)
+{
+ return 0;
+}
static inline void clear_ftrace_function(void) { }
static inline void ftrace_kill(void) { }
static inline void ftrace_stop(void) { }
@@ -275,6 +279,8 @@ extern void unregister_ftrace_function_probe_all(char *glob);
extern int ftrace_text_reserved(void *start, void *end);
+extern int ftrace_nr_registered_ops(void);
+
/*
* The dyn_ftrace record's flags field is split into two parts.
* the first part which is '0-FTRACE_REF_MAX' is a counter of
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index ad765b4..528d997 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -111,6 +111,27 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);
#define ftrace_ops_list_func ((ftrace_func_t)ftrace_ops_no_ops)
#endif
+/**
+ * ftrace_nr_registered_ops - return number of ops registered
+ *
+ * Returns the number of ftrace_ops registered and tracing functions
+ */
+int ftrace_nr_registered_ops(void)
+{
+ struct ftrace_ops *ops;
+ int cnt = 0;
+
+ mutex_lock(&ftrace_lock);
+
+ for (ops = ftrace_ops_list;
+ ops != &ftrace_list_end; ops = ops->next)
+ cnt++;
+
+ mutex_unlock(&ftrace_lock);
+
+ return cnt;
+}
+
/*
* Traverse the ftrace_global_list, invoking all entries. The reason that we
* can use rcu_dereference_raw() is that elements removed from this list
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 1fb6da8..86422f9 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -406,8 +406,141 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
return ret;
}
+
+static int trace_selftest_recursion_cnt;
+static void trace_selftest_test_recursion_func(unsigned long ip,
+ unsigned long pip,
+ struct ftrace_ops *op,
+ struct pt_regs *pt_regs)
+{
+ /*
+ * This function is registered without the recursion safe flag.
+ * The ftrace infrastructure should provide the recursion
+ * protection. If not, this will crash the kernel!
+ */
+ trace_selftest_recursion_cnt++;
+ DYN_FTRACE_TEST_NAME();
+}
+
+static void trace_selftest_test_recursion_safe_func(unsigned long ip,
+ unsigned long pip,
+ struct ftrace_ops *op,
+ struct pt_regs *pt_regs)
+{
+ /*
+ * We said we would provide our own recursion. By calling
+ * this function again, we should recurse back into this function
+ * and count again. But this only happens if the arch supports
+ * all of ftrace features and nothing else is using the function
+ * tracing utility.
+ */
+ if (trace_selftest_recursion_cnt++)
+ return;
+ DYN_FTRACE_TEST_NAME();
+}
+
+static struct ftrace_ops test_rec_probe = {
+ .func = trace_selftest_test_recursion_func,
+};
+
+static struct ftrace_ops test_recsafe_probe = {
+ .func = trace_selftest_test_recursion_safe_func,
+ .flags = FTRACE_OPS_FL_RECURSION_SAFE,
+};
+
+static int
+trace_selftest_function_recursion(void)
+{
+ int save_ftrace_enabled = ftrace_enabled;
+ int save_tracer_enabled = tracer_enabled;
+ char *func_name;
+ int len;
+ int ret;
+ int cnt;
+
+ /* The previous test PASSED */
+ pr_cont("PASSED\n");
+ pr_info("Testing ftrace recursion: ");
+
+
+ /* enable tracing, and record the filter function */
+ ftrace_enabled = 1;
+ tracer_enabled = 1;
+
+ /* Handle PPC64 '.' name */
+ func_name = "*" __stringify(DYN_FTRACE_TEST_NAME);
+ len = strlen(func_name);
+
+ ret = ftrace_set_filter(&test_rec_probe, func_name, len, 1);
+ if (ret) {
+ pr_cont("*Could not set filter* ");
+ goto out;
+ }
+
+ ret = register_ftrace_function(&test_rec_probe);
+ if (ret) {
+ pr_cont("*could not register callback* ");
+ goto out;
+ }
+
+ DYN_FTRACE_TEST_NAME();
+
+ unregister_ftrace_function(&test_rec_probe);
+
+ ret = -1;
+ if (trace_selftest_recursion_cnt != 1) {
+ pr_cont("*callback not called once (%d)* ",
+ trace_selftest_recursion_cnt);
+ goto out;
+ }
+
+ trace_selftest_recursion_cnt = 1;
+
+ pr_cont("PASSED\n");
+ pr_info("Testing ftrace recursion safe: ");
+
+ ret = ftrace_set_filter(&test_recsafe_probe, func_name, len, 1);
+ if (ret) {
+ pr_cont("*Could not set filter* ");
+ goto out;
+ }
+
+ ret = register_ftrace_function(&test_recsafe_probe);
+ if (ret) {
+ pr_cont("*could not register callback* ");
+ goto out;
+ }
+
+ DYN_FTRACE_TEST_NAME();
+
+ unregister_ftrace_function(&test_recsafe_probe);
+
+ /*
+ * If arch supports all ftrace features, and no other task
+ * was on the list, we should be fine.
+ */
+ if (!ftrace_nr_registered_ops() && !FTRACE_FORCE_LIST_FUNC)
+ cnt = 2; /* Should have recursed */
+ else
+ cnt = 1;
+
+ ret = -1;
+ if (trace_selftest_recursion_cnt != cnt) {
+ pr_cont("*callback not called expected %d times (%d)* ",
+ cnt, trace_selftest_recursion_cnt);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ ftrace_enabled = save_ftrace_enabled;
+ tracer_enabled = save_tracer_enabled;
+
+ return ret;
+}
#else
# define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; })
+# define trace_selftest_function_recursion() ({ 0; })
#endif /* CONFIG_DYNAMIC_FTRACE */
/*
@@ -455,7 +588,10 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
ret = trace_selftest_startup_dynamic_tracing(trace, tr,
DYN_FTRACE_TEST_NAME);
+ if (ret)
+ goto out;
+ ret = trace_selftest_function_recursion();
out:
ftrace_enabled = save_ftrace_enabled;
tracer_enabled = save_tracer_enabled;
--
1.7.10.4
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
next prev parent reply other threads:[~2012-07-21 2:22 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-21 2:19 [PATCH 00/19] [GIT PULL][v3.6] ftrace: Allow kprobes to work with ftace Steven Rostedt
2012-07-21 2:19 ` [PATCH 01/19] ftrace: Pass ftrace_ops as third parameter to function trace callback Steven Rostedt
2012-07-21 2:19 ` [PATCH 02/19] ftrace: Consolidate arch dependent functions with list function Steven Rostedt
2012-07-21 2:19 ` [PATCH 03/19] ftrace: Return pt_regs to function trace callback Steven Rostedt
2012-07-21 2:19 ` [PATCH 04/19] ftrace/x86_32: Push ftrace_ops in as 3rd parameter to function tracer Steven Rostedt
2012-07-21 2:19 ` [PATCH 05/19] ftrace/x86: Add separate function to save regs Steven Rostedt
2012-07-21 2:19 ` [PATCH 06/19] ftrace/x86: Add save_regs for i386 function calls Steven Rostedt
2012-07-21 2:19 ` [PATCH 07/19] ftrace/x86_32: Simplify parameter setup for ftrace_regs_caller Steven Rostedt
2012-07-23 4:06 ` Masami Hiramatsu
2012-07-21 2:19 ` [PATCH 08/19] ftrace/x86: Remove function_trace_stop check from graph caller Steven Rostedt
2012-07-21 2:19 ` [PATCH 09/19] ftrace: Add default recursion protection for function tracing Steven Rostedt
2012-07-21 2:19 ` [PATCH 10/19] ftrace: Only compile ftrace selftest if selftests are enabled Steven Rostedt
2012-07-21 2:19 ` Steven Rostedt [this message]
2012-07-21 2:19 ` [PATCH 12/19] ftrace: Add selftest to test function save-regs support Steven Rostedt
2012-07-21 2:19 ` [PATCH 13/19] ftrace: add ftrace_set_filter_ip() for address based filter Steven Rostedt
2012-07-21 2:19 ` [PATCH 14/19] kprobes: Inverse taking of module_mutex with kprobe_mutex Steven Rostedt
2012-07-21 2:19 ` [PATCH 15/19] kprobes: cleanup to separate probe-able check Steven Rostedt
2012-07-21 2:19 ` [PATCH 16/19] kprobes: Move locks into appropriate functions Steven Rostedt
2012-07-21 2:20 ` [PATCH 17/19] ftrace: Make ftrace_location() a nop on !DYNAMIC_FTRACE Steven Rostedt
2012-07-21 2:20 ` [PATCH 18/19] kprobes: introduce ftrace based optimization Steven Rostedt
2012-07-21 2:20 ` [PATCH 19/19] kprobes/x86: ftrace based optimization for x86 Steven Rostedt
2012-07-30 15:51 ` [PATCH 00/19] [GIT PULL][v3.6] ftrace: Allow kprobes to work with ftace Steven Rostedt
2012-07-31 14:37 ` [GIT PULL][v3.7] (was: Re: [PATCH 00/19] [GIT PULL][v3.6]) " Steven Rostedt
2012-07-31 15:12 ` [PATCH 00/19] [GIT PULL][v3.6] " Ingo Molnar
2012-08-07 13:23 ` Steven Rostedt
2012-08-21 9:26 ` Ingo Molnar
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=20120721022109.652033022@goodmis.org \
--to=rostedt@goodmis.org \
--cc=akpm@linux-foundation.org \
--cc=fweisbec@gmail.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=mingo@elte.hu \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox