aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorRoberto Agostino Vitillo <ravitillo@lbl.gov>2012-02-09 17:21:02 -0500
committerIngo Molnar <mingo@elte.hu>2012-03-09 02:26:05 -0500
commitbdfebd848f2a14e639031a0b0e61d7c7ee5e5fd2 (patch)
tree8ebcc7afda6b506dcd22d44bccdbd925c02b6768 /tools/perf
parentb5387528f31d98acedf06e930554b563d87e2383 (diff)
perf record: Add support for sampling taken branch
This patch adds a new option to enable taken branch stack sampling, i.e., leverage the PERF_SAMPLE_BRANCH_STACK feature of perf_events. There is a new option to active this mode: -b. It is possible to pass a set of filters to select the type of branches to sample. The following filters are available: - any : any type of branches - any_call : any function call or system call - any_ret : any function return or system call return - any_ind : any indirect branch - u: only when the branch target is at the user level - k: only when the branch target is in the kernel - hv: only when the branch target is in the hypervisor Filters can be combined by passing a comma separated list to the option: $ perf record -b any_call,u -e cycles:u branchy Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov> Signed-off-by: Stephane Eranian <eranian@google.com> Cc: peterz@infradead.org Cc: acme@redhat.com Cc: robert.richter@amd.com Cc: ming.m.lin@intel.com Cc: andi@firstfloor.org Cc: asharma@fb.com Cc: vweaver1@eecs.utk.edu Cc: khandual@linux.vnet.ibm.com Cc: dsahern@gmail.com Link: http://lkml.kernel.org/r/1328826068-11713-13-git-send-email-eranian@google.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-record.txt25
-rw-r--r--tools/perf/builtin-record.c74
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/util/evsel.c4
4 files changed, 104 insertions, 0 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index a5766b4b0125..60bddaf0e5bd 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -152,6 +152,31 @@ an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must ha
152corresponding events, i.e., they always refer to events defined earlier on the command 152corresponding events, i.e., they always refer to events defined earlier on the command
153line. 153line.
154 154
155-b::
156--branch-stack::
157Enable taken branch stack sampling. Each sample captures a series of consecutive
158taken branches. The number of branches captured with each sample depends on the
159underlying hardware, the type of branches of interest, and the executed code.
160It is possible to select the types of branches captured by enabling filters. The
161following filters are defined:
162
163 - any : any type of branches
164 - any_call: any function call or system call
165 - any_ret: any function return or system call return
166 - any_ind: any indirect branch
167 - u: only when the branch target is at the user level
168 - k: only when the branch target is in the kernel
169 - hv: only when the target is at the hypervisor level
170
171+
172At least one of any, any_call, any_ret, any_ind must be provided. The privilege levels may
173be ommitted, in which case, the privilege levels of the associated event are applied to the
174branch filter. Both kernel (k) and hypervisor (hv) privilege levels are subject to
175permissions. When sampling on multiple events, branch stack sampling is enabled for all
176the sampling events. The sampled branch type is the same for all events.
177Note that taken branch sampling may not be available on all processors.
178The various filters must be specified as a comma separated list: -b any_ret,u,k
179
155SEE ALSO 180SEE ALSO
156-------- 181--------
157linkperf:perf-stat[1], linkperf:perf-list[1] 182linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 75d230fef202..1c49d4e8767c 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -638,6 +638,77 @@ out_delete_session:
638 return err; 638 return err;
639} 639}
640 640
641#define BRANCH_OPT(n, m) \
642 { .name = n, .mode = (m) }
643
644#define BRANCH_END { .name = NULL }
645
646struct branch_mode {
647 const char *name;
648 int mode;
649};
650
651static const struct branch_mode branch_modes[] = {
652 BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
653 BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
654 BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
655 BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
656 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
657 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
658 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
659 BRANCH_END
660};
661
662static int
663parse_branch_stack(const struct option *opt, const char *str, int unset __used)
664{
665#define ONLY_PLM \
666 (PERF_SAMPLE_BRANCH_USER |\
667 PERF_SAMPLE_BRANCH_KERNEL |\
668 PERF_SAMPLE_BRANCH_HV)
669
670 uint64_t *mode = (uint64_t *)opt->value;
671 const struct branch_mode *br;
672 char *s, *os, *p;
673 int ret = -1;
674
675 *mode = 0;
676
677 /* because str is read-only */
678 s = os = strdup(str);
679 if (!s)
680 return -1;
681
682 for (;;) {
683 p = strchr(s, ',');
684 if (p)
685 *p = '\0';
686
687 for (br = branch_modes; br->name; br++) {
688 if (!strcasecmp(s, br->name))
689 break;
690 }
691 if (!br->name)
692 goto error;
693
694 *mode |= br->mode;
695
696 if (!p)
697 break;
698
699 s = p + 1;
700 }
701 ret = 0;
702
703 if ((*mode & ~ONLY_PLM) == 0) {
704 error("need at least one branch type with -b\n");
705 ret = -1;
706 }
707error:
708 free(os);
709 return ret;
710}
711
641static const char * const record_usage[] = { 712static const char * const record_usage[] = {
642 "perf record [<options>] [<command>]", 713 "perf record [<options>] [<command>]",
643 "perf record [<options>] -- <command> [<options>]", 714 "perf record [<options>] -- <command> [<options>]",
@@ -727,6 +798,9 @@ const struct option record_options[] = {
727 "monitor event in cgroup name only", 798 "monitor event in cgroup name only",
728 parse_cgroups), 799 parse_cgroups),
729 OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"), 800 OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
801 OPT_CALLBACK('b', "branch-stack", &record.opts.branch_stack,
802 "branch mode mask", "branch stack sampling modes",
803 parse_branch_stack),
730 OPT_END() 804 OPT_END()
731}; 805};
732 806
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 358f40135c4d..eec392e48067 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -222,6 +222,7 @@ struct perf_record_opts {
222 unsigned int freq; 222 unsigned int freq;
223 unsigned int mmap_pages; 223 unsigned int mmap_pages;
224 unsigned int user_freq; 224 unsigned int user_freq;
225 int branch_stack;
225 u64 default_interval; 226 u64 default_interval;
226 u64 user_interval; 227 u64 user_interval;
227 const char *cpu_list; 228 const char *cpu_list;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index a1fd1cd2a5af..f421f7cbc0d3 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -126,6 +126,10 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
126 attr->watermark = 0; 126 attr->watermark = 0;
127 attr->wakeup_events = 1; 127 attr->wakeup_events = 1;
128 } 128 }
129 if (opts->branch_stack) {
130 attr->sample_type |= PERF_SAMPLE_BRANCH_STACK;
131 attr->branch_sample_type = opts->branch_stack;
132 }
129 133
130 attr->mmap = track; 134 attr->mmap = track;
131 attr->comm = track; 135 attr->comm = track;