Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aad2b21c authored by Kan Liang's avatar Kan Liang Committed by Ingo Molnar
Browse files

perf tools: Enable LBR call stack support



Currently, there are two call chain recording options, fp and dwarf.

Haswell has a new feature that utilizes the existing LBR facility to
record call chains. Kernel side LBR support code provides this as a
third option to record call chains. This patch enables the lbr call
stack support on the tooling side.

LBR call stack has some limitations:

 - It reuses current LBR facility, so LBR call stack and branch record
   can not be enabled at the same time.

 - It is only available for user-space callchains.

However, it also offers some advantages:

 - LBR call stack can work on user apps which don't have frame-pointers
   or dwarf debug info compiled. It is a good alternative when nothing
   else works.

Tested-by: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarKan Liang <kan.liang@intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Cody P Schafer <cody@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Jacob Shin <jacob.w.shin@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masanari Iida <standby24x7@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Rodrigo Campos <rodrigo@sdfg.com.ar>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1420482185-29830-2-git-send-email-kan.liang@intel.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 2c44b193
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -115,13 +115,19 @@ OPTIONS
	implies -g.

	Allows specifying "fp" (frame pointer) or "dwarf"
	(DWARF's CFI - Call Frame Information) as the method to collect
	(DWARF's CFI - Call Frame Information) or "lbr"
	(Hardware Last Branch Record facility) as the method to collect
	the information used to show the call graphs.

	In some systems, where binaries are build with gcc
	--fomit-frame-pointer, using the "fp" method will produce bogus
	call graphs, using "dwarf", if available (perf tools linked to
	the libunwind library) should be used instead.
	Using the "lbr" method doesn't require any compiler options. It
	will produce call graphs from the hardware LBR registers. The
	main limition is that it is only available on new Intel
	platforms, such as Haswell. It can only get user call chain. It
	doesn't work with branch stack sampling at the same time.

-q::
--quiet::
+3 −3
Original line number Diff line number Diff line
@@ -658,7 +658,7 @@ parse_branch_stack(const struct option *opt, const char *str, int unset)

static void callchain_debug(void)
{
	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };

	pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);

@@ -751,9 +751,9 @@ static struct record record = {
#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "

#ifdef HAVE_DWARF_UNWIND_SUPPORT
const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
#else
const char record_callchain_help[] = CALLCHAIN_HELP "fp";
const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
#endif

/*
+2 −0
Original line number Diff line number Diff line
@@ -249,6 +249,8 @@ static int report__setup_sample_type(struct report *rep)
		if ((sample_type & PERF_SAMPLE_REGS_USER) &&
		    (sample_type & PERF_SAMPLE_STACK_USER))
			callchain_param.record_mode = CALLCHAIN_DWARF;
		else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
			callchain_param.record_mode = CALLCHAIN_LBR;
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
+8 −0
Original line number Diff line number Diff line
@@ -97,6 +97,14 @@ int parse_callchain_record_opt(const char *arg)
				callchain_param.dump_size = size;
			}
#endif /* HAVE_DWARF_UNWIND_SUPPORT */
		} else if (!strncmp(name, "lbr", sizeof("lbr"))) {
			if (!strtok_r(NULL, ",", &saveptr)) {
				callchain_param.record_mode = CALLCHAIN_LBR;
				ret = 0;
			} else
				pr_err("callchain: No more arguments "
					"needed for --call-graph lbr\n");
			break;
		} else {
			pr_err("callchain: Unknown --call-graph option "
			       "value: %s\n", arg);
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ enum perf_call_graph_mode {
	CALLCHAIN_NONE,
	CALLCHAIN_FP,
	CALLCHAIN_DWARF,
	CALLCHAIN_LBR,
	CALLCHAIN_MAX
};

Loading