perf: Add attribute to filter out callchains
authorFrederic Weisbecker <fweisbec@gmail.com>
Tue, 7 Aug 2012 13:20:41 +0000 (15:20 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 10 Aug 2012 15:40:57 +0000 (12:40 -0300)
Introducing following bits to the the perf_event_attr struct:

  - exclude_callchain_kernel to filter out kernel callchain
    from the sample dump

  - exclude_callchain_user to filter out user callchain
    from the sample dump

We need to be able to disable standard user callchain dump when we use
the dwarf cfi callchain mode, because frame pointer based user
callchains are useless in this mode.

Implementing also exclude_callchain_kernel to have complete set of
options.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
[ Added kernel callchains filtering ]
Cc: "Frank Ch. Eigler" <fche@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: Benjamin Redelings <benjamin.redelings@nescent.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Robert Richter <robert.richter@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Cc: Ulrich Drepper <drepper@gmail.com>
Link: http://lkml.kernel.org/r/1344345647-11536-7-git-send-email-jolsa@redhat.com
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
include/linux/perf_event.h
kernel/events/callchain.c

index d1d25f6a5e24d71b48f80ac3d5aced996ccb52dc..297ca3db6b4a9a4e8bf8a8ee1b63c63ef171847d 100644 (file)
@@ -268,7 +268,10 @@ struct perf_event_attr {
                                exclude_host   :  1, /* don't count in host   */
                                exclude_guest  :  1, /* don't count in guest  */
 
-                               __reserved_1   : 43;
+                               exclude_callchain_kernel : 1, /* exclude kernel callchains */
+                               exclude_callchain_user   : 1, /* exclude user callchains */
+
+                               __reserved_1   : 41;
 
        union {
                __u32           wakeup_events;    /* wakeup every n events */
index 98d4597f43d69e35a76535fac7d0bb6821ebdf7f..c77206184b8bd2c4c16cd981b9a383076f840b25 100644 (file)
@@ -159,6 +159,11 @@ perf_callchain(struct perf_event *event, struct pt_regs *regs)
        int rctx;
        struct perf_callchain_entry *entry;
 
+       int kernel = !event->attr.exclude_callchain_kernel;
+       int user   = !event->attr.exclude_callchain_user;
+
+       if (!kernel && !user)
+               return NULL;
 
        entry = get_callchain_entry(&rctx);
        if (rctx == -1)
@@ -169,24 +174,29 @@ perf_callchain(struct perf_event *event, struct pt_regs *regs)
 
        entry->nr = 0;
 
-       if (!user_mode(regs)) {
+       if (kernel && !user_mode(regs)) {
                perf_callchain_store(entry, PERF_CONTEXT_KERNEL);
                perf_callchain_kernel(entry, regs);
-               if (current->mm)
-                       regs = task_pt_regs(current);
-               else
-                       regs = NULL;
        }
 
-       if (regs) {
-               /*
-                * Disallow cross-task user callchains.
-                */
-               if (event->ctx->task && event->ctx->task != current)
-                       goto exit_put;
-
-               perf_callchain_store(entry, PERF_CONTEXT_USER);
-               perf_callchain_user(entry, regs);
+       if (user) {
+               if (!user_mode(regs)) {
+                       if  (current->mm)
+                               regs = task_pt_regs(current);
+                       else
+                               regs = NULL;
+               }
+
+               if (regs) {
+                       /*
+                        * Disallow cross-task user callchains.
+                        */
+                       if (event->ctx->task && event->ctx->task != current)
+                               goto exit_put;
+
+                       perf_callchain_store(entry, PERF_CONTEXT_USER);
+                       perf_callchain_user(entry, regs);
+               }
        }
 
 exit_put: