Re: [tip:perf/core] perf tools: Adding PERF_ATTR_SIZE_VER2 to the header swap check
On Tue, Aug 21, 2012 at 07:12:10PM +0200, Peter Zijlstra wrote: On Tue, 2012-08-21 at 08:51 -0700, tip-bot for Jiri Olsa wrote: @@ -1829,6 +1829,7 @@ out_free: static const int attr_file_abi_sizes[] = { [0] = PERF_ATTR_SIZE_VER0, [1] = PERF_ATTR_SIZE_VER1, + [2] = PERF_ATTR_SIZE_VER2, 0, }; Didn't we just get to VER4 ? that's leftover for the branch_sample_type addition jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf: Keep the perf_event_attr on version 3
On Tue, Aug 21, 2012 at 07:11:56PM +0200, Peter Zijlstra wrote: On Tue, 2012-08-21 at 08:49 -0700, tip-bot for Jiri Olsa wrote: #define PERF_ATTR_SIZE_VER388 /* add: sample_regs_user */ +#define PERF_ATTR_SIZE_VER496 /* add: sample_stack_user */ Both are introduced in this patch set, there's no release in between, why are we doing two version increments? Seems like pointless version space inflation to me. not sure why I did that, attached patch returns that to version3 jirka --- Stashing version 4 under version 3 and removing version 4, because both version changes were within single patchset. Reported-by: Peter Zijlstra a.p.zijls...@chello.nl Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- include/linux/perf_event.h | 4 ++-- tools/perf/util/header.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 297ca3d..28f9cee 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -205,8 +205,8 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER064 /* sizeof first published struct */ #define PERF_ATTR_SIZE_VER172 /* add: config2 */ #define PERF_ATTR_SIZE_VER280 /* add: branch_sample_type */ -#define PERF_ATTR_SIZE_VER388 /* add: sample_regs_user */ -#define PERF_ATTR_SIZE_VER496 /* add: sample_stack_user */ +#define PERF_ATTR_SIZE_VER396 /* add: sample_regs_user */ + /* add: sample_stack_user */ /* * Hardware event_id to monitor via a performance monitoring event: diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 1e5b6aa..5ed4812 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1831,7 +1831,6 @@ static const int attr_file_abi_sizes[] = { [1] = PERF_ATTR_SIZE_VER1, [2] = PERF_ATTR_SIZE_VER2, [3] = PERF_ATTR_SIZE_VER3, - [4] = PERF_ATTR_SIZE_VER4, 0, }; -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf tools: Fix 'No libunwind found' make warning message
On Tue, Aug 21, 2012 at 11:36:28AM +0200, Jiri Olsa wrote: On Tue, Aug 21, 2012 at 11:32:31AM +0200, Ingo Molnar wrote: * Arnaldo Carvalho de Melo a...@infradead.org wrote: SNIP One minor observation, the Makefile tells us: Makefile:496: No libunwind found. Please install libunwind = 0.99 I guess that should be libunwind-dev[el], right? Plain libunwind is not enough. right, will fix it thanks, jirka --- Changing error message when libunwind support is not found to inform properly to install libunwind-dev[el] package. Reported-by: Ingo Molnar mi...@elte.hu Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 6bd888d..218cdb5 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -493,7 +493,7 @@ endif FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y) - msg := $(warning No libunwind found. Please install libunwind = 0.99); + msg := $(warning No libunwind found, disables post unwind support. Please install libunwind-dev[el] = 0.99); NO_LIBUNWIND := 1 endif # Libunwind support endif # NO_LIBUNWIND -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 06/13] perf test: Add perf_event_attr record graph test
Adding tests to validate perf_event_attr data for commands: 'record -g --' 'record -g fp 'record -g dwarf Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com graph --- tools/perf/util/test-attr/test-record-graph-default | 6 ++ tools/perf/util/test-attr/test-record-graph-dwarf | 6 ++ tools/perf/util/test-attr/test-record-graph-fp | 6 ++ 3 files changed, 18 insertions(+) create mode 100644 tools/perf/util/test-attr/test-record-graph-default create mode 100644 tools/perf/util/test-attr/test-record-graph-dwarf create mode 100644 tools/perf/util/test-attr/test-record-graph-fp diff --git a/tools/perf/util/test-attr/test-record-graph-default b/tools/perf/util/test-attr/test-record-graph-default new file mode 100644 index 000..833d184 --- /dev/null +++ b/tools/perf/util/test-attr/test-record-graph-default @@ -0,0 +1,6 @@ +[config] +command = record +args= -g -- kill /dev/null 21 + +[event:base-record] +sample_type=295 diff --git a/tools/perf/util/test-attr/test-record-graph-dwarf b/tools/perf/util/test-attr/test-record-graph-dwarf new file mode 100644 index 000..41f3f67 --- /dev/null +++ b/tools/perf/util/test-attr/test-record-graph-dwarf @@ -0,0 +1,6 @@ +[config] +command = record +args= -g dwarf -- kill /dev/null 21 + +[event:base-record] +sample_type=295 diff --git a/tools/perf/util/test-attr/test-record-graph-fp b/tools/perf/util/test-attr/test-record-graph-fp new file mode 100644 index 000..7cef374 --- /dev/null +++ b/tools/perf/util/test-attr/test-record-graph-fp @@ -0,0 +1,6 @@ +[config] +command = record +args= -g fp kill /dev/null 21 + +[event:base-record] +sample_type=295 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 12/13] perf test: Add perf_event_attr stat group test
Adding test to validate perf_event_attr data for command: 'stat --group -e cycles,instructions' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/test-stat-group | 15 +++ 1 file changed, 15 insertions(+) create mode 100644 tools/perf/util/test-attr/test-stat-group diff --git a/tools/perf/util/test-attr/test-stat-group b/tools/perf/util/test-attr/test-stat-group new file mode 100644 index 000..fdc1596 --- /dev/null +++ b/tools/perf/util/test-attr/test-stat-group @@ -0,0 +1,15 @@ +[config] +command = stat +args= --group -e cycles,instructions kill /dev/null 21 +ret = 1 + +[event-1:base-stat] +fd=1 +group_fd=-1 + +[event-2:base-stat] +fd=2 +group_fd=1 +config=1 +disabled=0 +enable_on_exec=0 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 13/13] perf test: Add attr tests under builtin test command
The test attr suite is run only if it's run under perf source directory, because test attr files are not installed. If run elsewhere, tests are ommited (notification is displayed) and finished as successfull. Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/builtin-test.c | 4 tools/perf/perf.h | 1 + tools/perf/util/test-attr.c | 14 ++ 3 files changed, 19 insertions(+) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 381d5ab..f2d3c50 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -1135,6 +1135,10 @@ static struct test { .func = dso__test_data, }, { + .desc = Test perf attr, + .func = test_attr__run, + }, + { .func = NULL, }, }; diff --git a/tools/perf/perf.h b/tools/perf/perf.h index a67bb75..2039774 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -174,6 +174,7 @@ void test_attr__init(void); int test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags); +int test_attr__run(void); static inline int sys_perf_event_open(struct perf_event_attr *attr, diff --git a/tools/perf/util/test-attr.c b/tools/perf/util/test-attr.c index dd83954..eb610f7 100644 --- a/tools/perf/util/test-attr.c +++ b/tools/perf/util/test-attr.c @@ -126,3 +126,17 @@ int test_attr__open(struct perf_event_attr *attr, return fd; } + +int test_attr__run(void) +{ + struct stat st; + const char *run; + + run = python ./util/test-attr.py -d ./util/test-attr/ -p ./perf; + + if (!lstat(./util/, st)) + return system(run); + + fprintf(stderr, (ommitted)); + return 0; +} -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 09/13] perf test: Add perf_event_attr record no-inherit test
Adding test to validate perf_event_attr data for command: 'record -i' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/test-record-no-inherit | 7 +++ 1 file changed, 7 insertions(+) create mode 100644 tools/perf/util/test-attr/test-record-no-inherit diff --git a/tools/perf/util/test-attr/test-record-no-inherit b/tools/perf/util/test-attr/test-record-no-inherit new file mode 100644 index 000..9079a25 --- /dev/null +++ b/tools/perf/util/test-attr/test-record-no-inherit @@ -0,0 +1,7 @@ +[config] +command = record +args= -i kill /dev/null 21 + +[event:base-record] +sample_type=259 +inherit=0 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 04/13] perf test: Add perf_event_attr record freq test
Adding test to validate perf_event_attr data for command: 'record -F 100' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/test-record-freq | 6 ++ 1 file changed, 6 insertions(+) create mode 100644 tools/perf/util/test-attr/test-record-freq diff --git a/tools/perf/util/test-attr/test-record-freq b/tools/perf/util/test-attr/test-record-freq new file mode 100644 index 000..600d0f8 --- /dev/null +++ b/tools/perf/util/test-attr/test-record-freq @@ -0,0 +1,6 @@ +[config] +command = record +args= -F 100 kill /dev/null 21 + +[event:base-record] +sample_period=100 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 11/13] perf test: Add perf_event_attr stat no-inherit test
Adding test to validate perf_event_attr data for command: 'stat -i' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/test-stat-no-inherit | 7 +++ 1 file changed, 7 insertions(+) create mode 100644 tools/perf/util/test-attr/test-stat-no-inherit diff --git a/tools/perf/util/test-attr/test-stat-no-inherit b/tools/perf/util/test-attr/test-stat-no-inherit new file mode 100644 index 000..d54b2a1e --- /dev/null +++ b/tools/perf/util/test-attr/test-stat-no-inherit @@ -0,0 +1,7 @@ +[config] +command = stat +args= -i -e cycles kill /dev/null 21 +ret = 1 + +[event:base-stat] +inherit=0 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 08/13] perf test: Add perf_event_attr record no samples test
Adding test to validate perf_event_attr data for command: 'record -n' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/test-record-no-samples | 6 ++ 1 file changed, 6 insertions(+) create mode 100644 tools/perf/util/test-attr/test-record-no-samples diff --git a/tools/perf/util/test-attr/test-record-no-samples b/tools/perf/util/test-attr/test-record-no-samples new file mode 100644 index 000..d0141b2 --- /dev/null +++ b/tools/perf/util/test-attr/test-record-no-samples @@ -0,0 +1,6 @@ +[config] +command = record +args= -n kill /dev/null 21 + +[event:base-record] +sample_period=0 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 10/13] perf test: Add perf_event_attr stat basic test
Adding test to validate perf_event_attr data for command: 'stat' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/base-stat | 39 +++ tools/perf/util/test-attr/test-stat-basic | 6 + 2 files changed, 45 insertions(+) create mode 100644 tools/perf/util/test-attr/base-stat create mode 100644 tools/perf/util/test-attr/test-stat-basic diff --git a/tools/perf/util/test-attr/base-stat b/tools/perf/util/test-attr/base-stat new file mode 100644 index 000..f46db90 --- /dev/null +++ b/tools/perf/util/test-attr/base-stat @@ -0,0 +1,39 @@ +[event] +fd=1 +group_fd=-1 +flags=0 +type=0 +size=96 +config=0 +sample_period=0 +sample_type=0 +read_format=3 +disabled=1 +inherit=1 +pinned=0 +exclusive=0 +exclude_user=0 +exclude_kernel=0 +exclude_hv=0 +exclude_idle=0 +mmap=0 +comm=0 +freq=0 +inherit_stat=0 +enable_on_exec=1 +task=0 +watermask=0 +precise_ip=0 +mmap_data=0 +sample_id_all=0 +exclude_host=0 +exclude_guest=1 +exclude_callchain_kernel=0 +exclude_callchain_user=0 +wakeup_events=0 +bp_type=0 +config1=0 +config2=0 +branch_sample_type=0 +sample_regs_user=0 +sample_stack_user=0 diff --git a/tools/perf/util/test-attr/test-stat-basic b/tools/perf/util/test-attr/test-stat-basic new file mode 100644 index 000..74e1788 --- /dev/null +++ b/tools/perf/util/test-attr/test-stat-basic @@ -0,0 +1,6 @@ +[config] +command = stat +args= -e cycles kill /dev/null 21 +ret = 1 + +[event:base-stat] -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 07/13] perf test: Add perf_event_attr record period test
Adding test to validate perf_event_attr data for command: 'record -c 100 -P' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/test-record-period | 7 +++ 1 file changed, 7 insertions(+) create mode 100644 tools/perf/util/test-attr/test-record-period diff --git a/tools/perf/util/test-attr/test-record-period b/tools/perf/util/test-attr/test-record-period new file mode 100644 index 000..8abc531 --- /dev/null +++ b/tools/perf/util/test-attr/test-record-period @@ -0,0 +1,7 @@ +[config] +command = record +args= -c 100 -P kill /dev/null 21 + +[event:base-record] +sample_period=100 +freq=0 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 05/13] perf test: Add perf_event_attr record count test
Adding test to validate perf_event_attr data for command: 'record -c 123' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/test-record-count | 8 1 file changed, 8 insertions(+) create mode 100644 tools/perf/util/test-attr/test-record-count diff --git a/tools/perf/util/test-attr/test-record-count b/tools/perf/util/test-attr/test-record-count new file mode 100644 index 000..2f841de --- /dev/null +++ b/tools/perf/util/test-attr/test-record-count @@ -0,0 +1,8 @@ +[config] +command = record +args= -c 123 kill /dev/null 21 + +[event:base-record] +sample_period=123 +sample_type=7 +freq=0 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 03/13] perf test: Add perf_event_attr record group test
Adding test to validate perf_event_attr data for command: 'record --group -e cycles,instructions' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/test-record-group | 17 + 1 file changed, 17 insertions(+) create mode 100644 tools/perf/util/test-attr/test-record-group diff --git a/tools/perf/util/test-attr/test-record-group b/tools/perf/util/test-attr/test-record-group new file mode 100644 index 000..6cff60f --- /dev/null +++ b/tools/perf/util/test-attr/test-record-group @@ -0,0 +1,17 @@ +[config] +command = record +args= --group -e cycles,instructions kill 2/dev/null + +[event-1:base-record] +fd=1 +group_fd=-1 +sample_type=327 + +[event-2:base-record] +fd=2 +group_fd=1 +config=1 +sample_type=327 +mmap=0 +comm=0 +enable_on_exec=0 -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC 00/13] perf test: Add perf_event_attr tests
hi, this code tests the link between perf stat/record command line options and final perf_event_attr struct values. Also it tests the group fd linkage. It's probably missing many command line option combinations worth testing. I wanted to check with others for more ideas before diving into this. You can check this also here: git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/linux.git perf/attr_tests4 thanks, jirka Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/Makefile | 1 + tools/perf/builtin-test.c | 4 + tools/perf/perf.c | 2 + tools/perf/perf.h | 11 ++ tools/perf/util/test-attr.c | 142 ++ tools/perf/util/test-attr.py| 272 ++ tools/perf/util/test-attr/base-record | 39 tools/perf/util/test-attr/base-stat | 39 tools/perf/util/test-attr/test-record-basic | 5 + tools/perf/util/test-attr/test-record-count | 8 ++ tools/perf/util/test-attr/test-record-freq | 6 ++ tools/perf/util/test-attr/test-record-graph-default | 6 ++ tools/perf/util/test-attr/test-record-graph-dwarf | 6 ++ tools/perf/util/test-attr/test-record-graph-fp | 6 ++ tools/perf/util/test-attr/test-record-group | 17 tools/perf/util/test-attr/test-record-no-inherit| 7 ++ tools/perf/util/test-attr/test-record-no-samples| 6 ++ tools/perf/util/test-attr/test-record-period| 7 ++ tools/perf/util/test-attr/test-stat-basic | 6 ++ tools/perf/util/test-attr/test-stat-group | 15 +++ tools/perf/util/test-attr/test-stat-no-inherit | 7 ++ 21 files changed, 612 insertions(+) -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 02/13] perf test: Add perf_event_attr record basic test
Adding test to validate perf_event_attr data for command: 'record' Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/test-attr/base-record | 39 + tools/perf/util/test-attr/test-record-basic | 5 2 files changed, 44 insertions(+) create mode 100644 tools/perf/util/test-attr/base-record create mode 100644 tools/perf/util/test-attr/test-record-basic diff --git a/tools/perf/util/test-attr/base-record b/tools/perf/util/test-attr/base-record new file mode 100644 index 000..ea2d3c5 --- /dev/null +++ b/tools/perf/util/test-attr/base-record @@ -0,0 +1,39 @@ +[event] +fd=1 +group_fd=-1 +flags=0 +type=0 +size=96 +config=0 +sample_period=4000 +sample_type=263 +read_format=7 +disabled=1 +inherit=1 +pinned=0 +exclusive=0 +exclude_user=0 +exclude_kernel=0 +exclude_hv=0 +exclude_idle=0 +mmap=1 +comm=1 +freq=1 +inherit_stat=0 +enable_on_exec=1 +task=0 +watermask=0 +precise_ip=0 +mmap_data=0 +sample_id_all=1 +exclude_host=0 +exclude_guest=1 +exclude_callchain_kernel=0 +exclude_callchain_user=0 +wakeup_events=0 +bp_type=0 +config1=0 +config2=0 +branch_sample_type=0 +sample_regs_user=0 +sample_stack_user=0 diff --git a/tools/perf/util/test-attr/test-record-basic b/tools/perf/util/test-attr/test-record-basic new file mode 100644 index 000..55c0428 --- /dev/null +++ b/tools/perf/util/test-attr/test-record-basic @@ -0,0 +1,5 @@ +[config] +command = record +args= kill /dev/null 21 + +[event:base-record] -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 01/13] perf test: Add framework for atomated perf_event_attr tests
Adding automated test to check event's perf_event_attr values. The idea is run perf session with kidnaping sys_perf_event_open function. For each sys_perf_event_open call we store the perf_event_attr data to the file to be checked later against what we expect. You can run this by: # python ./util/test-attr.py -d ./util/test-attr/ -p ./perf -v Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/Makefile | 1 + tools/perf/perf.c| 2 + tools/perf/perf.h| 10 ++ tools/perf/util/test-attr.c | 128 tools/perf/util/test-attr.py | 272 +++ 5 files changed, 413 insertions(+) create mode 100644 tools/perf/util/test-attr.c create mode 100644 tools/perf/util/test-attr.py diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 722ddee..746375d 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -405,6 +405,7 @@ LIB_OBJS += $(OUTPUT)util/rblist.o LIB_OBJS += $(OUTPUT)util/intlist.o LIB_OBJS += $(OUTPUT)ui/helpline.o LIB_OBJS += $(OUTPUT)ui/stdio/hist.o +LIB_OBJS += $(OUTPUT)util/test-attr.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o diff --git a/tools/perf/perf.c b/tools/perf/perf.c index e7840e5..94092eb13 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -477,6 +477,8 @@ int main(int argc, const char **argv) } cmd = argv[0]; + test_attr__init(); + /* * We use PATH to find perf commands, but we prepend some higher * precedence paths: the --exec-path option, the PERF_EXEC_PATH diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 87f4ec6..a67bb75 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -5,6 +5,7 @@ struct winsize; void get_term_dimensions(struct winsize *ws); + #if defined(__i386__) #include ../../arch/x86/include/asm/unistd.h #define rmb() asm volatile(lock; addl $0,0(%%esp) ::: memory) @@ -168,11 +169,20 @@ static inline unsigned long long rdclock(void) (void) (_min1 == _min2); \ _min1 _min2 ? _min1 : _min2; }) +extern bool test_attr__enabled; +void test_attr__init(void); +int test_attr__open(struct perf_event_attr *attr, +pid_t pid, int cpu, int group_fd, +unsigned long flags); + static inline int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags) { + if (unlikely(test_attr__enabled)) + return test_attr__open(attr, pid, cpu, group_fd, flags); + return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); } diff --git a/tools/perf/util/test-attr.c b/tools/perf/util/test-attr.c new file mode 100644 index 000..dd83954 --- /dev/null +++ b/tools/perf/util/test-attr.c @@ -0,0 +1,128 @@ + +#include stdlib.h +#include stdio.h +#include inttypes.h +#include linux/types.h +#include ../perf.h +#include util.h + +#define ENV PERF_TEST_ATTR + +bool test_attr__enabled; + +static char *dir; + +void test_attr__init(void) +{ + dir = getenv(ENV); + test_attr__enabled = (dir != NULL); +} + +#define BUFSIZE 1024 + +#define WRITE_ASS(str, fmt, data) \ +do { \ + char buf[BUFSIZE]; \ + size_t size;\ + \ + size = snprintf(buf, BUFSIZE, #str =%fmt \n, data); \ + if (1 != fwrite(buf, size, 1, file)) { \ + perror(test attr - failed to write event file); \ + return -1; \ + } \ + \ +} while (0) + +static int store_event(int fd, struct perf_event_attr *attr, + pid_t pid, int cpu, int group_fd, + unsigned long flags) +{ + FILE *file; + char path[PATH_MAX]; + + snprintf(path, PATH_MAX, %s/event-%d, dir, fd); + + file = fopen(path, w+); + if (!file) { + perror(test attr - failed to open event file); + return -1; + } + +#define HEADER [event]\n + if (1 != fwrite(HEADER, sizeof(HEADER) - 1, 1, file)) { + perror(test attr - failed to write event file); + return -1; + } +#undef HEADER + + /* syscall arguments
Re: [PATCHv8 00/13] perf: Add backtrace post dwarf unwind
On Wed, Aug 01, 2012 at 06:04:31AM +0200, Stephane Eranian wrote: On Fri, Jul 27, 2012 at 2:23 PM, Jiri Olsa jo...@redhat.com wrote: hi, patches available also as tarball in here: http://people.redhat.com/~jolsa/perf_post_unwind_v8.tar.bz2 v8 changes: - patch 2 - added dump registers ABI specification as suggested by Stephane - v7 patches 9,10,16,17 already in Patches 4, 7 do not apply cleanly for me on tip-master @ commit 2a7d7ce when I use the tarball version of the patchset. there's conflict with fresh commit.. perf/trace: Add ability to set a target task for events commit e6dab5ffab59e910ec0e3355f4a6f29f7a7be474 Author: Andrew Vagin ava...@openvz.org Date: Wed Jul 11 18:14:58 2012 +0400 I'm testing v9 and will send it out shortly thanks, jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv9 00/13] perf: Add backtrace post dwarf unwind
hi, patches available also as tarball in here: http://people.redhat.com/~jolsa/perf_post_unwind_v9.tar.bz2 v9 changes: - rebased to current tip tree v8 changes: - patch 2 - added dump registers ABI specification as suggested by Stephane - v7 patches 9,10,16,17 already in v7 changes: - omitted v6 patches 9 and 15 They need more work and will be sent separately. I dont want to hold off whole patchset because of them. We could miss some related backtraces (syscall, vdso) in this version. - v6 patch 11, 14, 20 already in v6 changes: patch 01/23 - unrelated - ftrace stuff patch 03/23 - added PERF_SAMPLE_REGS_USER bit - added regs_user initialization patch 07/23 - added PERF_SAMPLE_STACK_USER bit - sample_stack_user changed to u32 and added size check new patches 1,9,10,20 v5 changes: patch 1/19 - having just one enum set of the perf registers patch 2/19 - using for_each_set_bit for scanning the mask - single regs enum for both 32 and 64 bits versions - using regs mask != 0 trigger to trigger the regs dump patch 5/19 - adding perf_output_skip so we can skip undumped part of the stack in RB patch 6/19 - using stack size != 0 trigger to trigger the stack dump - do not zero the memory for non retrieved part of the stack dump patch 7/19 - adding exclude_callchain_kernel attribute patch 8/19 - this could be taken without the rest of the series v4 changes: - no real change from v3, just rebase - v3 patch 06/17 got already merged v3 changes: patch 01/17 - added HAVE_PERF_REGS config option patch 02/17, 04/17 - regs and stack perf interface is more general now patch 06/17 - unrelated online fix for i386 compilation patch 16/17 - few namespace fixies --- Adding the post unwinding user stack backtrace using dwarf unwind via libunwind. The original work was done by Frederic. I mostly took his patches and make them compile in current kernel code plus I added some stuff here and there. The main idea is to store user registers and portion of user stack when the sample data during the record phase. Then during the report, when the data is presented, perform the actual dwarf dwarf unwind. attached patches: 01/13 perf: Unified API to record selective sets of arch registers 02/13 perf: Add ability to attach user level registers dump to sample 03/13 perf, x86: Add copy_from_user_nmi_nochk for best effort copy 04/13 perf: Factor __output_copy to be usable with specific copy function 05/13 perf: Add perf_output_skip function to skip bytes in sample 06/13 perf: Add ability to attach user stack dump to sample 07/13 perf: Add attribute to filter out callchains 08/13 perf, tool: Adding PERF_ATTR_SIZE_VER2 to the header swap check 09/13 perf, tool: Add interface to arch registers sets 10/13 perf, tool: Add libunwind dependency for dwarf cfi unwinding 11/13 perf, tool: Support user regs and stack in sample parsing 12/13 perf, tool: Support for dwarf cfi unwinding on post processing 13/13 perf, tool: Support for dwarf mode callchain on perf record I tested on Fedora. There was not much gain on i386, because the binaries are compiled with frame pointers. Thought the dwarf backtrace is more accurate and unwraps calls in more details (functions that do not set the frame pointers). I could see some improvement on x86_64, where I got full backtrace where current code could got just the first address out of the instruction pointer. Example on x86_64: [dwarf] perf record -g dwarf -e syscalls:sys_enter_write date 100.00% date libc-2.14.90.so [.] __GI___libc_write | --- __GI___libc_write _IO_file_write@@GLIBC_2.2.5 new_do_write _IO_do_write@@GLIBC_2.2.5 _IO_file_overflow@@GLIBC_2.2.5 0x4022cd 0x401ee6 __libc_start_main 0x4020b9 [frame pointer] perf record -g fp -e syscalls:sys_enter_write date 100.00% date libc-2.14.90.so [.] __GI___libc_write | --- __GI___libc_write Also I tested on coreutils binaries mainly, but I could see getting wider backtraces with dwarf unwind for more complex application like firefox. Attached patches should work on both x86 and x86_64. The unwind backtrace can be interrupted by following reasons: - bug in unwind information of processed shared library - bug in unwind processing code (most likely ;) ) - insufficient dump stack size - until full syscall register storage and vdso support we could miss some related backtraces jirka --- arch/Kconfig |6 + arch/x86/Kconfig |1 + arch/x86/include/asm/perf_event.h |2 +
[PATCH 01/13] perf: Unified API to record selective sets of arch registers
This brings a new API to help the selective dump of registers on event sampling, and its implementation for x86 arch. Added HAVE_PERF_REGS config option to determine if the architecture provides perf registers ABI. The information about desired registers will be passed in u64 mask. It's up to the architecture to map the registers into the mask bits. For the x86 arch implementation, both 32 and 64 bit registers bits are defined within single enum to ensure 64 bit system can provide register dump for compat task if needed in the future. Signed-off-by: Jiri Olsa jo...@redhat.com Original-patch-by: Frederic Weisbecker fweis...@gmail.com --- arch/Kconfig |6 +++ arch/x86/Kconfig |1 + arch/x86/include/asm/perf_regs.h | 33 ++ arch/x86/kernel/Makefile |2 + arch/x86/kernel/perf_regs.c | 90 ++ include/linux/perf_regs.h| 19 6 files changed, 151 insertions(+), 0 deletions(-) create mode 100644 arch/x86/include/asm/perf_regs.h create mode 100644 arch/x86/kernel/perf_regs.c create mode 100644 include/linux/perf_regs.h diff --git a/arch/Kconfig b/arch/Kconfig index 8c3d957..32f4873 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -222,6 +222,12 @@ config HAVE_PERF_EVENTS_NMI subsystem. Also has support for calculating CPU cycle events to determine how many clock cycles in a given period. +config HAVE_PERF_REGS + bool + help + Support selective register dumps for perf events. This includes + bit-mapping of each registers and a unique architecture id. + config HAVE_ARCH_JUMP_LABEL bool diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 94de2c5..acebbd6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -60,6 +60,7 @@ config X86 select HAVE_MIXED_BREAKPOINTS_REGS select PERF_EVENTS select HAVE_PERF_EVENTS_NMI + select HAVE_PERF_REGS select ANON_INODES select HAVE_ALIGNED_STRUCT_PAGE if SLUB !M386 select HAVE_CMPXCHG_LOCAL if !M386 diff --git a/arch/x86/include/asm/perf_regs.h b/arch/x86/include/asm/perf_regs.h new file mode 100644 index 000..3f2207b --- /dev/null +++ b/arch/x86/include/asm/perf_regs.h @@ -0,0 +1,33 @@ +#ifndef _ASM_X86_PERF_REGS_H +#define _ASM_X86_PERF_REGS_H + +enum perf_event_x86_regs { + PERF_REG_X86_AX, + PERF_REG_X86_BX, + PERF_REG_X86_CX, + PERF_REG_X86_DX, + PERF_REG_X86_SI, + PERF_REG_X86_DI, + PERF_REG_X86_BP, + PERF_REG_X86_SP, + PERF_REG_X86_IP, + PERF_REG_X86_FLAGS, + PERF_REG_X86_CS, + PERF_REG_X86_SS, + PERF_REG_X86_DS, + PERF_REG_X86_ES, + PERF_REG_X86_FS, + PERF_REG_X86_GS, + PERF_REG_X86_R8, + PERF_REG_X86_R9, + PERF_REG_X86_R10, + PERF_REG_X86_R11, + PERF_REG_X86_R12, + PERF_REG_X86_R13, + PERF_REG_X86_R14, + PERF_REG_X86_R15, + + PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1, + PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1, +}; +#endif /* _ASM_X86_PERF_REGS_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 8215e56..8d7a619 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -100,6 +100,8 @@ obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_UPROBES) += uprobes.o +obj-$(CONFIG_PERF_EVENTS) += perf_regs.o + ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y) diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c new file mode 100644 index 000..c00c92a --- /dev/null +++ b/arch/x86/kernel/perf_regs.c @@ -0,0 +1,90 @@ + +#include linux/kernel.h +#include linux/bug.h +#include linux/stddef.h +#include asm/perf_regs.h +#include asm/ptrace.h + +#ifdef CONFIG_X86_32 +#define PERF_REG_X86_MAX PERF_REG_X86_32_MAX +#else +#define PERF_REG_X86_MAX PERF_REG_X86_64_MAX +#endif + +#define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) + +static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = { + PT_REGS_OFFSET(PERF_REG_X86_AX, ax), + PT_REGS_OFFSET(PERF_REG_X86_BX, bx), + PT_REGS_OFFSET(PERF_REG_X86_CX, cx), + PT_REGS_OFFSET(PERF_REG_X86_DX, dx), + PT_REGS_OFFSET(PERF_REG_X86_SI, si), + PT_REGS_OFFSET(PERF_REG_X86_DI, di), + PT_REGS_OFFSET(PERF_REG_X86_BP, bp), + PT_REGS_OFFSET(PERF_REG_X86_SP, sp), + PT_REGS_OFFSET(PERF_REG_X86_IP, ip), + PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags), + PT_REGS_OFFSET(PERF_REG_X86_CS, cs), + PT_REGS_OFFSET(PERF_REG_X86_SS, ss), +#ifdef CONFIG_X86_32 + PT_REGS_OFFSET(PERF_REG_X86_DS, ds), + PT_REGS_OFFSET(PERF_REG_X86_ES, es), + PT_REGS_OFFSET(PERF_REG_X86_FS, fs), + PT_REGS_OFFSET(PERF_REG_X86_GS, gs), +#else + /* +* The pt_regs struct does not store
[PATCH 04/13] perf: Factor __output_copy to be usable with specific copy function
From: Frederic Weisbecker fweis...@gmail.com Adding a generic way to use __output_copy function with specific copy function via DEFINE_PERF_OUTPUT_COPY macro. Using this to add new __output_copy_user function, that provides output copy from user pointers. For x86 the copy_from_user_nmi_nochk function is used and __copy_from_user_inatomic for the rest of the architectures. This new function will be used in user stack dump on sample, coming in next patches. Signed-off-by: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- arch/x86/include/asm/perf_event.h |2 + include/linux/perf_event.h|2 +- kernel/events/internal.h | 62 kernel/events/ring_buffer.c |4 +- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index cb4e43b..054d64f 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -262,4 +262,6 @@ static inline void perf_check_microcode(void) { } static inline void amd_pmu_disable_virt(void) { } #endif +#define arch_perf_out_copy_user copy_from_user_nmi_nochk + #endif /* _ASM_X86_PERF_EVENT_H */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 3d4d847..d41394a 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1319,7 +1319,7 @@ static inline bool has_branch_stack(struct perf_event *event) extern int perf_output_begin(struct perf_output_handle *handle, struct perf_event *event, unsigned int size); extern void perf_output_end(struct perf_output_handle *handle); -extern void perf_output_copy(struct perf_output_handle *handle, +extern unsigned int perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len); extern int perf_swevent_get_recursion_context(void); extern void perf_swevent_put_recursion_context(int rctx); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index a096c19..7fd5408 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -2,6 +2,7 @@ #define _KERNEL_EVENTS_INTERNAL_H #include linux/hardirq.h +#include linux/uaccess.h /* Buffer handling */ @@ -76,30 +77,49 @@ static inline unsigned long perf_data_size(struct ring_buffer *rb) return rb-nr_pages (PAGE_SHIFT + page_order(rb)); } -static inline void -__output_copy(struct perf_output_handle *handle, - const void *buf, unsigned int len) +#define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \ +static inline unsigned int \ +func_name(struct perf_output_handle *handle, \ + const void *buf, unsigned int len)\ +{ \ + unsigned long size, written;\ + \ + do {\ + size = min_t(unsigned long, handle-size, len); \ + \ + written = memcpy_func(handle-addr, buf, size); \ + \ + len -= written; \ + handle-addr += written;\ + buf += written; \ + handle-size -= written;\ + if (!handle-size) {\ + struct ring_buffer *rb = handle-rb;\ + \ + handle-page++; \ + handle-page = rb-nr_pages - 1; \ + handle-addr = rb-data_pages[handle-page];\ + handle-size = PAGE_SIZE page_order(rb); \ + } \ + } while (len written == size); \ + \ + return len; \ +} + +static inline int memcpy_common(void *dst, const void *src, size_t n) { - do { - unsigned long size = min_t(unsigned long, handle-size, len); - - memcpy(handle-addr, buf, size); - - len -= size; - handle-addr += size; - buf += size; - handle-size -= size; - if (!handle-size) { - struct
[PATCH 03/13] perf, x86: Add copy_from_user_nmi_nochk for best effort copy
Adding copy_from_user_nmi_nochk that provides the best effort copy regardless the requesting size crossing the task boundary. This is going to be useful for stack dump we need in post DWARF CFI based unwind, where we have predefined size of the user stack to dump, and we need to store the most of the requested dump size, regardless this size is crossing the task boundary. Signed-off-by: Jiri Olsa jo...@redhat.com --- arch/x86/include/asm/uaccess.h |2 ++ arch/x86/lib/usercopy.c| 15 +++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index e1f3a17..d8d6bcd 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -562,6 +562,8 @@ struct __large_struct { unsigned long buf[100]; }; #endif /* CONFIG_X86_WP_WORKS_OK */ extern unsigned long +copy_from_user_nmi_nochk(void *to, const void __user *from, unsigned long n); +extern unsigned long copy_from_user_nmi(void *to, const void __user *from, unsigned long n); extern __must_check long strncpy_from_user(char *dst, const char __user *src, long count); diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index 4f74d94..29ca1c7 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -14,7 +14,7 @@ * best effort, GUP based copy_from_user() that is NMI-safe */ unsigned long -copy_from_user_nmi(void *to, const void __user *from, unsigned long n) +copy_from_user_nmi_nochk(void *to, const void __user *from, unsigned long n) { unsigned long offset, addr = (unsigned long)from; unsigned long size, len = 0; @@ -22,9 +22,6 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) void *map; int ret; - if (__range_not_ok(from, n, TASK_SIZE)) - return len; - do { ret = __get_user_pages_fast(addr, 1, 0, page); if (!ret) @@ -46,4 +43,14 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) return len; } +EXPORT_SYMBOL_GPL(copy_from_user_nmi_nochk); + +unsigned long +copy_from_user_nmi(void *to, const void __user *from, unsigned long n) +{ + if (__range_not_ok(from, n, TASK_SIZE) == 0) + return 0; + + return copy_from_user_nmi_nochk(to, from, n); +} EXPORT_SYMBOL_GPL(copy_from_user_nmi); -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 07/13] perf: Add attribute to filter out callchains
From: Frederic Weisbecker fweis...@gmail.com 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: Frederic Weisbecker fweis...@gmail.com [ Added kernel callchains filtering ] Signed-off-by: Jiri Olsa jo...@redhat.com CC: Andrew Vagin ava...@openvz.org --- include/linux/perf_event.h |5 - kernel/events/callchain.c | 36 +--- kernel/events/core.c |6 +- kernel/events/internal.h |3 ++- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index d1d25f6..297ca3d 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -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 */ diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c index 98d4597..cbed627 100644 --- a/kernel/events/callchain.c +++ b/kernel/events/callchain.c @@ -154,7 +154,8 @@ put_callchain_entry(int rctx) } struct perf_callchain_entry * -perf_callchain(struct perf_event *event, struct pt_regs *regs) +perf_callchain(struct perf_event *event, struct pt_regs *regs, + int kernel, int user) { int rctx; struct perf_callchain_entry *entry; @@ -169,24 +170,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: diff --git a/kernel/events/core.c b/kernel/events/core.c index c4582bb..0902d4a 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4130,8 +4130,12 @@ void perf_prepare_sample(struct perf_event_header *header, if (sample_type PERF_SAMPLE_CALLCHAIN) { int size = 1; + int kernel = !event-attr.exclude_callchain_kernel; + int user = !event-attr.exclude_callchain_user; - data-callchain = perf_callchain(event, regs); + if (kernel || user) + data-callchain = perf_callchain(event, regs, +kernel, user); if (data-callchain) size += data-callchain-nr; diff --git a/kernel/events/internal.h b/kernel/events/internal.h index ce7bdfc..95d0215 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -126,7 +126,8 @@ DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user) /* Callchain handling */ extern struct perf_callchain_entry * -perf_callchain(struct perf_event *event, struct pt_regs *regs); +perf_callchain(struct perf_event *event, struct pt_regs *regs, + int kernel, int user); extern int get_callchain_buffers(void); extern void put_callchain_buffers(void
[PATCH 05/13] perf: Add perf_output_skip function to skip bytes in sample
Introducing perf_output_skip function to be able to skip data within the perf ring buffer. When writing data into perf ring buffer we first reserve needed place in ring buffer and then copy the actual data. There's a possibility we won't be able to fill all the reserved size with data, so we need a way to skip the remaining bytes. This is going to be useful when storing the user stack dump, where we might end up with less data than we originally requested. Signed-off-by: Jiri Olsa jo...@redhat.com Acked-by: Frederic Weisbecker fweis...@gmail.com --- include/linux/perf_event.h |2 ++ kernel/events/internal.h|4 kernel/events/ring_buffer.c |6 ++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index d41394a..8a73f75 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1321,6 +1321,8 @@ extern int perf_output_begin(struct perf_output_handle *handle, extern void perf_output_end(struct perf_output_handle *handle); extern unsigned int perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len); +extern unsigned int perf_output_skip(struct perf_output_handle *handle, +unsigned int len); extern int perf_swevent_get_recursion_context(void); extern void perf_swevent_put_recursion_context(int rctx); extern void perf_event_enable(struct perf_event *event); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 7fd5408..ce7bdfc 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -114,6 +114,10 @@ static inline int memcpy_common(void *dst, const void *src, size_t n) DEFINE_OUTPUT_COPY(__output_copy, memcpy_common) +#define MEMCPY_SKIP(dst, src, n) (n) + +DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP) + #ifndef arch_perf_out_copy_user #define arch_perf_out_copy_user __copy_from_user_inatomic #endif diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index b4c2ad3..23cb34f 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -188,6 +188,12 @@ unsigned int perf_output_copy(struct perf_output_handle *handle, return __output_copy(handle, buf, len); } +unsigned int perf_output_skip(struct perf_output_handle *handle, + unsigned int len) +{ + return __output_skip(handle, NULL, len); +} + void perf_output_end(struct perf_output_handle *handle) { perf_output_put_handle(handle); -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 10/13] perf, tool: Add libunwind dependency for dwarf cfi unwinding
Adding libunwind to be linked with perf if available. It's required for the to get dwarf cfi unwinding support. Also building perf with the dwarf call frame informations by default, so that we can unwind callchains in perf itself. Adding LIBUNWIND_DIR Makefile variable allowing user to specify the directory with libunwind to be linked. This is used for debug purposes. Signed-off-by: Jiri Olsa jo...@redhat.com Original-patch-by: Frederic Weisbecker fweis...@gmail.com --- tools/perf/Makefile | 30 +- tools/perf/config/feature-tests.mak | 25 + 2 files changed, 54 insertions(+), 1 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 0548d93..a1ee011 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -38,6 +38,9 @@ include config/utilities.mak # Define NO_NEWT if you do not want TUI support. # # Define NO_DEMANGLE if you do not want C++ symbol demangling. +# +# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf +# backtrace post unwind. $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) @@ -59,6 +62,7 @@ AR = $(CROSS_COMPILE)ar ifeq ($(ARCH),i386) ARCH := x86 NO_PERF_REGS := 0 + LIBUNWIND_LIBS = -lunwind -lunwind-x86 endif ifeq ($(ARCH),x86_64) ARCH := x86 @@ -72,6 +76,7 @@ ifeq ($(ARCH),x86_64) ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S endif NO_PERF_REGS := 0 + LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 endif # Treat warnings as errors unless directed not to @@ -92,7 +97,7 @@ ifdef PARSER_DEBUG PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG endif -CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) +CFLAGS = -fno-omit-frame-pointer -ggdb3 -funwind-tables -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) EXTLIBS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE ALL_LDFLAGS = $(LDFLAGS) @@ -457,6 +462,21 @@ ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) endif # Dwarf support endif # NO_DWARF +ifndef NO_LIBUNWIND +# for linking with debug library, run like: +# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ +ifdef LIBUNWIND_DIR + LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include + LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib +endif + +FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) +ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y) + msg := $(warning No libunwind found. Please install libunwind = 0.99); + NO_LIBUNWIND := 1 +endif # Libunwind support +endif # NO_LIBUNWIND + -include arch/$(ARCH)/Makefile ifneq ($(OUTPUT),) @@ -488,6 +508,14 @@ else endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF +ifdef NO_LIBUNWIND + BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT +else + EXTLIBS += $(LIBUNWIND_LIBS) + BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS) + BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS) +endif + ifdef NO_NEWT BASIC_CFLAGS += -DNO_NEWT_SUPPORT else diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak index 6c18785..2f1156a 100644 --- a/tools/perf/config/feature-tests.mak +++ b/tools/perf/config/feature-tests.mak @@ -154,3 +154,28 @@ int main(void) return 0; } endef + +ifndef NO_LIBUNWIND +define SOURCE_LIBUNWIND +#include libunwind.h +#include stdlib.h + +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); + + +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) + +int main(void) +{ + unw_addr_space_t addr_space; + addr_space = unw_create_addr_space(NULL, 0); + unw_init_remote(NULL, addr_space, NULL); + dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL); + return 0; +} +endef +endif -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 11/13] perf, tool: Support user regs and stack in sample parsing
Adding following info to be parsed out of the event sample: - user register set - user stack dump Both are global and specific to all events within the session. This info will be used in the unwind patches coming in shortly. Adding simple output printout (report -D) for both register and stack dumps. Signed-off-by: Jiri Olsa jo...@redhat.com Original-patch-by: Frederic Weisbecker fweis...@gmail.com --- tools/perf/builtin-test.c |4 ++-- tools/perf/util/event.h | 16 +++- tools/perf/util/evlist.c |8 tools/perf/util/evlist.h |1 + tools/perf/util/evsel.c | 30 +- tools/perf/util/header.c |2 ++ tools/perf/util/python.c |3 ++- tools/perf/util/session.c | 36 tools/perf/util/session.h |8 ++-- 9 files changed, 101 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index d909eb7..000efb0 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -564,7 +564,7 @@ static int test__basic_mmap(void) } err = perf_event__parse_sample(event, attr.sample_type, sample_size, - false, sample, false); + false, 0, sample, false); if (err) { pr_err(Can't parse sample, err = %d\n, err); goto out_munmap; @@ -790,7 +790,7 @@ static int test__PERF_RECORD(void) err = perf_event__parse_sample(event, sample_type, sample_size, true, - sample, false); + 0, sample, false); if (err 0) { if (verbose) perf_event__fprintf(event, stderr); diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 1b19728..ed978eb 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -69,6 +69,16 @@ struct sample_event { u64 array[]; }; +struct regs_dump { + u64 *regs; +}; + +struct stack_dump { + u16 offset; + u64 size; + char *data; +}; + struct perf_sample { u64 ip; u32 pid, tid; @@ -82,6 +92,8 @@ struct perf_sample { void *raw_data; struct ip_callchain *callchain; struct branch_stack *branch_stack; + struct regs_dump user_regs; + struct stack_dump user_stack; }; #define BUILD_ID_SIZE 20 @@ -199,7 +211,9 @@ const char *perf_event__name(unsigned int id); int perf_event__parse_sample(const union perf_event *event, u64 type, int sample_size, bool sample_id_all, -struct perf_sample *sample, bool swapped); +u64 sample_regs_user, struct perf_sample *data, +bool swapped); + int perf_event__synthesize_sample(union perf_event *event, u64 type, const struct perf_sample *sample, bool swapped); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3edfd34..057a27d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -689,6 +689,14 @@ bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) return true; } +u64 perf_evlist__sample_regs_user(const struct perf_evlist *evlist) +{ + struct perf_evsel *first; + + first = list_entry(evlist-entries.next, struct perf_evsel, node); + return first-attr.sample_regs_user; +} + u64 perf_evlist__sample_type(const struct perf_evlist *evlist) { struct perf_evsel *first; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 40d4d3c..8dbf46c 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -124,6 +124,7 @@ u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); +u64 perf_evlist__sample_regs_user(const struct perf_evlist *evlist); void perf_evlist__splice_list_tail(struct perf_evlist *evlist, struct list_head *list, diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index e817713..3a284b1 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -8,6 +8,7 @@ */ #include byteswap.h +#include linux/bitops.h #include asm/bug.h #include evsel.h #include evlist.h @@ -730,7 +731,8 @@ static bool sample_overlap(const union perf_event *event, int perf_event__parse_sample(const union perf_event *event, u64 type, int sample_size, bool sample_id_all
[PATCH 12/13] perf, tool: Support for dwarf cfi unwinding on post processing
This brings the support for dwarf cfi unwinding on perf post processing. Call frame informations are retrieved and then passed to libunwind that requests memory and register content from the applications. Adding unwind object to handle the user stack backtrace based on the user register values and user stack dump. The unwind object access the libunwind via remote interface and provides to it all the necessary data to unwind the stack. The unwind interface provides following function: unwind__get_entries And callback (specified in above function) to retrieve the backtrace entries: typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); Signed-off-by: Jiri Olsa jo...@redhat.com Original-patch-by: Frederic Weisbecker fweis...@gmail.com --- tools/perf/Makefile|2 + tools/perf/arch/x86/Makefile |3 + tools/perf/arch/x86/util/unwind.c | 111 tools/perf/builtin-report.c| 24 +- tools/perf/builtin-script.c| 16 +- tools/perf/builtin-top.c |5 +- tools/perf/util/include/linux/compiler.h |1 + tools/perf/util/map.h |7 +- .../perf/util/scripting-engines/trace-event-perl.c |3 +- .../util/scripting-engines/trace-event-python.c|3 +- tools/perf/util/session.c | 61 ++- tools/perf/util/session.h |3 +- tools/perf/util/trace-event-scripting.c|3 +- tools/perf/util/trace-event.h |5 +- tools/perf/util/unwind.c | 567 tools/perf/util/unwind.h | 34 ++ 16 files changed, 811 insertions(+), 37 deletions(-) create mode 100644 tools/perf/arch/x86/util/unwind.c create mode 100644 tools/perf/util/unwind.c create mode 100644 tools/perf/util/unwind.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index a1ee011..52e9e6c 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -328,6 +328,7 @@ LIB_H += util/cgroup.h LIB_H += $(TRACE_EVENT_DIR)event-parse.h LIB_H += util/target.h LIB_H += util/perf_regs.h +LIB_H += util/unwind.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o @@ -514,6 +515,7 @@ else EXTLIBS += $(LIBUNWIND_LIBS) BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS) BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS) + LIB_OBJS += $(OUTPUT)util/unwind.o endif ifdef NO_NEWT diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 744e629..815841c 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile @@ -2,4 +2,7 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o endif +ifndef NO_LIBUNWIND +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o +endif LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o diff --git a/tools/perf/arch/x86/util/unwind.c b/tools/perf/arch/x86/util/unwind.c new file mode 100644 index 000..78d956e --- /dev/null +++ b/tools/perf/arch/x86/util/unwind.c @@ -0,0 +1,111 @@ + +#include errno.h +#include libunwind.h +#include perf_regs.h +#include ../../util/unwind.h + +#ifdef ARCH_X86_64 +int unwind__arch_reg_id(int regnum) +{ + int id; + + switch (regnum) { + case UNW_X86_64_RAX: + id = PERF_REG_X86_AX; + break; + case UNW_X86_64_RDX: + id = PERF_REG_X86_DX; + break; + case UNW_X86_64_RCX: + id = PERF_REG_X86_CX; + break; + case UNW_X86_64_RBX: + id = PERF_REG_X86_BX; + break; + case UNW_X86_64_RSI: + id = PERF_REG_X86_SI; + break; + case UNW_X86_64_RDI: + id = PERF_REG_X86_DI; + break; + case UNW_X86_64_RBP: + id = PERF_REG_X86_BP; + break; + case UNW_X86_64_RSP: + id = PERF_REG_X86_SP; + break; + case UNW_X86_64_R8: + id = PERF_REG_X86_R8; + break; + case UNW_X86_64_R9: + id = PERF_REG_X86_R9; + break; + case UNW_X86_64_R10: + id = PERF_REG_X86_R10; + break; + case UNW_X86_64_R11: + id = PERF_REG_X86_R11; + break; + case UNW_X86_64_R12: + id = PERF_REG_X86_R12; + break; + case UNW_X86_64_R13: + id = PERF_REG_X86_R13; + break; + case UNW_X86_64_R14: + id = PERF_REG_X86_R14; + break; + case UNW_X86_64_R15: + id = PERF_REG_X86_R15; + break; + case UNW_X86_64_RIP: + id = PERF_REG_X86_IP
[PATCH 13/13] perf, tool: Support for dwarf mode callchain on perf record
This patch enables perf to use the dwarf unwind code. It extends the perf record '-g' option with following arguments: 'fp' - provides framepointer based user stack backtrace 'dwarf[,size]' - provides dwarf (libunwind) based user stack backtrace. The size specifies the size of the user stack dump. If omitted it is 8192 by default. If libunwind is found during the perf build, then the 'dwarf' argument becomes available for record command. The 'fp' stays as default option in any case. Examples: (perf compiled with libunwind) perf record -g dwarf ls - provides dwarf unwind with 8192 as stack dump size perf record -g dwarf,4096 ls - provides dwarf unwind with 4096 as stack dump size perf record -g -- ls perf record -g fp ls - provides frame pointer unwind Signed-off-by: Jiri Olsa jo...@redhat.com Original-patch-by: Frederic Weisbecker fweis...@gmail.com --- tools/perf/builtin-record.c | 108 ++- tools/perf/perf.h |9 +++- tools/perf/util/evsel.c | 13 +- 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f5a6452..fff130b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -31,6 +31,15 @@ #include sched.h #include sys/mman.h +#define CALLCHAIN_HELP do call-graph (stack chain/backtrace) recording: + +#ifdef NO_LIBUNWIND_SUPPORT +static char callchain_help[] = CALLCHAIN_HELP [fp]; +#else +static unsigned long default_stack_dump_size = 8192; +static char callchain_help[] = CALLCHAIN_HELP [fp] dwarf; +#endif + enum write_mode_t { WRITE_FORCE, WRITE_APPEND @@ -732,6 +741,100 @@ error: return ret; } +#ifndef NO_LIBUNWIND_SUPPORT +static int get_stack_size(char *str, unsigned long *_size) +{ + char *endptr; + unsigned long size; + unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); + + size = strtoul(str, endptr, 0); + + do { + if (*endptr) + break; + + size = round_up(size, sizeof(u64)); + if (!size || size max_size) + break; + + *_size = size; + return 0; + + } while (0); + + pr_err(callchain: Incorrect stack dump size (max %ld): %s\n, + max_size, str); + return -1; +} +#endif /* !NO_LIBUNWIND_SUPPORT */ + +static int +parse_callchain_opt(const struct option *opt __used, const char *arg, + int unset) +{ + struct perf_record *rec = (struct perf_record *)opt-value; + char *tok, *name, *saveptr = NULL; + char buf[20]; + int ret = -1; + + /* --no-call-graph */ + if (unset) + return 0; + + /* We specified default option if none is provided. */ + BUG_ON(!arg); + + /* We need buffer that we know we can write to. */ + snprintf(buf, 20, %s, arg); + + tok = strtok_r((char *)buf, ,, saveptr); + name = tok ? : (char *)buf; + + do { + /* Framepointer style */ + if (!strncmp(name, fp, sizeof(fp))) { + if (!strtok_r(NULL, ,, saveptr)) { + rec-opts.call_graph = CALLCHAIN_FP; + ret = 0; + } else + pr_err(callchain: No more arguments + needed for -g fp\n); + break; + +#ifndef NO_LIBUNWIND_SUPPORT + /* Dwarf style */ + } else if (!strncmp(name, dwarf, sizeof(dwarf))) { + ret = 0; + rec-opts.call_graph = CALLCHAIN_DWARF; + rec-opts.stack_dump_size = default_stack_dump_size; + + tok = strtok_r(NULL, ,, saveptr); + if (tok) { + unsigned long size = 0; + + ret = get_stack_size(tok, size); + rec-opts.stack_dump_size = size; + } + + if (!ret) + pr_debug(callchain: stack dump size %d\n, +rec-opts.stack_dump_size); +#endif /* !NO_LIBUNWIND_SUPPORT */ + } else { + pr_err(callchain: Unknown -g option + value: %s\n, name); + break; + } + + } while (0); + + if (!ret) + pr_debug(callchain: type %d\n, rec-opts.call_graph); + + return ret; +} + static const char * const record_usage[] = { perf record [options] [command], perf record [options] -- command [options], @@ -803,8 +906,9 @@ const struct option record_options[] = { number
[PATCH 09/13] perf, tool: Add interface to arch registers sets
Adding header files to access unified API for arch registers. util/perf_regs.h - global perf_reg declarations arch/x86/include/perf_regs.h - x86 arch specific Adding perf_reg_name function to obtain register name based on the reg ID value, and PERF_REGS_MASK macro with mask definition of all current arch registers (will be used in unwind patches). Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/Makefile | 13 +- tools/perf/arch/x86/include/perf_regs.h | 80 +++ tools/perf/util/perf_regs.h | 14 + 3 files changed, 106 insertions(+), 1 deletions(-) create mode 100644 tools/perf/arch/x86/include/perf_regs.h create mode 100644 tools/perf/util/perf_regs.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 77f124f..0548d93 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -50,13 +50,15 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ -e s/sh[234].*/sh/ ) +NO_PERF_REGS := 1 CC = $(CROSS_COMPILE)gcc AR = $(CROSS_COMPILE)ar # Additional ARCH settings for x86 ifeq ($(ARCH),i386) -ARCH := x86 + ARCH := x86 + NO_PERF_REGS := 0 endif ifeq ($(ARCH),x86_64) ARCH := x86 @@ -69,6 +71,7 @@ ifeq ($(ARCH),x86_64) ARCH_CFLAGS := -DARCH_X86_64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S endif + NO_PERF_REGS := 0 endif # Treat warnings as errors unless directed not to @@ -319,6 +322,7 @@ LIB_H += $(ARCH_INCLUDE) LIB_H += util/cgroup.h LIB_H += $(TRACE_EVENT_DIR)event-parse.h LIB_H += util/target.h +LIB_H += util/perf_regs.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o @@ -670,6 +674,13 @@ else endif endif +ifeq ($(NO_PERF_REGS),0) + ifeq ($(ARCH),x86) + LIB_H += arch/x86/include/perf_regs.h + endif +else + BASIC_CFLAGS += -DNO_PERF_REGS +endif ifdef NO_STRLCPY BASIC_CFLAGS += -DNO_STRLCPY diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h new file mode 100644 index 000..46fc9f1 --- /dev/null +++ b/tools/perf/arch/x86/include/perf_regs.h @@ -0,0 +1,80 @@ +#ifndef ARCH_PERF_REGS_H +#define ARCH_PERF_REGS_H + +#include stdlib.h +#include ../../util/types.h +#include ../../../../../arch/x86/include/asm/perf_regs.h + +#ifndef ARCH_X86_64 +#define PERF_REGS_MASK ((1ULL PERF_REG_X86_32_MAX) - 1) +#else +#define REG_NOSUPPORT ((1ULL PERF_REG_X86_DS) | \ + (1ULL PERF_REG_X86_ES) | \ + (1ULL PERF_REG_X86_FS) | \ + (1ULL PERF_REG_X86_GS)) +#define PERF_REGS_MASK (((1ULL PERF_REG_X86_64_MAX) - 1) ~REG_NOSUPPORT) +#endif +#define PERF_REG_IP PERF_REG_X86_IP +#define PERF_REG_SP PERF_REG_X86_SP + +static inline const char *perf_reg_name(int id) +{ + switch (id) { + case PERF_REG_X86_AX: + return AX; + case PERF_REG_X86_BX: + return BX; + case PERF_REG_X86_CX: + return CX; + case PERF_REG_X86_DX: + return DX; + case PERF_REG_X86_SI: + return SI; + case PERF_REG_X86_DI: + return DI; + case PERF_REG_X86_BP: + return BP; + case PERF_REG_X86_SP: + return SP; + case PERF_REG_X86_IP: + return IP; + case PERF_REG_X86_FLAGS: + return FLAGS; + case PERF_REG_X86_CS: + return CS; + case PERF_REG_X86_SS: + return SS; + case PERF_REG_X86_DS: + return DS; + case PERF_REG_X86_ES: + return ES; + case PERF_REG_X86_FS: + return FS; + case PERF_REG_X86_GS: + return GS; +#ifdef ARCH_X86_64 + case PERF_REG_X86_R8: + return R8; + case PERF_REG_X86_R9: + return R9; + case PERF_REG_X86_R10: + return R10; + case PERF_REG_X86_R11: + return R11; + case PERF_REG_X86_R12: + return R12; + case PERF_REG_X86_R13: + return R13; + case PERF_REG_X86_R14: + return R14; + case PERF_REG_X86_R15: + return R15; +#endif /* ARCH_X86_64 */ + default: + return NULL; + } + + return NULL; +} + +#endif /* ARCH_PERF_REGS_H */ diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h new file mode 100644 index 000..3efb79a --- /dev/null +++ b/tools/perf/util/perf_regs.h @@ -0,0 +1,14 @@ +#ifndef __PERF_REGS_H +#define __PERF_REGS_H + +#ifndef NO_PERF_REGS_DEFS +#include perf_regs.h +#else +#define PERF_REGS_MASK 0
[PATCH 08/13] perf, tool: Adding PERF_ATTR_SIZE_VER2 to the header swap check
Updating attr_file_abi_sizes array with PERF_ATTR_SIZE_VER2 version, so we have the swap check complete. Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/header.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 3a6d204..5d470a3 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1820,6 +1820,7 @@ out_free: static const int attr_file_abi_sizes[] = { [0] = PERF_ATTR_SIZE_VER0, [1] = PERF_ATTR_SIZE_VER1, + [2] = PERF_ATTR_SIZE_VER2, 0, }; -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 02/13] perf: Add ability to attach user level registers dump to sample
Introducing PERF_SAMPLE_REGS_USER sample type bit to trigger the dump of user level registers on sample. Registers we want to dump are specified by sample_regs_user bitmask. Only user level registers are dumped at the moment. Meaning the register values of the user space context as it was before the user entered the kernel for whatever reason (syscall, irq, exception, or a PMI happening in userspace). The layout of the sample_regs_user bitmap is described in asm/perf_regs.h for archs that support register dump. This is going to be useful to bring Dwarf CFI based stack unwinding on top of samples. Signed-off-by: Jiri Olsa jo...@redhat.com Original-patch-by: Frederic Weisbecker fweis...@gmail.com [ Dump registers ABI specification. ] Suggested-by: Stephane Eranian eran...@google.com --- arch/x86/kernel/perf_regs.c | 15 ++ include/linux/perf_event.h | 35 +-- include/linux/perf_regs.h |6 kernel/events/core.c| 66 +++ 4 files changed, 119 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index c00c92a..83cf975 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -1,5 +1,7 @@ #include linux/kernel.h +#include linux/sched.h +#include linux/perf_event.h #include linux/bug.h #include linux/stddef.h #include asm/perf_regs.h @@ -71,6 +73,11 @@ int perf_reg_validate(u64 mask) return 0; } + +u64 perf_reg_abi(struct task_struct *task) +{ + return PERF_SAMPLE_REGS_ABI_32; +} #else /* CONFIG_X86_64 */ #define REG_NOSUPPORT ((1ULL PERF_REG_X86_DS) | \ (1ULL PERF_REG_X86_ES) | \ @@ -87,4 +94,12 @@ int perf_reg_validate(u64 mask) return 0; } + +u64 perf_reg_abi(struct task_struct *task) +{ + if (test_tsk_thread_flag(task, TIF_IA32)) + return PERF_SAMPLE_REGS_ABI_32; + else + return PERF_SAMPLE_REGS_ABI_64; +} #endif /* CONFIG_X86_32 */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 7602ccb..3d4d847 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -130,8 +130,9 @@ enum perf_event_sample_format { PERF_SAMPLE_STREAM_ID = 1U 9, PERF_SAMPLE_RAW = 1U 10, PERF_SAMPLE_BRANCH_STACK= 1U 11, + PERF_SAMPLE_REGS_USER = 1U 12, - PERF_SAMPLE_MAX = 1U 12, /* non-ABI */ + PERF_SAMPLE_MAX = 1U 13, /* non-ABI */ }; /* @@ -163,6 +164,15 @@ enum perf_branch_sample_type { PERF_SAMPLE_BRANCH_HV) /* + * Values to determine ABI of the registers dump. + */ +enum perf_sample_regs_abi { + PERF_SAMPLE_REGS_ABI_NONE = 0, + PERF_SAMPLE_REGS_ABI_32 = 1, + PERF_SAMPLE_REGS_ABI_64 = 2, +}; + +/* * The format of the data returned by read() on a perf event fd, * as specified by attr.read_format: * @@ -194,6 +204,7 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER064 /* sizeof first published struct */ #define PERF_ATTR_SIZE_VER172 /* add: config2 */ #define PERF_ATTR_SIZE_VER280 /* add: branch_sample_type */ +#define PERF_ATTR_SIZE_VER388 /* add: sample_regs_user */ /* * Hardware event_id to monitor via a performance monitoring event: @@ -271,7 +282,13 @@ struct perf_event_attr { __u64 bp_len; __u64 config2; /* extension of config1 */ }; - __u64 branch_sample_type; /* enum branch_sample_type */ + __u64 branch_sample_type; /* enum perf_branch_sample_type */ + + /* +* Defines set of user regs to dump on samples. +* See asm/perf_regs.h for details. +*/ + __u64 sample_regs_user; }; /* @@ -548,6 +565,9 @@ enum perf_event_type { *char data[size];} PERF_SAMPLE_RAW * * { u64 from, to, flags } lbr[nr];} PERF_SAMPLE_BRANCH_STACK +* +* { u64 abi; # enum perf_sample_regs_abi +*u64 regs[weight(mask)]; } PERF_SAMPLE_REGS_USER * }; */ PERF_RECORD_SAMPLE = 9, @@ -609,6 +629,7 @@ struct perf_guest_info_callbacks { #include linux/static_key.h #include linux/atomic.h #include linux/sysfs.h +#include linux/perf_regs.h #include asm/local.h struct perf_callchain_entry { @@ -654,6 +675,11 @@ struct perf_branch_stack { struct perf_branch_entryentries[0]; }; +struct perf_regs_user { + __u64 abi; + struct pt_regs *regs; +}; + struct task_struct; /* @@ -1133,6 +1159,7 @@ struct perf_sample_data { struct perf_callchain_entry *callchain; struct perf_raw_record *raw; struct perf_branch_stack*br_stack
Re: perf: commit 44f24cb3156a1e (Factor DSO symtab types) causes segfaults
On Wed, Aug 01, 2012 at 01:57:40PM +0200, Markus Trippelsdorf wrote: On 2012.07.31 at 16:14 +0200, Ingo Molnar wrote: Jiri Olsa (4): perf symbols: Factor DSO symtab types to generic binary types The commit above causes perf segfaults on my machine (running glibc trunk): (gdb) run top --stdio Starting program: /usr/src/linux/tools/perf/perf top --stdio warning: no loadable sections found in added symbol-file system-supplied DSO at 0x77ffa000 [Thread debugging using libthread_db enabled] Using host libthread_db library /lib/libthread_db.so.1. Program received signal SIGSEGV, Segmentation fault. dso__load (dso=0x6661d0, map=map@entry=0x666170, filter=filter@entry=0x426840 symbol_filter) at util/symbol.c:1833 1833dso-symtab_type = binary_type_symtab[i]; (gdb) bt #0 dso__load (dso=0x6661d0, map=map@entry=0x666170, filter=filter@entry=0x426840 symbol_filter) at util/symbol.c:1833 #1 0x0045fe87 in map__load (self=self@entry=0x666170, filter=filter@entry=0x426840 symbol_filter) at util/map.c:124 #2 0x0045ffbd in map__find_symbol (self=0x666170, addr=11008, filter=filter@entry=0x426840 symbol_filter) at util/map.c:168 #3 0x0043b5df in perf_event__preprocess_sample (event=event@entry=0x744c8720, machine=machine@entry=0x647730, al=al@entry=0x7fffb030, sample=sample@entry=0x7fffb060, filter=filter@entry=0x426840 symbol_filter) at util/event.c:886 #4 0x00426d8e in perf_event__process_sample (machine=0x647730, sample=0x7fffb060, evsel=optimized out, event=0x744c8720, tool=0x7fffb2c0) at builtin-top.c:723 #5 perf_top__mmap_read_idx (top=top@entry=0x7fffb2c0, idx=idx@entry=3) at builtin-top.c:858 #6 0x004291c3 in perf_top__mmap_read (top=optimized out) at builtin-top.c:873 #7 __cmd_top (top=0x7fffb2c0) at builtin-top.c:1040 #8 cmd_top (argc=optimized out, argv=optimized out, prefix=optimized out) at builtin-top.c:1348 #9 0x00414d03 in run_builtin (p=p@entry=0x4dc888, argc=argc@entry=2, argv=argv@entry=0x7fffe0b0) at perf.c:273 #10 0x00415487 in handle_internal_command (argv=0x7fffe0b0, argc=2) at perf.c:345 #11 run_argv (argv=0x7fffdeb0, argcp=0x7fffdebc) at perf.c:389 #12 main (argc=2, argv=0x7fffe0b0) at perf.c:487 (gdb) hi, I cannot reproduce, but found one obvious bug, could you please test? thanks, jirka --- tools/perf/util/symbol.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fdad4eee..fe86612 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -64,7 +64,7 @@ static enum dso_binary_type binary_type_symtab[] = { DSO_BINARY_TYPE__NOT_FOUND, }; -#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab) +#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab) static enum dso_binary_type binary_type_data[] = { DSO_BINARY_TYPE__BUILD_ID_CACHE, @@ -72,7 +72,7 @@ static enum dso_binary_type binary_type_data[] = { DSO_BINARY_TYPE__NOT_FOUND, }; -#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data) +#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data) int dso__name_len(const struct dso *dso) { -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: perf: commit 44f24cb3156a1e (Factor DSO symtab types) causes segfaults
On Wed, Aug 01, 2012 at 02:25:22PM +0200, Markus Trippelsdorf wrote: On 2012.08.01 at 14:21 +0200, Jiri Olsa wrote: On Wed, Aug 01, 2012 at 01:57:40PM +0200, Markus Trippelsdorf wrote: On 2012.07.31 at 16:14 +0200, Ingo Molnar wrote: Jiri Olsa (4): perf symbols: Factor DSO symtab types to generic binary types The commit above causes perf segfaults on my machine (running glibc trunk): (gdb) run top --stdio Starting program: /usr/src/linux/tools/perf/perf top --stdio warning: no loadable sections found in added symbol-file system-supplied DSO at 0x77ffa000 [Thread debugging using libthread_db enabled] Using host libthread_db library /lib/libthread_db.so.1. Program received signal SIGSEGV, Segmentation fault. dso__load (dso=0x6661d0, map=map@entry=0x666170, filter=filter@entry=0x426840 symbol_filter) at util/symbol.c:1833 1833dso-symtab_type = binary_type_symtab[i]; (gdb) bt #0 dso__load (dso=0x6661d0, map=map@entry=0x666170, filter=filter@entry=0x426840 symbol_filter) at util/symbol.c:1833 #1 0x0045fe87 in map__load (self=self@entry=0x666170, filter=filter@entry=0x426840 symbol_filter) at util/map.c:124 #2 0x0045ffbd in map__find_symbol (self=0x666170, addr=11008, filter=filter@entry=0x426840 symbol_filter) at util/map.c:168 #3 0x0043b5df in perf_event__preprocess_sample (event=event@entry=0x744c8720, machine=machine@entry=0x647730, al=al@entry=0x7fffb030, sample=sample@entry=0x7fffb060, filter=filter@entry=0x426840 symbol_filter) at util/event.c:886 #4 0x00426d8e in perf_event__process_sample (machine=0x647730, sample=0x7fffb060, evsel=optimized out, event=0x744c8720, tool=0x7fffb2c0) at builtin-top.c:723 #5 perf_top__mmap_read_idx (top=top@entry=0x7fffb2c0, idx=idx@entry=3) at builtin-top.c:858 #6 0x004291c3 in perf_top__mmap_read (top=optimized out) at builtin-top.c:873 #7 __cmd_top (top=0x7fffb2c0) at builtin-top.c:1040 #8 cmd_top (argc=optimized out, argv=optimized out, prefix=optimized out) at builtin-top.c:1348 #9 0x00414d03 in run_builtin (p=p@entry=0x4dc888, argc=argc@entry=2, argv=argv@entry=0x7fffe0b0) at perf.c:273 #10 0x00415487 in handle_internal_command (argv=0x7fffe0b0, argc=2) at perf.c:345 #11 run_argv (argv=0x7fffdeb0, argcp=0x7fffdebc) at perf.c:389 #12 main (argc=2, argv=0x7fffe0b0) at perf.c:487 (gdb) I cannot reproduce, but found one obvious bug, could you please test? Your patch fixes the issue. Thank you. thanks, I'll send official patch ASAP jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf, tool: Fix array sizes for binary types arrays
Following commit introduced wrong array boundaries, that could lead to SIGSEGV. perf symbols: Factor DSO symtab types to generic binary types commit 44f24cb3156a1e7d2b6bb501b7f6153aed08994c Author: Jiri Olsa jo...@redhat.com Fixing to use proper array size. Reported-by: Markus Trippelsdorf mar...@trippelsdorf.de Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/symbol.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fdad4eee..fe86612 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -64,7 +64,7 @@ static enum dso_binary_type binary_type_symtab[] = { DSO_BINARY_TYPE__NOT_FOUND, }; -#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab) +#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab) static enum dso_binary_type binary_type_data[] = { DSO_BINARY_TYPE__BUILD_ID_CACHE, @@ -72,7 +72,7 @@ static enum dso_binary_type binary_type_data[] = { DSO_BINARY_TYPE__NOT_FOUND, }; -#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data) +#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data) int dso__name_len(const struct dso *dso) { -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf, test: Fix parse events automated tests
Parse events tests got broken after following commit: perf tools: Fix trace events storms due to weight demux commit 0983cc0dbca45250cbb5984bec7c303ac265b8e5 Author: Frederic Weisbecker fweis...@gmail.com that added PERF_SAMPLE_PERIOD sample type for tracepoints. Updating related tests. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Frederic Weisbecker fweis...@gmail.com --- tools/perf/util/parse-events-test.c | 12 ++-- 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index 1b997d2..127d648 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -13,6 +13,9 @@ do { \ } \ } while (0) +#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ +PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) + static int test__checkevent_tracepoint(struct perf_evlist *evlist) { struct perf_evsel *evsel = list_entry(evlist-entries.next, @@ -21,8 +24,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist) TEST_ASSERT_VAL(wrong number of entries, 1 == evlist-nr_entries); TEST_ASSERT_VAL(wrong type, PERF_TYPE_TRACEPOINT == evsel-attr.type); TEST_ASSERT_VAL(wrong sample_type, - (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == - evsel-attr.sample_type); + PERF_TP_SAMPLE_TYPE == evsel-attr.sample_type); TEST_ASSERT_VAL(wrong sample_period, 1 == evsel-attr.sample_period); return 0; } @@ -37,8 +39,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) TEST_ASSERT_VAL(wrong type, PERF_TYPE_TRACEPOINT == evsel-attr.type); TEST_ASSERT_VAL(wrong sample_type, - (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) - == evsel-attr.sample_type); + PERF_TP_SAMPLE_TYPE == evsel-attr.sample_type); TEST_ASSERT_VAL(wrong sample_period, 1 == evsel-attr.sample_period); } @@ -428,8 +429,7 @@ static int test__checkevent_list(struct perf_evlist *evlist) evsel = list_entry(evsel-node.next, struct perf_evsel, node); TEST_ASSERT_VAL(wrong type, PERF_TYPE_TRACEPOINT == evsel-attr.type); TEST_ASSERT_VAL(wrong sample_type, - (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == - evsel-attr.sample_type); + PERF_TP_SAMPLE_TYPE == evsel-attr.sample_type); TEST_ASSERT_VAL(wrong sample_period, 1 == evsel-attr.sample_period); TEST_ASSERT_VAL(wrong exclude_user, evsel-attr.exclude_user); TEST_ASSERT_VAL(wrong exclude_kernel, !evsel-attr.exclude_kernel); -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 13/13] perf, tool: Support for dwarf mode callchain on perf record
On Wed, Aug 01, 2012 at 08:26:11AM -0600, David Ahern wrote: On 8/1/12 4:11 AM, Jiri Olsa wrote: +static int +parse_callchain_opt(const struct option *opt __used, const char *arg, +int unset) +{ +struct perf_record *rec = (struct perf_record *)opt-value; +char *tok, *name, *saveptr = NULL; +char buf[20]; +int ret = -1; + +/* --no-call-graph */ +if (unset) +return 0; + +/* We specified default option if none is provided. */ +BUG_ON(!arg); + +/* We need buffer that we know we can write to. */ +snprintf(buf, 20, %s, arg); Isn't arg the user supplied string? What if the user messes up and passes in 20+ characters to -g argument? [jolsa@dhcp-26-214 perf]$ ./perf record -g dwarf123213214321432143214321432143214321432143214321 ls callchain: Unknown -g option value: dwarf12321321432143 ... hm, but if user specified it like this: [jolsa@dhcp-26-214 perf]$ ./perf record -vg 'dwarf,5' ls callchain: Incorrect stack dump size (max 65528): then we're in trouble.. I'll send a fix thanks, jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 07/13] perf: Add attribute to filter out callchains
On Thu, Aug 02, 2012 at 11:38:26AM +0400, Andrew Vagin wrote: On Wed, Aug 01, 2012 at 02:10:59PM +0400, Jiri Olsa wrote: From: Frederic Weisbecker fweis...@gmail.com 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: Frederic Weisbecker fweis...@gmail.com [ Added kernel callchains filtering ] Signed-off-by: Jiri Olsa jo...@redhat.com CC: Andrew Vagin ava...@openvz.org Acked-by: Andrew Vagin ava...@openvz.org diff --git a/kernel/events/core.c b/kernel/events/core.c index c4582bb..0902d4a 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4130,8 +4130,12 @@ void perf_prepare_sample(struct perf_event_header *header, if (sample_type PERF_SAMPLE_CALLCHAIN) { int size = 1; + int kernel = !event-attr.exclude_callchain_kernel; + int user = !event-attr.exclude_callchain_user; - data-callchain = perf_callchain(event, regs); + if (kernel || user) + data-callchain = perf_callchain(event, regs, +kernel, user); I am not sure, that we need two arguments kernel and user here, we can get them from event inside perf_callchain... right.. I'll send an update with other fixies thanks jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/17] perf, x86: Add copy_from_user_nmi_nochk for best effort copy
On Thu, Aug 02, 2012 at 11:47:30AM -0700, Andy Lutomirski wrote: On 07/22/2012 05:14 AM, Jiri Olsa wrote: Adding copy_from_user_nmi_nochk that provides the best effort copy regardless the requesting size crossing the task boundary. This is going to be useful for stack dump we need in post DWARF CFI based unwind, where we have predefined size of the user stack to dump, and we need to store the most of the requested dump size, regardless this size is crossing the task boundary. Huh? This is a TASK_SIZE check, which makes sure that the request doesn't cross into kernel land. Otherwise userspace could presumably read kernel memory by setting bogus values of sp. haven't realized that.. new version won't have this thanks, jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/6] perf, x86: Making hardware events translations available in sysfs
On Mon, Aug 20, 2012 at 10:25:42AM +0200, Stephane Eranian wrote: On Mon, Jul 9, 2012 at 10:37 PM, Jiri Olsa jo...@redhat.com wrote: SNIP +static ssize_t event_sysfs_data(char *page, u64 config) +{ + u64 event = (config ARCH_PERFMON_EVENTSEL_EVENT) | +(config AMD64_EVENTSEL_EVENT) 24; + u64 umask = (config ARCH_PERFMON_EVENTSEL_UMASK) 8; + u64 inv= (config ARCH_PERFMON_EVENTSEL_INV) 23; + u64 cmask = (config ARCH_PERFMON_EVENTSEL_CMASK) 24; + ssize_t ret; + + /* +* We have whole page size to spend and just little data +* to write, so we can safely use sprintf. +*/ + ret = sprintf(page, event=0x%02llx, event); + + if (umask) + ret += sprintf(page + ret, ,umask=0x%02llx, umask); + + if (inv) + ret += sprintf(page + ret, ,inv); + + if (cmask) + ret += sprintf(page + ret, ,cmask=0x%02llx, cmask); + You are not handling the model specific modifiers such as any_thread on Intel. It's not used right now. But you should handle the case now. That will avoid problems in the future. ok, will add those + ret += sprintf(page + ret, \n); + + return ret; +} SNIP static const struct attribute_group *x86_pmu_attr_groups[] = { x86_pmu_attr_group, x86_pmu_format_group, + x86_pmu_events_group, NULL, }; You are not checking whether or not the generic event is even available on the host core PMU. You don't want to expose generic events which are not available. thats what patch 2 does And if you do this, then you need to take care of the other arch as well. They also deserve the extended syntax. hm, I could try to add something for ppc, but that's where my arch hw availability ends thanks, jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 5/8] perf tools: Catch event names from command line
On Thu, Aug 16, 2012 at 09:10:21PM +0200, Robert Richter wrote: Use command line string provided by the -e option to name events. This way we get unique events names that also support pmu event syntax (pmu_name/config/modifier). No need to reconstruct the name anymore from its attributes. We use the event_desc of the header to store the name in the perf.data header. Thus it is also available for perf report. Implemented by putting the parser in different states to parse events or configs. I like the idea of multiple states in parser, but parse tests fails: [jolsa@krava perf]$ ./perf test -vvv parse 5: parse events tests: --- start --- running test 0 'syscalls:sys_enter_open' running test 1 'syscalls:*' running test 2 'r1a' running test 3 '1:1' running test 4 'instructions' running test 5 'cycles/period=10,config2/' running test 6 'faults' running test 7 'L1-dcache-load-miss' running test 8 'mem:0' running test 9 'mem:0:x' running test 10 'mem:0:r' running test 11 'mem:0:w' running test 12 'syscalls:sys_enter_open:k' running test 13 'syscalls:*:u' running test 14 'r1a:kp' running test 15 '1:1:hp' running test 16 'instructions:h' running test 17 'faults:u' running test 18 'L1-dcache-load-miss:kp' running test 19 'mem:0:u' FAILED util/parse-events-test.c:309 wrong name end parse events tests: FAILED! jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [GIT PULL 00/24] perf/core improvements and fixes
On Tue, Aug 21, 2012 at 11:32:31AM +0200, Ingo Molnar wrote: * Arnaldo Carvalho de Melo a...@infradead.org wrote: SNIP One minor observation, the Makefile tells us: Makefile:496: No libunwind found. Please install libunwind = 0.99 I guess that should be libunwind-dev[el], right? Plain libunwind is not enough. right, will fix it thanks, jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] misc: ifdef KMOD, saving some bytes probably
found some code in misc.c that could be ifdef'ed for KMOD Signed-off-by: Jiri Olsa [EMAIL PROTECTED] --- drivers/char/misc.c |7 ++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/drivers/char/misc.c b/drivers/char/misc.c index a39101f..3455b09 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -126,7 +126,8 @@ static int misc_open(struct inode * inode, struct file * file) break; } } - + +#if defined(CONFIG_KMOD) if (!new_fops) { mutex_unlock(misc_mtx); request_module(char-major-%d-%d, MISC_MAJOR, minor); @@ -141,6 +142,10 @@ static int misc_open(struct inode * inode, struct file * file) if (!new_fops) goto fail; } +#else + if (!new_fops) + goto fail; +#endif err = 0; old_fops = file-f_op; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] fs: removing unused fops from struct char_device_struct
Hi, seems struct char_device_struct::fops is no longer used, removing it. I checked with make allyesconfig and got proper compile. Signed-off-by: Jiri Olsa [EMAIL PROTECTED] --- fs/char_dev.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/fs/char_dev.c b/fs/char_dev.c index c3bfa76..e4527fb 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -55,7 +55,6 @@ static struct char_device_struct { unsigned int baseminor; int minorct; char name[64]; - struct file_operations *fops; struct cdev *cdev; /* will die */ } *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] fs: removing unused fops from struct char_device_struct
oops, sorry... for some reason I though you were the guy :) I'll resend jirka Greg KH wrote: On Wed, Feb 20, 2008 at 09:57:23PM +0100, Jiri Olsa wrote: Hi, seems struct char_device_struct::fops is no longer used, removing it. I checked with make allyesconfig and got proper compile. Signed-off-by: Jiri Olsa [EMAIL PROTECTED] Hm, why send this to me? Did I make the mistake of touching this file last? Hm, nope, someone else touched it after I did, I'm safe :) Seriously, I have no problem with this, but it should probably go through Andrew. thanks, greg k-h -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] kernel: Removing duplicit #includes
Removing duplicit #includes for kernel/ Signed-off-by: Jiri Olsa [EMAIL PROTECTED] --- kernel/printk.c |1 - kernel/profile.c |2 -- kernel/sysctl.c |1 - 3 files changed, 0 insertions(+), 4 deletions(-) diff --git a/kernel/printk.c b/kernel/printk.c index a30fe33..3f06748 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -32,7 +32,6 @@ #include linux/security.h #include linux/bootmem.h #include linux/syscalls.h -#include linux/jiffies.h #include asm/uaccess.h diff --git a/kernel/profile.c b/kernel/profile.c index 5e95330..92b71ea 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -20,7 +20,6 @@ #include linux/mm.h #include linux/cpumask.h #include linux/cpu.h -#include linux/profile.h #include linux/highmem.h #include linux/mutex.h #include asm/sections.h @@ -425,7 +424,6 @@ void profile_tick(int type) #ifdef CONFIG_PROC_FS #include linux/proc_fs.h #include asm/uaccess.h -#include asm/ptrace.h static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3b4efbe..5aec15e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -37,7 +37,6 @@ #include linux/highuid.h #include linux/writeback.h #include linux/hugetlb.h -#include linux/security.h #include linux/initrd.h #include linux/times.h #include linux/limits.h - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] kernel: Removing duplicit #includes
Removing duplicit #includes for kernel/ Signed-off-by: Jiri Olsa [EMAIL PROTECTED] --- kernel/printk.c |1 - kernel/profile.c |2 -- kernel/sysctl.c |1 - 3 files changed, 0 insertions(+), 4 deletions(-) diff --git a/kernel/printk.c b/kernel/printk.c index a30fe33..3f06748 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -32,7 +32,6 @@ #include linux/security.h #include linux/bootmem.h #include linux/syscalls.h -#include linux/jiffies.h #include asm/uaccess.h diff --git a/kernel/profile.c b/kernel/profile.c index 5e95330..92b71ea 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -20,7 +20,6 @@ #include linux/mm.h #include linux/cpumask.h #include linux/cpu.h -#include linux/profile.h #include linux/highmem.h #include linux/mutex.h #include asm/sections.h @@ -425,7 +424,6 @@ void profile_tick(int type) #ifdef CONFIG_PROC_FS #include linux/proc_fs.h #include asm/uaccess.h -#include asm/ptrace.h static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3b4efbe..5aec15e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -37,7 +37,6 @@ #include linux/highuid.h #include linux/writeback.h #include linux/hugetlb.h -#include linux/security.h #include linux/initrd.h #include linux/times.h #include linux/limits.h - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] kernel: Removing duplicit #includes
sorry, the patch is mangled, I will resend another Jiri Olsa wrote: Removing duplicit #includes for kernel/ Signed-off-by: Jiri Olsa [EMAIL PROTECTED] --- kernel/printk.c |1 - kernel/profile.c |2 -- kernel/sysctl.c |1 - 3 files changed, 0 insertions(+), 4 deletions(-) diff --git a/kernel/printk.c b/kernel/printk.c index a30fe33..3f06748 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -32,7 +32,6 @@ #include linux/security.h #include linux/bootmem.h #include linux/syscalls.h -#include linux/jiffies.h #include asm/uaccess.h diff --git a/kernel/profile.c b/kernel/profile.c index 5e95330..92b71ea 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -20,7 +20,6 @@ #include linux/mm.h #include linux/cpumask.h #include linux/cpu.h -#include linux/profile.h #include linux/highmem.h #include linux/mutex.h #include asm/sections.h @@ -425,7 +424,6 @@ void profile_tick(int type) #ifdef CONFIG_PROC_FS #include linux/proc_fs.h #include asm/uaccess.h -#include asm/ptrace.h static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3b4efbe..5aec15e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -37,7 +37,6 @@ #include linux/highuid.h #include linux/writeback.h #include linux/hugetlb.h -#include linux/security.h #include linux/initrd.h #include linux/times.h #include linux/limits.h - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv3 0/3] perf tool: Add new event group management
On Fri, Jul 06, 2012 at 03:42:54AM +0200, Stephane Eranian wrote: On Fri, Jul 6, 2012 at 3:32 AM, Ulrich Drepper drep...@gmail.com wrote: On Thu, Jul 5, 2012 at 12:15 PM, Stephane Eranian eran...@google.com wrote: I don't understand why you actually need the :2 suffix. There can only be one leader. So assume it is the first one. Users have to know the first one is the leader which seems like a natural thing to do for me. It would make you syntax less ugly than it already is. In a blue sky world I would have done this. In fact, this is what I tried before reading the sources to find out there is no group support so far. But given that multiple -e options already have a meaning I would be hesitant to change this. That's why I said you activate grouping via -e only when you have the --group-events or --group-reads option in front. That would not change the meaning of the multiple -e when none of those group options are specified. I discussed this with peter.. peterz the {} thing allows: 1) multiple groups in a single -e, 2) group attributes as for the leader sampling, we can have the first event to become the leader by default (omit the leader index modifier) and enable the leader sampling by another modifier: peterz right, just make it a single 'l' (el not one) to indicate 'leader' sampling jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv3 0/6] perf, tool: Allow to use hw events in PMU syntax
hi, here's the change to make following syntax available: perf stat -e cpu/event=instructions/u ls this is identical to: perf stat -e instructions:u ls v3 changes: - patches v2 1,5,6,9 are already in - patch 1 - sysfs 'events' attribute file names with dashes '-' - using 'event/umask/inv/cmask' terms assigments instead simple 'config' - patch 2 - undefined events sysfs attributes filtered out v2 changes: - making the hw events translations available under the 'events', the userspace trnaslation is then done by existing term aliasing code with some little tweeks ;) - patches 1-3 are independent fixies Attached patches: 1/6 perf, x86: Making hardware events translations available in sysfs 2/6 perf, x86: Filter out undefined events from sysfs events attribute 3/6 perf, tool: Fix pmu object alias initialization 4/6 perf, tool: Properly free format data 5/6 perf, tool: Add support to specify hw event as pmu event term 6/6 perf, test: Add automated tests for pmu sysfs translated events jirka --- arch/x86/kernel/cpu/perf_event.c| 98 + tools/perf/util/parse-events-test.c | 75 +++-- tools/perf/util/parse-events.c | 13 + tools/perf/util/parse-events.h |2 ++ tools/perf/util/parse-events.y |9 ++ tools/perf/util/pmu.c | 59 --- 6 files changed, 232 insertions(+), 24 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/6] perf, x86: Making hardware events translations available in sysfs
Making hardware events translations available through the sysfs. Adding 'events' group attribute under the sysfs x86 PMU record with attribute/file for each hardware event: # ls /sys/devices/cpu/events/ branch-instructions branch-misses bus-cycles cache-misses cache-references cpu-cycles instructions ref-cycles stalled-cycles-backend stalled-cycles-frontend The file - hw event ID mappings is: file hw event ID --- cpu-cyclesPERF_COUNT_HW_CPU_CYCLES instructions PERF_COUNT_HW_INSTRUCTIONS cache-references PERF_COUNT_HW_CACHE_REFERENCES cache-misses PERF_COUNT_HW_CACHE_MISSES branch-instructions PERF_COUNT_HW_BRANCH_INSTRUCTIONS branch-misses PERF_COUNT_HW_BRANCH_MISSES bus-cyclesPERF_COUNT_HW_BUS_CYCLES stalled-cycles-frontend PERF_COUNT_HW_STALLED_CYCLES_FRONTEND stalled-cycles-backendPERF_COUNT_HW_STALLED_CYCLES_BACKEND ref-cyclesPERF_COUNT_HW_REF_CPU_CYCLES Each file in 'events' directory contains term translation for the symbolic hw event for the currently running cpu model. # cat /sys/devices/cpu/events/stalled-cycles-backend event=0xb1,umask=0x01,inv,cmask=0x01 Suggested-by: Peter Zijlstra a.p.zijls...@chello.nl Signed-off-by: Jiri Olsa jo...@redhat.com --- arch/x86/kernel/cpu/perf_event.c | 74 ++ 1 file changed, 74 insertions(+) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 29557aa..09452c2 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1638,9 +1638,83 @@ static struct attribute_group x86_pmu_attr_group = { .attrs = x86_pmu_attrs, }; +static ssize_t event_sysfs_data(char *page, u64 config) +{ + u64 event = (config ARCH_PERFMON_EVENTSEL_EVENT) | +(config AMD64_EVENTSEL_EVENT) 24; + u64 umask = (config ARCH_PERFMON_EVENTSEL_UMASK) 8; + u64 inv= (config ARCH_PERFMON_EVENTSEL_INV) 23; + u64 cmask = (config ARCH_PERFMON_EVENTSEL_CMASK) 24; + ssize_t ret; + + /* +* We have whole page size to spend and just little data +* to write, so we can safely use sprintf. +*/ + ret = sprintf(page, event=0x%02llx, event); + + if (umask) + ret += sprintf(page + ret, ,umask=0x%02llx, umask); + + if (inv) + ret += sprintf(page + ret, ,inv); + + if (cmask) + ret += sprintf(page + ret, ,cmask=0x%02llx, cmask); + + ret += sprintf(page + ret, \n); + + return ret; +} + +#define PMU_EVENTS_ATTR(_name, _id)\ +static ssize_t \ +_id##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *page) \ +{ \ + u64 config = x86_pmu.event_map(_id);\ + BUILD_BUG_ON(_id = PERF_COUNT_HW_MAX); \ + return event_sysfs_data(page, config); \ +} \ + \ +static struct device_attribute event_attr_##_id = \ + __ATTR(_name, 0444, _id##_show, NULL) + +PMU_EVENTS_ATTR(cpu-cycles, PERF_COUNT_HW_CPU_CYCLES); +PMU_EVENTS_ATTR(instructions, PERF_COUNT_HW_INSTRUCTIONS); +PMU_EVENTS_ATTR(cache-references, PERF_COUNT_HW_CACHE_REFERENCES); +PMU_EVENTS_ATTR(cache-misses, PERF_COUNT_HW_CACHE_MISSES); +PMU_EVENTS_ATTR(branch-instructions, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); +PMU_EVENTS_ATTR(branch-misses, PERF_COUNT_HW_BRANCH_MISSES); +PMU_EVENTS_ATTR(bus-cycles, PERF_COUNT_HW_BUS_CYCLES); +PMU_EVENTS_ATTR(stalled-cycles-frontend, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); +PMU_EVENTS_ATTR(stalled-cycles-backend, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); +PMU_EVENTS_ATTR(ref-cycles, PERF_COUNT_HW_REF_CPU_CYCLES); + +static struct attribute *events_attr[] = { + event_attr_PERF_COUNT_HW_CPU_CYCLES.attr, + event_attr_PERF_COUNT_HW_INSTRUCTIONS.attr, + event_attr_PERF_COUNT_HW_CACHE_REFERENCES.attr, + event_attr_PERF_COUNT_HW_CACHE_MISSES.attr, + event_attr_PERF_COUNT_HW_BRANCH_INSTRUCTIONS.attr, + event_attr_PERF_COUNT_HW_BRANCH_MISSES.attr, + event_attr_PERF_COUNT_HW_BUS_CYCLES.attr, + event_attr_PERF_COUNT_HW_STALLED_CYCLES_FRONTEND.attr, + event_attr_PERF_COUNT_HW_STALLED_CYCLES_BACKEND.attr, + event_attr_PERF_COUNT_HW_REF_CPU_CYCLES.attr, + NULL, +}; + +static struct attribute_group x86_pmu_events_group = { + .name = events, + .attrs = events_attr, +}; + static const struct attribute_group *x86_pmu_attr_groups[] = { x86_pmu_attr_group, x86_pmu_format_group
[PATCH 3/6] perf, tool: Fix pmu object alias initialization
The pmu_lookup should return pmus that do not expose the 'events' group attribute in sysfs. Also it should fail when any other error during 'events' lookup is hit (pmu_aliases fails). Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/pmu.c |7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 67715a4..3c86022 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -161,7 +161,7 @@ static int pmu_aliases(char *name, struct list_head *head) %s/bus/event_source/devices/%s/events, sysfs, name); if (stat(path, st) 0) - return -1; + return 0;/* no error if 'events' does not exist */ if (pmu_aliases_parse(path, head)) return -1; @@ -237,6 +237,9 @@ static struct perf_pmu *pmu_lookup(char *name) if (pmu_format(name, format)) return NULL; + if (pmu_aliases(name, aliases)) + return NULL; + if (pmu_type(name, type)) return NULL; @@ -244,8 +247,6 @@ static struct perf_pmu *pmu_lookup(char *name) if (!pmu) return NULL; - pmu_aliases(name, aliases); - INIT_LIST_HEAD(pmu-format); INIT_LIST_HEAD(pmu-aliases); list_splice(format, pmu-format); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 6/6] perf, test: Add automated tests for pmu sysfs translated events
Adding automated tests for all events found under PMU/events directory. Tested events are in 'cpu/event=xxx/u' format, where 'xxx' is substibuted by every event found. The 'event=xxx' term is translated to the cpu specific term. We only check that the event is created (not the real config numbers) and that modifier is properly set. Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/parse-events-test.c | 75 ++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index 1b997d2..a2aac11 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -13,6 +13,8 @@ do { \ } \ } while (0) +static int test_cnt; + static int test__checkevent_tracepoint(struct perf_evlist *evlist) { struct perf_evsel *evsel = list_entry(evlist-entries.next, @@ -470,6 +472,23 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist) return 0; } +static int test__checkevent_pmu_events(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + evsel = list_entry(evlist-entries.next, struct perf_evsel, node); + TEST_ASSERT_VAL(wrong number of entries, 1 == evlist-nr_entries); + TEST_ASSERT_VAL(wrong type, PERF_TYPE_RAW == evsel-attr.type); + TEST_ASSERT_VAL(wrong exclude_user, + !evsel-attr.exclude_user); + TEST_ASSERT_VAL(wrong exclude_kernel, + evsel-attr.exclude_kernel); + TEST_ASSERT_VAL(wrong exclude_hv, evsel-attr.exclude_hv); + TEST_ASSERT_VAL(wrong precise_ip, !evsel-attr.precise_ip); + + return 0; +} + static int test__checkterms_simple(struct list_head *terms) { struct parse_events__term *term; @@ -666,6 +685,8 @@ static int test_event(struct test__event_st *e) struct perf_evlist *evlist; int ret; + pr_debug(running test %4d '%s'\n, test_cnt++, e-name); + evlist = perf_evlist__new(NULL, NULL); if (evlist == NULL) return -ENOMEM; @@ -691,7 +712,6 @@ static int test_events(struct test__event_st *events, unsigned cnt) for (i = 0; i cnt; i++) { struct test__event_st *e = events[i]; - pr_debug(running test %d '%s'\n, i, e-name); ret = test_event(e); if (ret) break; @@ -732,7 +752,7 @@ static int test_terms(struct test__term *terms, unsigned cnt) for (i = 0; i cnt; i++) { struct test__term *t = terms[i]; - pr_debug(running test %d '%s'\n, i, t-str); + pr_debug(running test %4d '%s'\n, test_cnt, t-str); ret = test_term(t); if (ret) break; @@ -756,6 +776,51 @@ static int test_pmu(void) return !ret; } +static int test_pmu_events(void) +{ + struct stat st; + char path[PATH_MAX]; + struct dirent *ent; + DIR *dir; + int ret; + + snprintf(path, PATH_MAX, %s/bus/event_source/devices/cpu/events/, +sysfs_find_mountpoint()); + + ret = stat(path, st); + if (ret) { + pr_debug(ommiting PMU cpu events tests\n); + return 0; + } + + dir = opendir(path); + if (!dir) { + pr_debug(can't open pmu event dir); + return -1; + } + + while (!ret (ent = readdir(dir))) { +#define MAX_NAME 100 + struct test__event_st e; + char name[MAX_NAME]; + + if (!strcmp(ent-d_name, .) || + !strcmp(ent-d_name, ..)) + continue; + + snprintf(name, MAX_NAME, cpu/event=%s/u, ent-d_name); + + e.name = name; + e.check = test__checkevent_pmu_events; + + ret = test_event(e); +#undef MAX_NAME + } + + closedir(dir); + return ret; +} + int parse_events__test(void) { int ret; @@ -772,5 +837,11 @@ do { \ if (test_pmu()) TEST_EVENTS(test__events_pmu); + if (test_pmu()) { + ret = test_pmu_events(); + if (ret) + return ret; + } + return test_terms(test__terms, ARRAY_SIZE(test__terms)); } -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 5/6] perf, tool: Add support to specify hw event as pmu event term
Adding a way to specify hw event as pmu event term like: 'cpu/event=cpu-cycles/u' 'cpu/event=instructions,.../u' The 'event=cpu-cycles' term is replaced/translated by the hw events term translation, which is exposed by sysfs 'events' group attribute. Adding parser bits, the rest is already handled by the pmu alias code. Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/parse-events.c | 13 + tools/perf/util/parse-events.h |2 ++ tools/perf/util/parse-events.y |9 + 3 files changed, 24 insertions(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 1aa721d..780bc45 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1045,6 +1045,19 @@ int parse_events__term_str(struct parse_events__term **term, config, str, 0); } +int parse_events__term_sym_hw(struct parse_events__term **term, + char *config, unsigned idx) +{ + struct event_symbol *sym; + + BUG_ON(idx = PERF_COUNT_HW_MAX); + sym = event_symbols_hw[idx]; + + return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, + PARSE_EVENTS__TERM_TYPE_USER, config, + (char *) sym-symbol, 0); +} + int parse_events__term_clone(struct parse_events__term **new, struct parse_events__term *term) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index ee9c218..eaf2fd7 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -76,6 +76,8 @@ int parse_events__term_num(struct parse_events__term **_term, int type_term, char *config, long num); int parse_events__term_str(struct parse_events__term **_term, int type_term, char *config, char *str); +int parse_events__term_sym_hw(struct parse_events__term **term, + char *config, unsigned idx); int parse_events__term_clone(struct parse_events__term **new, struct parse_events__term *term); void parse_events__free_terms(struct list_head *terms); diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 2bc5fbf..9c74d8a 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -269,6 +269,15 @@ PE_NAME '=' PE_VALUE $$ = term; } | +PE_NAME '=' PE_VALUE_SYM_HW +{ + struct parse_events__term *term; + int config = $3 255; + + ABORT_ON(parse_events__term_sym_hw(term, $1, config)); + $$ = term; +} +| PE_NAME { struct parse_events__term *term; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/6] perf, x86: Filter out undefined events from sysfs events attribute
The sysfs events group attribute currently shows all hw events, including also undefined ones. This patch filters out all undefined events out of the sysfs events group attribute, so they don't even show up. Suggested-by: Peter Zijlstra a.p.zijls...@chello.nl Signed-off-by: Jiri Olsa jo...@redhat.com --- arch/x86/kernel/cpu/perf_event.c | 24 1 file changed, 24 insertions(+) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 09452c2..9fb23dd 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1306,6 +1306,8 @@ static struct attribute_group x86_pmu_format_group = { .attrs = NULL, }; +static void __init filter_events_group(void); + static int __init init_hw_perf_events(void) { struct x86_pmu_quirk *quirk; @@ -1352,6 +1354,8 @@ static int __init init_hw_perf_events(void) x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ x86_pmu_format_group.attrs = x86_pmu.format_attrs; + filter_events_group(); + pr_info(... version:%d\n, x86_pmu.version); pr_info(... bit width: %d\n, x86_pmu.cntval_bits); pr_info(... generic registers: %d\n, x86_pmu.num_counters); @@ -1718,6 +1722,26 @@ static const struct attribute_group *x86_pmu_attr_groups[] = { NULL, }; +/* + * Remove all undefined events (x86_pmu.event_map(id) == 0) + * out of events_attr attributes. + */ +static void __init filter_events_group(void) +{ + int i, j; + + for (i = 0; events_attr[i]; i++) { + if (x86_pmu.event_map(i)) + continue; + + for (j = i; events_attr[j]; j++) + events_attr[j] = events_attr[j + 1]; + + /* Check the shifted attr. */ + i--; + } +} + static void x86_pmu_flush_branch_stack(void) { if (x86_pmu.flush_branch_stack) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 4/6] perf, tool: Properly free format data
Format data are allocated during PMU lookup. If the lookup fails in next steps, we don't release the format data. This patch ensures that format data get released in case there's failure during PMU load. Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/pmu.c | 58 ++--- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 3c86022..e8cff3d 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -15,6 +15,14 @@ extern FILE *perf_pmu_in; static LIST_HEAD(pmus); +static void pmu_format_release(struct list_head *head) +{ + struct perf_pmu__format *format, *h; + + list_for_each_entry_safe(format, h, head, list) + free(format); +} + /* * Parse process all the sysfs attributes located under * the directory specified in 'dir' parameter. @@ -229,32 +237,38 @@ static struct perf_pmu *pmu_lookup(char *name) LIST_HEAD(aliases); __u32 type; - /* -* The pmu data we store need consists of the pmu -* type value and format definitions. Load both right -* now. -*/ - if (pmu_format(name, format)) - return NULL; + do { + /* + * The pmu data we store need consists of the pmu + * type value, format and events definitions. Load + * all of them right now. + */ + if (pmu_format(name, format)) + break; - if (pmu_aliases(name, aliases)) - return NULL; + if (pmu_aliases(name, aliases)) + break; - if (pmu_type(name, type)) - return NULL; + if (pmu_type(name, type)) + break; - pmu = zalloc(sizeof(*pmu)); - if (!pmu) - return NULL; + pmu = zalloc(sizeof(*pmu)); + if (!pmu) + break; - INIT_LIST_HEAD(pmu-format); - INIT_LIST_HEAD(pmu-aliases); - list_splice(format, pmu-format); - list_splice(aliases, pmu-aliases); - pmu-name = strdup(name); - pmu-type = type; - list_add_tail(pmu-list, pmus); - return pmu; + INIT_LIST_HEAD(pmu-format); + INIT_LIST_HEAD(pmu-aliases); + list_splice(format, pmu-format); + list_splice(aliases, pmu-aliases); + pmu-name = strdup(name); + pmu-type = type; + list_add_tail(pmu-list, pmus); + return pmu; + + } while (0); + + pmu_format_release(format); + return NULL; } static struct perf_pmu *pmu_find(char *name) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 02/17] perf: Add ability to attach user level registers dump to sample
Introducing PERF_SAMPLE_REGS_USER sample type bit to trigger the dump of user level registers on sample. Registers we want to dump are specified by sample_regs_user bitmask. Only user level registers are dumped at the moment. Meaning the register values of the user space context as it was before the user entered the kernel for whatever reason (syscall, irq, exception, or a PMI happening in userspace). The layout of the sample_regs_user bitmap is described in asm/perf_regs.h for archs that support register dump. This is going to be useful to bring Dwarf CFI based stack unwinding on top of samples. Signed-off-by: Jiri Olsa jo...@redhat.com Original-patch-by: Frederic Weisbecker fweis...@gmail.com --- include/linux/perf_event.h | 20 -- kernel/events/core.c | 61 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 76c5c8b..57f209d 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -130,8 +130,9 @@ enum perf_event_sample_format { PERF_SAMPLE_STREAM_ID = 1U 9, PERF_SAMPLE_RAW = 1U 10, PERF_SAMPLE_BRANCH_STACK= 1U 11, + PERF_SAMPLE_REGS_USER = 1U 12, - PERF_SAMPLE_MAX = 1U 12, /* non-ABI */ + PERF_SAMPLE_MAX = 1U 13, /* non-ABI */ }; /* @@ -194,6 +195,7 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER064 /* sizeof first published struct */ #define PERF_ATTR_SIZE_VER172 /* add: config2 */ #define PERF_ATTR_SIZE_VER280 /* add: branch_sample_type */ +#define PERF_ATTR_SIZE_VER388 /* add: sample_regs_user */ /* * Hardware event_id to monitor via a performance monitoring event: @@ -271,7 +273,13 @@ struct perf_event_attr { __u64 bp_len; __u64 config2; /* extension of config1 */ }; - __u64 branch_sample_type; /* enum branch_sample_type */ + __u64 branch_sample_type; /* enum perf_branch_sample_type */ + + /* +* Defines set of user regs to dump on samples. +* See asm/perf_regs.h for details. +*/ + __u64 sample_regs_user; }; /* @@ -548,6 +556,9 @@ enum perf_event_type { *char data[size];} PERF_SAMPLE_RAW * * { u64 from, to, flags } lbr[nr];} PERF_SAMPLE_BRANCH_STACK +* +* { u64 available; +*u64 regs[weight(mask)]; } PERF_SAMPLE_REGS_USER * }; */ PERF_RECORD_SAMPLE = 9, @@ -609,6 +620,7 @@ struct perf_guest_info_callbacks { #include linux/static_key.h #include linux/atomic.h #include linux/sysfs.h +#include linux/perf_regs.h #include asm/local.h struct perf_callchain_entry { @@ -1133,6 +1145,7 @@ struct perf_sample_data { struct perf_callchain_entry *callchain; struct perf_raw_record *raw; struct perf_branch_stack*br_stack; + struct pt_regs *regs_user; }; static inline void perf_sample_data_init(struct perf_sample_data *data, @@ -1142,7 +1155,8 @@ static inline void perf_sample_data_init(struct perf_sample_data *data, data-addr = addr; data-raw = NULL; data-br_stack = NULL; - data-period= period; + data-period = period; + data-regs_user = NULL; } extern void perf_output_sample(struct perf_output_handle *handle, diff --git a/kernel/events/core.c b/kernel/events/core.c index f1cf0ed..e817e32 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3756,6 +3756,33 @@ int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) } EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks); +static void +perf_output_sample_regs(struct perf_output_handle *handle, + struct pt_regs *regs, u64 mask) +{ + int bit; + + for_each_set_bit(bit, (const unsigned long *) mask, +sizeof(mask) * BITS_PER_BYTE) { + u64 val; + + val = perf_reg_value(regs, bit); + perf_output_put(handle, val); + } +} + +static struct pt_regs *perf_sample_regs_user(struct pt_regs *regs) +{ + if (!user_mode(regs)) { + if (current-mm) + regs = task_pt_regs(current); + else + regs = NULL; + } + + return regs; +} + static void __perf_event_header__init_id(struct perf_event_header *header, struct perf_sample_data *data, struct perf_event *event) @@ -4016,6 +4043,23 @@ void perf_output_sample(struct perf_output_handle *handle, perf_output_put(handle
[PATCH 08/17] perf, tool: Adding PERF_ATTR_SIZE_VER2 to the header swap check
Updating attr_file_abi_sizes array with PERF_ATTR_SIZE_VER2 version, so we have the swap check complete. Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/header.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 5a47aba..9678af6 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1814,6 +1814,7 @@ out_free: static const int attr_file_abi_sizes[] = { [0] = PERF_ATTR_SIZE_VER0, [1] = PERF_ATTR_SIZE_VER1, + [2] = PERF_ATTR_SIZE_VER2, 0, }; -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 12/17] perf, tool: Add libunwind dependency for dwarf cfi unwinding
Adding libunwind to be linked with perf if available. It's required for the to get dwarf cfi unwinding support. Also building perf with the dwarf call frame informations by default, so that we can unwind callchains in perf itself. Adding LIBUNWIND_DIR Makefile variable allowing user to specify the directory with libunwind to be linked. This is used for debug purposes. Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Frederic Weisbecker fweis...@gmail.com --- tools/perf/Makefile | 30 +- tools/perf/config/feature-tests.mak | 25 + 2 files changed, 54 insertions(+), 1 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 576db7e..d0c3291 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -38,6 +38,9 @@ include config/utilities.mak # Define NO_NEWT if you do not want TUI support. # # Define NO_DEMANGLE if you do not want C++ symbol demangling. +# +# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf +# backtrace post unwind. $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) @@ -59,6 +62,7 @@ AR = $(CROSS_COMPILE)ar ifeq ($(ARCH),i386) ARCH := x86 NO_PERF_REGS := 0 + LIBUNWIND_LIBS = -lunwind -lunwind-x86 endif ifeq ($(ARCH),x86_64) ARCH := x86 @@ -72,6 +76,7 @@ ifeq ($(ARCH),x86_64) ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S endif NO_PERF_REGS := 0 + LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 endif # Treat warnings as errors unless directed not to @@ -92,7 +97,7 @@ ifdef PARSER_DEBUG PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG endif -CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) +CFLAGS = -fno-omit-frame-pointer -ggdb3 -funwind-tables -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) EXTLIBS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE ALL_LDFLAGS = $(LDFLAGS) @@ -456,6 +461,21 @@ ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) endif # Dwarf support endif # NO_DWARF +ifndef NO_LIBUNWIND +# for linking with debug library, run like: +# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ +ifdef LIBUNWIND_DIR + LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include + LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib +endif + +FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) +ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y) + msg := $(warning No libunwind found. Please install libunwind = 0.99); + NO_LIBUNWIND := 1 +endif # Libunwind support +endif # NO_LIBUNWIND + -include arch/$(ARCH)/Makefile ifneq ($(OUTPUT),) @@ -487,6 +507,14 @@ else endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF +ifdef NO_LIBUNWIND + BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT +else + EXTLIBS += $(LIBUNWIND_LIBS) + BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS) + BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS) +endif + ifdef NO_NEWT BASIC_CFLAGS += -DNO_NEWT_SUPPORT else diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak index 6c18785..2f1156a 100644 --- a/tools/perf/config/feature-tests.mak +++ b/tools/perf/config/feature-tests.mak @@ -154,3 +154,28 @@ int main(void) return 0; } endef + +ifndef NO_LIBUNWIND +define SOURCE_LIBUNWIND +#include libunwind.h +#include stdlib.h + +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); + + +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) + +int main(void) +{ + unw_addr_space_t addr_space; + addr_space = unw_create_addr_space(NULL, 0); + unw_init_remote(NULL, addr_space, NULL); + dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL); + return 0; +} +endef +endif -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 01/17] perf: Unified API to record selective sets of arch registers
This brings a new API to help the selective dump of registers on event sampling, and its implementation for x86 arch. Added HAVE_PERF_REGS config option to determine if the architecture provides perf registers ABI. The information about desired registers will be passed in u64 mask. It's up to the architecture to map the registers into the mask bits. For the x86 arch implementation, both 32 and 64 bit registers bits are defined within single enum to ensure 64 bit system can provide register dump for compat task if needed in the future. Signed-off-by: Jiri Olsa jo...@redhat.com Original-patch-by: Frederic Weisbecker fweis...@gmail.com --- arch/Kconfig |6 +++ arch/x86/Kconfig |1 + arch/x86/include/asm/perf_regs.h | 33 ++ arch/x86/kernel/Makefile |2 + arch/x86/kernel/perf_regs.c | 90 ++ include/linux/perf_regs.h| 19 6 files changed, 151 insertions(+), 0 deletions(-) create mode 100644 arch/x86/include/asm/perf_regs.h create mode 100644 arch/x86/kernel/perf_regs.c create mode 100644 include/linux/perf_regs.h diff --git a/arch/Kconfig b/arch/Kconfig index 8c3d957..32f4873 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -222,6 +222,12 @@ config HAVE_PERF_EVENTS_NMI subsystem. Also has support for calculating CPU cycle events to determine how many clock cycles in a given period. +config HAVE_PERF_REGS + bool + help + Support selective register dumps for perf events. This includes + bit-mapping of each registers and a unique architecture id. + config HAVE_ARCH_JUMP_LABEL bool diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 94de2c5..acebbd6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -60,6 +60,7 @@ config X86 select HAVE_MIXED_BREAKPOINTS_REGS select PERF_EVENTS select HAVE_PERF_EVENTS_NMI + select HAVE_PERF_REGS select ANON_INODES select HAVE_ALIGNED_STRUCT_PAGE if SLUB !M386 select HAVE_CMPXCHG_LOCAL if !M386 diff --git a/arch/x86/include/asm/perf_regs.h b/arch/x86/include/asm/perf_regs.h new file mode 100644 index 000..3f2207b --- /dev/null +++ b/arch/x86/include/asm/perf_regs.h @@ -0,0 +1,33 @@ +#ifndef _ASM_X86_PERF_REGS_H +#define _ASM_X86_PERF_REGS_H + +enum perf_event_x86_regs { + PERF_REG_X86_AX, + PERF_REG_X86_BX, + PERF_REG_X86_CX, + PERF_REG_X86_DX, + PERF_REG_X86_SI, + PERF_REG_X86_DI, + PERF_REG_X86_BP, + PERF_REG_X86_SP, + PERF_REG_X86_IP, + PERF_REG_X86_FLAGS, + PERF_REG_X86_CS, + PERF_REG_X86_SS, + PERF_REG_X86_DS, + PERF_REG_X86_ES, + PERF_REG_X86_FS, + PERF_REG_X86_GS, + PERF_REG_X86_R8, + PERF_REG_X86_R9, + PERF_REG_X86_R10, + PERF_REG_X86_R11, + PERF_REG_X86_R12, + PERF_REG_X86_R13, + PERF_REG_X86_R14, + PERF_REG_X86_R15, + + PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1, + PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1, +}; +#endif /* _ASM_X86_PERF_REGS_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 8215e56..8d7a619 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -100,6 +100,8 @@ obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_UPROBES) += uprobes.o +obj-$(CONFIG_PERF_EVENTS) += perf_regs.o + ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y) diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c new file mode 100644 index 000..c00c92a --- /dev/null +++ b/arch/x86/kernel/perf_regs.c @@ -0,0 +1,90 @@ + +#include linux/kernel.h +#include linux/bug.h +#include linux/stddef.h +#include asm/perf_regs.h +#include asm/ptrace.h + +#ifdef CONFIG_X86_32 +#define PERF_REG_X86_MAX PERF_REG_X86_32_MAX +#else +#define PERF_REG_X86_MAX PERF_REG_X86_64_MAX +#endif + +#define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) + +static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = { + PT_REGS_OFFSET(PERF_REG_X86_AX, ax), + PT_REGS_OFFSET(PERF_REG_X86_BX, bx), + PT_REGS_OFFSET(PERF_REG_X86_CX, cx), + PT_REGS_OFFSET(PERF_REG_X86_DX, dx), + PT_REGS_OFFSET(PERF_REG_X86_SI, si), + PT_REGS_OFFSET(PERF_REG_X86_DI, di), + PT_REGS_OFFSET(PERF_REG_X86_BP, bp), + PT_REGS_OFFSET(PERF_REG_X86_SP, sp), + PT_REGS_OFFSET(PERF_REG_X86_IP, ip), + PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags), + PT_REGS_OFFSET(PERF_REG_X86_CS, cs), + PT_REGS_OFFSET(PERF_REG_X86_SS, ss), +#ifdef CONFIG_X86_32 + PT_REGS_OFFSET(PERF_REG_X86_DS, ds), + PT_REGS_OFFSET(PERF_REG_X86_ES, es), + PT_REGS_OFFSET(PERF_REG_X86_FS, fs), + PT_REGS_OFFSET(PERF_REG_X86_GS, gs), +#else + /* +* The pt_regs struct does not store
[PATCH 06/17] perf: Add ability to attach user stack dump to sample
Introducing PERF_SAMPLE_STACK_USER sample type bit to trigger the dump of the user level stack on sample. The size of the dump is specified by sample_stack_user value. Being able to dump parts of the user stack, starting from the stack pointer, will be useful to make a post mortem dwarf CFI based stack unwinding. Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Frederic Weisbecker fweis...@gmail.com --- include/linux/perf_event.h | 18 ++- kernel/events/core.c | 121 +++- 2 files changed, 137 insertions(+), 2 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index a4c53da..b4663b3 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -131,8 +131,9 @@ enum perf_event_sample_format { PERF_SAMPLE_RAW = 1U 10, PERF_SAMPLE_BRANCH_STACK= 1U 11, PERF_SAMPLE_REGS_USER = 1U 12, + PERF_SAMPLE_STACK_USER = 1U 13, - PERF_SAMPLE_MAX = 1U 13, /* non-ABI */ + PERF_SAMPLE_MAX = 1U 14, /* non-ABI */ }; /* @@ -196,6 +197,7 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER172 /* add: config2 */ #define PERF_ATTR_SIZE_VER280 /* add: branch_sample_type */ #define PERF_ATTR_SIZE_VER388 /* add: sample_regs_user */ +#define PERF_ATTR_SIZE_VER496 /* add: sample_stack_user */ /* * Hardware event_id to monitor via a performance monitoring event: @@ -280,6 +282,14 @@ struct perf_event_attr { * See asm/perf_regs.h for details. */ __u64 sample_regs_user; + + /* +* Defines size of the user stack to dump on samples. +*/ + __u32 sample_stack_user; + + /* Align to u64. */ + __u32 __reserved_2; }; /* @@ -559,6 +569,10 @@ enum perf_event_type { * * { u64 available; *u64 regs[weight(mask)]; } PERF_SAMPLE_REGS_USER +* +* { u64 size; +*char data[size]; +*u64 dyn_size; } PERF_SAMPLE_STACK_USER * }; */ PERF_RECORD_SAMPLE = 9, @@ -1146,6 +1160,7 @@ struct perf_sample_data { struct perf_raw_record *raw; struct perf_branch_stack*br_stack; struct pt_regs *regs_user; + u64 stack_user_size; }; static inline void perf_sample_data_init(struct perf_sample_data *data, @@ -1157,6 +1172,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data, data-br_stack = NULL; data-period = period; data-regs_user = NULL; + data-stack_user_size = 0; } extern void perf_output_sample(struct perf_output_handle *handle, diff --git a/kernel/events/core.c b/kernel/events/core.c index e817e32..8a9cf80 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3771,6 +3771,45 @@ perf_output_sample_regs(struct perf_output_handle *handle, } } +static void +perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size, + struct pt_regs *regs) +{ + /* Case of a kernel thread, nothing to dump */ + if (!regs) { + u64 size = 0; + perf_output_put(handle, size); + } else { + unsigned long sp; + unsigned int rem; + u64 dyn_size; + + /* +* We dump: +* static size +* - the size requested by user or the best one we can fit +* in to the sample max size +* data +* - user stack dump data +* dynamic size +* - the actual dumped size +*/ + + /* Static size. */ + perf_output_put(handle, dump_size); + + /* Data. */ + sp = user_stack_pointer(regs); + rem = __output_copy_user(handle, (void *) sp, dump_size); + dyn_size = dump_size - rem; + + perf_output_skip(handle, rem); + + /* Dynamic size. */ + perf_output_put(handle, dyn_size); + } +} + static struct pt_regs *perf_sample_regs_user(struct pt_regs *regs) { if (!user_mode(regs)) { @@ -4060,6 +4099,11 @@ void perf_output_sample(struct perf_output_handle *handle, mask); } } + + if (sample_type PERF_SAMPLE_STACK_USER) + perf_output_sample_ustack(handle, + data-stack_user_size, + data-regs_user); } void perf_prepare_sample(struct perf_event_header *header
[PATCH 07/17] perf: Add attribute to filter out callchains
From: Frederic Weisbecker fweis...@gmail.com 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: Frederic Weisbecker fweis...@gmail.com [ Added kernel callchains filtering ] Signed-off-by: Jiri Olsa jo...@redhat.com --- include/linux/perf_event.h |5 - kernel/events/callchain.c | 25 +++-- kernel/events/core.c |5 - kernel/events/internal.h |3 ++- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index b4663b3..91c2de2 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -259,7 +259,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 */ diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c index 6581a04..905ffb2 100644 --- a/kernel/events/callchain.c +++ b/kernel/events/callchain.c @@ -153,12 +153,12 @@ put_callchain_entry(int rctx) put_recursion_context(__get_cpu_var(callchain_recursion), rctx); } -struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) +struct perf_callchain_entry *perf_callchain(struct pt_regs *regs, + int kernel, int user) { int rctx; struct perf_callchain_entry *entry; - entry = get_callchain_entry(rctx); if (rctx == -1) return NULL; @@ -168,18 +168,23 @@ struct perf_callchain_entry *perf_callchain(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) { - 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) { + perf_callchain_store(entry, PERF_CONTEXT_USER); + perf_callchain_user(entry, regs); + } } exit_put: diff --git a/kernel/events/core.c b/kernel/events/core.c index 8a9cf80..78f405e 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4126,8 +4126,11 @@ void perf_prepare_sample(struct perf_event_header *header, if (sample_type PERF_SAMPLE_CALLCHAIN) { int size = 1; + int kernel = !event-attr.exclude_callchain_kernel; + int user = !event-attr.exclude_callchain_user; - data-callchain = perf_callchain(regs); + if (kernel || user) + data-callchain = perf_callchain(regs, kernel, user); if (data-callchain) size += data-callchain-nr; diff --git a/kernel/events/internal.h b/kernel/events/internal.h index be1ef29..abcc03d 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -125,7 +125,8 @@ DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP) DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user) /* Callchain handling */ -extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs); +extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs, + int kernel, int user); extern int get_callchain_buffers(void); extern void put_callchain_buffers(void); -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 11/17] perf, tool: Add interface to arch registers sets
Adding header files to access unified API for arch registers. util/perf_regs.h - global perf_reg declarations arch/x86/include/perf_regs.h - x86 arch specific Adding perf_reg_name function to obtain register name based on the reg ID value, and PERF_REGS_MASK macro with mask definition of all current arch registers (will be used in unwind patches). Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/Makefile | 13 +- tools/perf/arch/x86/include/perf_regs.h | 80 +++ tools/perf/util/perf_regs.h | 14 + 3 files changed, 106 insertions(+), 1 deletions(-) create mode 100644 tools/perf/arch/x86/include/perf_regs.h create mode 100644 tools/perf/util/perf_regs.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 75d74e5..576db7e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -50,13 +50,15 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ -e s/sh[234].*/sh/ ) +NO_PERF_REGS := 1 CC = $(CROSS_COMPILE)gcc AR = $(CROSS_COMPILE)ar # Additional ARCH settings for x86 ifeq ($(ARCH),i386) -ARCH := x86 + ARCH := x86 + NO_PERF_REGS := 0 endif ifeq ($(ARCH),x86_64) ARCH := x86 @@ -69,6 +71,7 @@ ifeq ($(ARCH),x86_64) ARCH_CFLAGS := -DARCH_X86_64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S endif + NO_PERF_REGS := 0 endif # Treat warnings as errors unless directed not to @@ -319,6 +322,7 @@ LIB_H += $(ARCH_INCLUDE) LIB_H += util/cgroup.h LIB_H += $(TRACE_EVENT_DIR)event-parse.h LIB_H += util/target.h +LIB_H += util/perf_regs.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o @@ -669,6 +673,13 @@ else endif endif +ifeq ($(NO_PERF_REGS),0) + ifeq ($(ARCH),x86) + LIB_H += arch/x86/include/perf_regs.h + endif +else + BASIC_CFLAGS += -DNO_PERF_REGS +endif ifdef NO_STRLCPY BASIC_CFLAGS += -DNO_STRLCPY diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h new file mode 100644 index 000..46fc9f1 --- /dev/null +++ b/tools/perf/arch/x86/include/perf_regs.h @@ -0,0 +1,80 @@ +#ifndef ARCH_PERF_REGS_H +#define ARCH_PERF_REGS_H + +#include stdlib.h +#include ../../util/types.h +#include ../../../../../arch/x86/include/asm/perf_regs.h + +#ifndef ARCH_X86_64 +#define PERF_REGS_MASK ((1ULL PERF_REG_X86_32_MAX) - 1) +#else +#define REG_NOSUPPORT ((1ULL PERF_REG_X86_DS) | \ + (1ULL PERF_REG_X86_ES) | \ + (1ULL PERF_REG_X86_FS) | \ + (1ULL PERF_REG_X86_GS)) +#define PERF_REGS_MASK (((1ULL PERF_REG_X86_64_MAX) - 1) ~REG_NOSUPPORT) +#endif +#define PERF_REG_IP PERF_REG_X86_IP +#define PERF_REG_SP PERF_REG_X86_SP + +static inline const char *perf_reg_name(int id) +{ + switch (id) { + case PERF_REG_X86_AX: + return AX; + case PERF_REG_X86_BX: + return BX; + case PERF_REG_X86_CX: + return CX; + case PERF_REG_X86_DX: + return DX; + case PERF_REG_X86_SI: + return SI; + case PERF_REG_X86_DI: + return DI; + case PERF_REG_X86_BP: + return BP; + case PERF_REG_X86_SP: + return SP; + case PERF_REG_X86_IP: + return IP; + case PERF_REG_X86_FLAGS: + return FLAGS; + case PERF_REG_X86_CS: + return CS; + case PERF_REG_X86_SS: + return SS; + case PERF_REG_X86_DS: + return DS; + case PERF_REG_X86_ES: + return ES; + case PERF_REG_X86_FS: + return FS; + case PERF_REG_X86_GS: + return GS; +#ifdef ARCH_X86_64 + case PERF_REG_X86_R8: + return R8; + case PERF_REG_X86_R9: + return R9; + case PERF_REG_X86_R10: + return R10; + case PERF_REG_X86_R11: + return R11; + case PERF_REG_X86_R12: + return R12; + case PERF_REG_X86_R13: + return R13; + case PERF_REG_X86_R14: + return R14; + case PERF_REG_X86_R15: + return R15; +#endif /* ARCH_X86_64 */ + default: + return NULL; + } + + return NULL; +} + +#endif /* ARCH_PERF_REGS_H */ diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h new file mode 100644 index 000..3efb79a --- /dev/null +++ b/tools/perf/util/perf_regs.h @@ -0,0 +1,14 @@ +#ifndef __PERF_REGS_H +#define __PERF_REGS_H + +#ifndef NO_PERF_REGS_DEFS +#include perf_regs.h +#else +#define PERF_REGS_MASK 0
[PATCH 10/17] perf, tool: Add interface to read DSO image data
Adding following interface for DSO object to allow reading of DSO image data: dso__data_fd - opens DSO and returns file descriptor Binary types are used to locate/open DSO in following order: DSO_BINARY_TYPE__BUILD_ID_CACHE DSO_BINARY_TYPE__SYSTEM_PATH_DSO In other word we first try to open DSO build-id path, and if that fails we try to open DSO system path. dso__data_read_offset - reads DSO data from specified offset dso__data_read_addr - reads DSO data from specified address/map. Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/symbol.c | 109 ++ tools/perf/util/symbol.h |8 +++ 2 files changed, 117 insertions(+), 0 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 79fc779..ff4d603 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -65,6 +65,14 @@ static enum dso_binary_type binary_type_symtab[] = { #define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab) +static enum dso_binary_type binary_type_data[] = { + DSO_BINARY_TYPE__BUILD_ID_CACHE, + DSO_BINARY_TYPE__SYSTEM_PATH_DSO, + DSO_BINARY_TYPE__NOT_FOUND, +}; + +#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data) + int dso__name_len(const struct dso *dso) { if (!dso) @@ -336,6 +344,7 @@ struct dso *dso__new(const char *name) for (i = 0; i MAP__NR_TYPES; ++i) dso-symbols[i] = dso-symbol_names[i] = RB_ROOT; dso-symtab_type = DSO_BINARY_TYPE__NOT_FOUND; + dso-data_type = DSO_BINARY_TYPE__NOT_FOUND; dso-loaded = 0; dso-sorted_by_name = 0; dso-has_build_id = 0; @@ -2946,3 +2955,103 @@ struct map *dso__new_map(const char *name) return map; } + +static int open_dso(struct dso *dso, struct machine *machine) +{ + char *root_dir = (char *) ; + char *name; + int fd; + + name = malloc(PATH_MAX); + if (!name) + return -ENOMEM; + + if (machine) + root_dir = machine-root_dir; + + if (dso__binary_type_file(dso, dso-data_type, + root_dir, name, PATH_MAX)) { + free(name); + return -EINVAL; + } + + fd = open(name, O_RDONLY); + free(name); + return fd; +} + +int dso__data_fd(struct dso *dso, struct machine *machine) +{ + int i = 0; + + if (dso-data_type != DSO_BINARY_TYPE__NOT_FOUND) + return open_dso(dso, machine); + + do { + int fd; + + dso-data_type = binary_type_data[i++]; + + fd = open_dso(dso, machine); + if (fd = 0) + return fd; + + } while (dso-data_type != DSO_BINARY_TYPE__NOT_FOUND); + + return -EINVAL; +} + +static ssize_t dso_cache_read(struct dso *dso __used, u64 offset __used, + u8 *data __used, ssize_t size __used) +{ + return -EINVAL; +} + +static int dso_cache_add(struct dso *dso __used, u64 offset __used, +u8 *data __used, ssize_t size __used) +{ + return 0; +} + +static ssize_t read_dso_data(struct dso *dso, struct machine *machine, +u64 offset, u8 *data, ssize_t size) +{ + ssize_t rsize = -1; + int fd; + + fd = dso__data_fd(dso, machine); + if (fd 0) + return -1; + + do { + if (-1 == lseek(fd, offset, SEEK_SET)) + break; + + rsize = read(fd, data, size); + if (-1 == rsize) + break; + + if (dso_cache_add(dso, offset, data, size)) + pr_err(Failed to add data int dso cache.); + + } while (0); + + close(fd); + return rsize; +} + +ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, + u64 offset, u8 *data, ssize_t size) +{ + if (dso_cache_read(dso, offset, data, size)) + return read_dso_data(dso, machine, offset, data, size); + return 0; +} + +ssize_t dso__data_read_addr(struct dso *dso, struct map *map, + struct machine *machine, u64 addr, + u8 *data, ssize_t size) +{ + u64 offset = map-map_ip(map, addr); + return dso__data_read_offset(dso, machine, offset, data, size); +} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index dc474f0..9b9ea00 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -189,6 +189,7 @@ struct dso { enum dso_kernel_typekernel; enum dso_swap_type needs_swap; enum dso_binary_typesymtab_type; + enum dso_binary_typedata_type; u8 adjust_symbols:1; u8 has_build_id:1; u8 hit:1
[PATCH 14/17] perf, tool: Support for dwarf cfi unwinding on post processing
This brings the support for dwarf cfi unwinding on perf post processing. Call frame informations are retrieved and then passed to libunwind that requests memory and register content from the applications. Adding unwind object to handle the user stack backtrace based on the user register values and user stack dump. The unwind object access the libunwind via remote interface and provides to it all the necessary data to unwind the stack. The unwind interface provides following function: unwind__get_entries And callback (specified in above function) to retrieve the backtrace entries: typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Frederic Weisbecker fweis...@gmail.com --- tools/perf/Makefile|2 + tools/perf/arch/x86/Makefile |3 + tools/perf/arch/x86/util/unwind.c | 111 tools/perf/builtin-report.c| 24 +- tools/perf/builtin-script.c| 16 +- tools/perf/builtin-top.c |5 +- tools/perf/util/include/linux/compiler.h |1 + tools/perf/util/map.h |7 +- .../perf/util/scripting-engines/trace-event-perl.c |3 +- .../util/scripting-engines/trace-event-python.c|3 +- tools/perf/util/session.c | 61 ++- tools/perf/util/session.h |3 +- tools/perf/util/trace-event-scripting.c|3 +- tools/perf/util/trace-event.h |5 +- tools/perf/util/unwind.c | 567 tools/perf/util/unwind.h | 34 ++ 16 files changed, 811 insertions(+), 37 deletions(-) create mode 100644 tools/perf/arch/x86/util/unwind.c create mode 100644 tools/perf/util/unwind.c create mode 100644 tools/perf/util/unwind.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index d0c3291..c18c790 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -328,6 +328,7 @@ LIB_H += util/cgroup.h LIB_H += $(TRACE_EVENT_DIR)event-parse.h LIB_H += util/target.h LIB_H += util/perf_regs.h +LIB_H += util/unwind.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o @@ -513,6 +514,7 @@ else EXTLIBS += $(LIBUNWIND_LIBS) BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS) BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS) + LIB_OBJS += $(OUTPUT)util/unwind.o endif ifdef NO_NEWT diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 744e629..815841c 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile @@ -2,4 +2,7 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o endif +ifndef NO_LIBUNWIND +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o +endif LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o diff --git a/tools/perf/arch/x86/util/unwind.c b/tools/perf/arch/x86/util/unwind.c new file mode 100644 index 000..78d956e --- /dev/null +++ b/tools/perf/arch/x86/util/unwind.c @@ -0,0 +1,111 @@ + +#include errno.h +#include libunwind.h +#include perf_regs.h +#include ../../util/unwind.h + +#ifdef ARCH_X86_64 +int unwind__arch_reg_id(int regnum) +{ + int id; + + switch (regnum) { + case UNW_X86_64_RAX: + id = PERF_REG_X86_AX; + break; + case UNW_X86_64_RDX: + id = PERF_REG_X86_DX; + break; + case UNW_X86_64_RCX: + id = PERF_REG_X86_CX; + break; + case UNW_X86_64_RBX: + id = PERF_REG_X86_BX; + break; + case UNW_X86_64_RSI: + id = PERF_REG_X86_SI; + break; + case UNW_X86_64_RDI: + id = PERF_REG_X86_DI; + break; + case UNW_X86_64_RBP: + id = PERF_REG_X86_BP; + break; + case UNW_X86_64_RSP: + id = PERF_REG_X86_SP; + break; + case UNW_X86_64_R8: + id = PERF_REG_X86_R8; + break; + case UNW_X86_64_R9: + id = PERF_REG_X86_R9; + break; + case UNW_X86_64_R10: + id = PERF_REG_X86_R10; + break; + case UNW_X86_64_R11: + id = PERF_REG_X86_R11; + break; + case UNW_X86_64_R12: + id = PERF_REG_X86_R12; + break; + case UNW_X86_64_R13: + id = PERF_REG_X86_R13; + break; + case UNW_X86_64_R14: + id = PERF_REG_X86_R14; + break; + case UNW_X86_64_R15: + id = PERF_REG_X86_R15; + break; + case UNW_X86_64_RIP: + id = PERF_REG_X86_IP
[PATCH 15/17] perf, tool: Support for dwarf mode callchain on perf record
This patch enables perf to use the dwarf unwind code. It extends the perf record '-g' option with following arguments: 'fp' - provides framepointer based user stack backtrace 'dwarf[,size]' - provides dwarf (libunwind) based user stack backtrace. The size specifies the size of the user stack dump. If omitted it is 8192 by default. If libunwind is found during the perf build, then the 'dwarf' argument becomes available for record command. The 'fp' stays as default option in any case. Examples: (perf compiled with libunwind) perf record -g dwarf ls - provides dwarf unwind with 8192 as stack dump size perf record -g dwarf,4096 ls - provides dwarf unwind with 4096 as stack dump size perf record -g -- ls perf record -g fp ls - provides frame pointer unwind Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Frederic Weisbecker fweis...@gmail.com --- tools/perf/builtin-record.c | 108 ++- tools/perf/perf.h |9 +++- tools/perf/util/evsel.c | 13 +- 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f5a6452..fff130b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -31,6 +31,15 @@ #include sched.h #include sys/mman.h +#define CALLCHAIN_HELP do call-graph (stack chain/backtrace) recording: + +#ifdef NO_LIBUNWIND_SUPPORT +static char callchain_help[] = CALLCHAIN_HELP [fp]; +#else +static unsigned long default_stack_dump_size = 8192; +static char callchain_help[] = CALLCHAIN_HELP [fp] dwarf; +#endif + enum write_mode_t { WRITE_FORCE, WRITE_APPEND @@ -732,6 +741,100 @@ error: return ret; } +#ifndef NO_LIBUNWIND_SUPPORT +static int get_stack_size(char *str, unsigned long *_size) +{ + char *endptr; + unsigned long size; + unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); + + size = strtoul(str, endptr, 0); + + do { + if (*endptr) + break; + + size = round_up(size, sizeof(u64)); + if (!size || size max_size) + break; + + *_size = size; + return 0; + + } while (0); + + pr_err(callchain: Incorrect stack dump size (max %ld): %s\n, + max_size, str); + return -1; +} +#endif /* !NO_LIBUNWIND_SUPPORT */ + +static int +parse_callchain_opt(const struct option *opt __used, const char *arg, + int unset) +{ + struct perf_record *rec = (struct perf_record *)opt-value; + char *tok, *name, *saveptr = NULL; + char buf[20]; + int ret = -1; + + /* --no-call-graph */ + if (unset) + return 0; + + /* We specified default option if none is provided. */ + BUG_ON(!arg); + + /* We need buffer that we know we can write to. */ + snprintf(buf, 20, %s, arg); + + tok = strtok_r((char *)buf, ,, saveptr); + name = tok ? : (char *)buf; + + do { + /* Framepointer style */ + if (!strncmp(name, fp, sizeof(fp))) { + if (!strtok_r(NULL, ,, saveptr)) { + rec-opts.call_graph = CALLCHAIN_FP; + ret = 0; + } else + pr_err(callchain: No more arguments + needed for -g fp\n); + break; + +#ifndef NO_LIBUNWIND_SUPPORT + /* Dwarf style */ + } else if (!strncmp(name, dwarf, sizeof(dwarf))) { + ret = 0; + rec-opts.call_graph = CALLCHAIN_DWARF; + rec-opts.stack_dump_size = default_stack_dump_size; + + tok = strtok_r(NULL, ,, saveptr); + if (tok) { + unsigned long size = 0; + + ret = get_stack_size(tok, size); + rec-opts.stack_dump_size = size; + } + + if (!ret) + pr_debug(callchain: stack dump size %d\n, +rec-opts.stack_dump_size); +#endif /* !NO_LIBUNWIND_SUPPORT */ + } else { + pr_err(callchain: Unknown -g option + value: %s\n, name); + break; + } + + } while (0); + + if (!ret) + pr_debug(callchain: type %d\n, rec-opts.call_graph); + + return ret; +} + static const char * const record_usage[] = { perf record [options] [command], perf record [options] -- command [options], @@ -803,8 +906,9 @@ const struct option record_options[] = { number
[PATCH 17/17] perf, tool: Add dso data caching tests
Adding automated test for DSO data reading. Testing raw/cached reads from different file/cache locations. Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/Makefile |1 + tools/perf/builtin-test.c |4 + tools/perf/util/dso-test-data.c | 154 +++ tools/perf/util/symbol.h|1 + 4 files changed, 160 insertions(+), 0 deletions(-) create mode 100644 tools/perf/util/dso-test-data.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index c18c790..1f550fa 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -364,6 +364,7 @@ LIB_OBJS += $(OUTPUT)util/usage.o LIB_OBJS += $(OUTPUT)util/wrapper.o LIB_OBJS += $(OUTPUT)util/sigchain.o LIB_OBJS += $(OUTPUT)util/symbol.o +LIB_OBJS += $(OUTPUT)util/dso-test-data.o LIB_OBJS += $(OUTPUT)util/color.o LIB_OBJS += $(OUTPUT)util/pager.o LIB_OBJS += $(OUTPUT)util/header.o diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 5d59398..000efb0 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -1142,6 +1142,10 @@ static struct test { .func = test__perf_pmu, }, { + .desc = Test dso data interface, + .func = dso__test_data, + }, + { .func = NULL, }, }; diff --git a/tools/perf/util/dso-test-data.c b/tools/perf/util/dso-test-data.c new file mode 100644 index 000..ec62977 --- /dev/null +++ b/tools/perf/util/dso-test-data.c @@ -0,0 +1,154 @@ + +#include stdlib.h +#include sys/types.h +#include sys/stat.h +#include fcntl.h +#include string.h + +#include symbol.h + +#define TEST_ASSERT_VAL(text, cond) \ +do { \ + if (!(cond)) { \ + pr_debug(FAILED %s:%d %s\n, __FILE__, __LINE__, text); \ + return -1; \ + } \ +} while (0) + +static char *test_file(int size) +{ + static char buf_templ[] = /tmp/test-XX; + char *templ = buf_templ; + int fd, i; + unsigned char *buf; + + fd = mkostemp(templ, O_CREAT|O_WRONLY|O_TRUNC); + + buf = malloc(size); + if (!buf) { + close(fd); + return NULL; + } + + for (i = 0; i size; i++) + buf[i] = (unsigned char) ((int) i % 10); + + if (size != write(fd, buf, size)) + templ = NULL; + + close(fd); + return templ; +} + +#define TEST_FILE_SIZE (DSO__DATA_CACHE_SIZE * 20) + +struct test_data__offset { + off_t offset; + u8 data[10]; + int size; +}; + +struct test_data__offset offsets[] = { + /* Fill first cache page. */ + { + .offset = 10, + .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + .size = 10, + }, + /* Read first cache page. */ + { + .offset = 10, + .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + .size = 10, + }, + /* Fill cache boundary pages. */ + { + .offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10, + .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + .size = 10, + }, + /* Read cache boundary pages. */ + { + .offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10, + .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + .size = 10, + }, + /* Fill final cache page. */ + { + .offset = TEST_FILE_SIZE - 10, + .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + .size = 10, + }, + /* Read final cache page. */ + { + .offset = TEST_FILE_SIZE - 10, + .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + .size = 10, + }, + /* Read final cache page. */ + { + .offset = TEST_FILE_SIZE - 3, + .data = { 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 }, + .size = 3, + }, +}; + +#define OFFSETS_CNT (sizeof(offsets) / sizeof(struct test_data__offset)) + +int dso__test_data(void) +{ + struct machine machine; + struct dso *dso; + char *file = test_file(TEST_FILE_SIZE); + int i; + + TEST_ASSERT_VAL(No test file, file); + + memset(machine, 0, sizeof(machine)); + + dso = dso__new((const char *)file); + + /* Basic 10 bytes tests. */ + for (i = 0; i (int) OFFSETS_CNT; i++) { + struct test_data__offset *data = offsets[i]; + ssize_t size; + u8 buf[10]; + + memset(buf, 0, 10); + size = dso__data_read_offset(dso, machine, data-offset, +buf, 10); + + TEST_ASSERT_VAL(Wrong size, size == data-size); + TEST_ASSERT_VAL(Wrong data, !memcmp(buf, data-data, 10)); + } + + /* Read cross multiple cache pages. */ + { + ssize_t size; + int c
[PATCH 16/17] perf, tool: Add dso data caching
Adding dso data caching so we don't need to open/read/close, each time we want dso data. The DSO data caching affects following functions: dso__data_read_offset dso__data_read_addr Each DSO read tries to find the data (based on offset) inside the cache. If it's not present it fills the cache from file, and returns the data. If it is present, data are returned with no file read. Each data read is cached by reading cache page sized/aligned amount of DSO data. The cache page size is hardcoded to 4096. The cache is using RB tree with file offset as a sort key. Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/util/symbol.c | 154 -- tools/perf/util/symbol.h | 11 +++ 2 files changed, 147 insertions(+), 18 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index ff4d603..d60490f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -29,6 +29,7 @@ #define NT_GNU_BUILD_ID 3 #endif +static void dso_cache__free(struct rb_root *root); static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); static int elf_read_build_id(Elf *elf, void *bf, size_t size); static void dsos__add(struct list_head *head, struct dso *dso); @@ -343,6 +344,7 @@ struct dso *dso__new(const char *name) dso__set_short_name(dso, dso-name); for (i = 0; i MAP__NR_TYPES; ++i) dso-symbols[i] = dso-symbol_names[i] = RB_ROOT; + dso-cache = RB_ROOT; dso-symtab_type = DSO_BINARY_TYPE__NOT_FOUND; dso-data_type = DSO_BINARY_TYPE__NOT_FOUND; dso-loaded = 0; @@ -378,6 +380,7 @@ void dso__delete(struct dso *dso) free((char *)dso-short_name); if (dso-lname_alloc) free(dso-long_name); + dso_cache__free(dso-cache); free(dso); } @@ -3001,22 +3004,87 @@ int dso__data_fd(struct dso *dso, struct machine *machine) return -EINVAL; } -static ssize_t dso_cache_read(struct dso *dso __used, u64 offset __used, - u8 *data __used, ssize_t size __used) +static void +dso_cache__free(struct rb_root *root) { - return -EINVAL; + struct rb_node *next = rb_first(root); + + while (next) { + struct dso_cache *cache; + + cache = rb_entry(next, struct dso_cache, rb_node); + next = rb_next(cache-rb_node); + rb_erase(cache-rb_node, root); + free(cache); + } } -static int dso_cache_add(struct dso *dso __used, u64 offset __used, -u8 *data __used, ssize_t size __used) +static struct dso_cache* +dso_cache__find(struct rb_root *root, u64 offset) { - return 0; + struct rb_node **p = root-rb_node; + struct rb_node *parent = NULL; + struct dso_cache *cache; + + while (*p != NULL) { + u64 end; + + parent = *p; + cache = rb_entry(parent, struct dso_cache, rb_node); + end = cache-offset + DSO__DATA_CACHE_SIZE; + + if (offset cache-offset) + p = (*p)-rb_left; + else if (offset = end) + p = (*p)-rb_right; + else + return cache; + } + return NULL; +} + +static void +dso_cache__insert(struct rb_root *root, struct dso_cache *new) +{ + struct rb_node **p = root-rb_node; + struct rb_node *parent = NULL; + struct dso_cache *cache; + u64 offset = new-offset; + + while (*p != NULL) { + u64 end; + + parent = *p; + cache = rb_entry(parent, struct dso_cache, rb_node); + end = cache-offset + DSO__DATA_CACHE_SIZE; + + if (offset cache-offset) + p = (*p)-rb_left; + else if (offset = end) + p = (*p)-rb_right; + } + + rb_link_node(new-rb_node, parent, p); + rb_insert_color(new-rb_node, root); +} + +static ssize_t +dso_cache__memcpy(struct dso_cache *cache, u64 offset, + u8 *data, u64 size) +{ + u64 cache_offset = offset - cache-offset; + u64 cache_size = min(cache-size - cache_offset, size); + + memcpy(data, cache-data + cache_offset, cache_size); + return cache_size; } -static ssize_t read_dso_data(struct dso *dso, struct machine *machine, -u64 offset, u8 *data, ssize_t size) +static ssize_t +dso_cache__read(struct dso *dso, struct machine *machine, +u64 offset, u8 *data, ssize_t size) { - ssize_t rsize = -1; + struct dso_cache *cache; + ssize_t ret; int fd; fd = dso__data_fd(dso, machine); @@ -3024,28 +3092,78 @@ static ssize_t read_dso_data(struct dso *dso, struct machine *machine, return -1; do { - if (-1 == lseek(fd
[PATCH 13/17] perf, tool: Support user regs and stack in sample parsing
Adding following info to be parsed out of the event sample: - user register set - user stack dump Both are global and specific to all events within the session. This info will be used in the unwind patches coming in shortly. Adding simple output printout (report -D) for both register and stack dumps. Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Frederic Weisbecker fweis...@gmail.com --- tools/perf/builtin-test.c |4 ++-- tools/perf/util/event.h | 16 +++- tools/perf/util/evlist.c |8 tools/perf/util/evlist.h |1 + tools/perf/util/evsel.c | 30 +- tools/perf/util/header.c |2 ++ tools/perf/util/python.c |3 ++- tools/perf/util/session.c | 36 tools/perf/util/session.h |8 ++-- 9 files changed, 101 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 5ce3030..5d59398 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -564,7 +564,7 @@ static int test__basic_mmap(void) } err = perf_event__parse_sample(event, attr.sample_type, sample_size, - false, sample, false); + false, 0, sample, false); if (err) { pr_err(Can't parse sample, err = %d\n, err); goto out_munmap; @@ -790,7 +790,7 @@ static int test__PERF_RECORD(void) err = perf_event__parse_sample(event, sample_type, sample_size, true, - sample, false); + 0, sample, false); if (err 0) { if (verbose) perf_event__fprintf(event, stderr); diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 1b19728..ed978eb 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -69,6 +69,16 @@ struct sample_event { u64 array[]; }; +struct regs_dump { + u64 *regs; +}; + +struct stack_dump { + u16 offset; + u64 size; + char *data; +}; + struct perf_sample { u64 ip; u32 pid, tid; @@ -82,6 +92,8 @@ struct perf_sample { void *raw_data; struct ip_callchain *callchain; struct branch_stack *branch_stack; + struct regs_dump user_regs; + struct stack_dump user_stack; }; #define BUILD_ID_SIZE 20 @@ -199,7 +211,9 @@ const char *perf_event__name(unsigned int id); int perf_event__parse_sample(const union perf_event *event, u64 type, int sample_size, bool sample_id_all, -struct perf_sample *sample, bool swapped); +u64 sample_regs_user, struct perf_sample *data, +bool swapped); + int perf_event__synthesize_sample(union perf_event *event, u64 type, const struct perf_sample *sample, bool swapped); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index f74e956..02fd2e2b 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -689,6 +689,14 @@ bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) return true; } +u64 perf_evlist__sample_regs_user(const struct perf_evlist *evlist) +{ + struct perf_evsel *first; + + first = list_entry(evlist-entries.next, struct perf_evsel, node); + return first-attr.sample_regs_user; +} + u64 perf_evlist__sample_type(const struct perf_evlist *evlist) { struct perf_evsel *first; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 40d4d3c..8dbf46c 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -124,6 +124,7 @@ u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); +u64 perf_evlist__sample_regs_user(const struct perf_evlist *evlist); void perf_evlist__splice_list_tail(struct perf_evlist *evlist, struct list_head *list, diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index e817713..3a284b1 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -8,6 +8,7 @@ */ #include byteswap.h +#include linux/bitops.h #include asm/bug.h #include evsel.h #include evlist.h @@ -730,7 +731,8 @@ static bool sample_overlap(const union perf_event *event, int perf_event__parse_sample(const union perf_event *event, u64 type, int sample_size, bool sample_id_all
[PATCH 09/17] perf, tool: Factor DSO symtab types to generic binary types
Adding interface to access DSOs so it could be used from another place. New DSO binary type is added - making current SYMTAB__* types more general: DSO_BINARY_TYPE__* = SYMTAB__* Following function is added to return path based on the specified binary type: dso__binary_type_file Signed-off-by: Jiri Olsa jo...@redhat.com --- tools/perf/builtin-top.c |2 +- tools/perf/util/annotate.c |2 +- tools/perf/util/symbol.c | 209 ++-- tools/perf/util/symbol.h | 34 4 files changed, 145 insertions(+), 102 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index e3cab5f..35e86c6 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -125,7 +125,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) /* * We can't annotate with just /proc/kallsyms */ - if (map-dso-symtab_type == SYMTAB__KALLSYMS) { + if (map-dso-symtab_type == DSO_BINARY_TYPE__KALLSYMS) { pr_err(Can't annotate %s: No vmlinux file was found in the path\n, sym-name); sleep(1); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 8069dfb..7d3641f 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -777,7 +777,7 @@ fallback: free_filename = false; } - if (dso-symtab_type == SYMTAB__KALLSYMS) { + if (dso-symtab_type == DSO_BINARY_TYPE__KALLSYMS) { char bf[BUILD_ID_SIZE * 2 + 16] = with build id ; char *build_id_msg = NULL; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 50958bb..79fc779 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -48,6 +48,23 @@ struct symbol_conf symbol_conf = { .symfs= , }; +static enum dso_binary_type binary_type_symtab[] = { + DSO_BINARY_TYPE__KALLSYMS, + DSO_BINARY_TYPE__GUEST_KALLSYMS, + DSO_BINARY_TYPE__JAVA_JIT, + DSO_BINARY_TYPE__DEBUGLINK, + DSO_BINARY_TYPE__BUILD_ID_CACHE, + DSO_BINARY_TYPE__FEDORA_DEBUGINFO, + DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, + DSO_BINARY_TYPE__BUILDID_DEBUGINFO, + DSO_BINARY_TYPE__SYSTEM_PATH_DSO, + DSO_BINARY_TYPE__GUEST_KMODULE, + DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, + DSO_BINARY_TYPE__NOT_FOUND, +}; + +#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab) + int dso__name_len(const struct dso *dso) { if (!dso) @@ -318,7 +335,7 @@ struct dso *dso__new(const char *name) dso__set_short_name(dso, dso-name); for (i = 0; i MAP__NR_TYPES; ++i) dso-symbols[i] = dso-symbol_names[i] = RB_ROOT; - dso-symtab_type = SYMTAB__NOT_FOUND; + dso-symtab_type = DSO_BINARY_TYPE__NOT_FOUND; dso-loaded = 0; dso-sorted_by_name = 0; dso-has_build_id = 0; @@ -806,9 +823,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename, symbols__fixup_end(dso-symbols[map-type]); if (dso-kernel == DSO_TYPE_GUEST_KERNEL) - dso-symtab_type = SYMTAB__GUEST_KALLSYMS; + dso-symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; else - dso-symtab_type = SYMTAB__KALLSYMS; + dso-symtab_type = DSO_BINARY_TYPE__KALLSYMS; return dso__split_kallsyms(dso, map, filter); } @@ -1660,32 +1677,110 @@ out: char dso__symtab_origin(const struct dso *dso) { static const char origin[] = { - [SYMTAB__KALLSYMS]= 'k', - [SYMTAB__JAVA_JIT]= 'j', - [SYMTAB__DEBUGLINK] = 'l', - [SYMTAB__BUILD_ID_CACHE] = 'B', - [SYMTAB__FEDORA_DEBUGINFO]= 'f', - [SYMTAB__UBUNTU_DEBUGINFO]= 'u', - [SYMTAB__BUILDID_DEBUGINFO] = 'b', - [SYMTAB__SYSTEM_PATH_DSO] = 'd', - [SYMTAB__SYSTEM_PATH_KMODULE] = 'K', - [SYMTAB__GUEST_KALLSYMS] = 'g', - [SYMTAB__GUEST_KMODULE] = 'G', + [DSO_BINARY_TYPE__KALLSYMS] = 'k', + [DSO_BINARY_TYPE__JAVA_JIT] = 'j', + [DSO_BINARY_TYPE__DEBUGLINK]= 'l', + [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', + [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f', + [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u', + [DSO_BINARY_TYPE__BUILDID_DEBUGINFO]= 'b', + [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', + [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', + [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', + [DSO_BINARY_TYPE__GUEST_KMODULE]= 'G', }; - if (dso == NULL || dso-symtab_type
[PATCH 05/17] perf: Add perf_output_skip function to skip bytes in sample
Introducing perf_output_skip function to be able to skip data within the perf ring buffer. When writing data into perf ring buffer we first reserve needed place in ring buffer and then copy the actual data. There's a possibility we won't be able to fill all the reserved size with data, so we need a way to skip the remaining bytes. This is going to be useful when storing the user stack dump, where we might end up with less data than we originally requested. Signed-off-by: Jiri Olsa jo...@redhat.com Acked-by: Frederic Weisbecker fweis...@gmail.com --- include/linux/perf_event.h |2 ++ kernel/events/internal.h|4 kernel/events/ring_buffer.c |6 ++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 432227b..a4c53da 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1305,6 +1305,8 @@ extern int perf_output_begin(struct perf_output_handle *handle, extern void perf_output_end(struct perf_output_handle *handle); extern unsigned int perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len); +extern unsigned int perf_output_skip(struct perf_output_handle *handle, +unsigned int len); extern int perf_swevent_get_recursion_context(void); extern void perf_swevent_put_recursion_context(int rctx); extern void perf_event_enable(struct perf_event *event); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 2206a0f..be1ef29 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -114,6 +114,10 @@ static inline int memcpy_common(void *dst, const void *src, size_t n) DEFINE_OUTPUT_COPY(__output_copy, memcpy_common) +#define MEMCPY_SKIP(dst, src, n) (n) + +DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP) + #ifndef arch_perf_out_copy_user #define arch_perf_out_copy_user __copy_from_user_inatomic #endif diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index b4c2ad3..23cb34f 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -188,6 +188,12 @@ unsigned int perf_output_copy(struct perf_output_handle *handle, return __output_copy(handle, buf, len); } +unsigned int perf_output_skip(struct perf_output_handle *handle, + unsigned int len) +{ + return __output_skip(handle, NULL, len); +} + void perf_output_end(struct perf_output_handle *handle) { perf_output_put_handle(handle); -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 00/17] perf: Add backtrace post dwarf unwind
hi, patches available also as tarball in here: http://people.redhat.com/~jolsa/perf_post_unwind_v7.tar.bz2 v7 changes: - omitted v6 patches 9 and 15 They need more work and will be sent separately. I dont want to hold off whole patchset because of them. We could miss some related backtraces (syscall, vdso) in this version. - v6 patch 11, 14, 20 already in v6 changes: patch 01/23 - unrelated - ftrace stuff patch 03/23 - added PERF_SAMPLE_REGS_USER bit - added regs_user initialization patch 07/23 - added PERF_SAMPLE_STACK_USER bit - sample_stack_user changed to u32 and added size check new patches 1,9,10,20 v5 changes: patch 1/19 - having just one enum set of the perf registers patch 2/19 - using for_each_set_bit for scanning the mask - single regs enum for both 32 and 64 bits versions - using regs mask != 0 trigger to trigger the regs dump patch 5/19 - adding perf_output_skip so we can skip undumped part of the stack in RB patch 6/19 - using stack size != 0 trigger to trigger the stack dump - do not zero the memory for non retrieved part of the stack dump patch 7/19 - adding exclude_callchain_kernel attribute patch 8/19 - this could be taken without the rest of the series v4 changes: - no real change from v3, just rebase - v3 patch 06/17 got already merged v3 changes: patch 01/17 - added HAVE_PERF_REGS config option patch 02/17, 04/17 - regs and stack perf interface is more general now patch 06/17 - unrelated online fix for i386 compilation patch 16/17 - few namespace fixies --- Adding the post unwinding user stack backtrace using dwarf unwind via libunwind. The original work was done by Frederic. I mostly took his patches and make them compile in current kernel code plus I added some stuff here and there. The main idea is to store user registers and portion of user stack when the sample data during the record phase. Then during the report, when the data is presented, perform the actual dwarf dwarf unwind. attached patches: 01/17 perf: Unified API to record selective sets of arch registers 02/17 perf: Add ability to attach user level registers dump to sample 03/17 perf, x86: Add copy_from_user_nmi_nochk for best effort copy 04/17 perf: Factor __output_copy to be usable with specific copy function 05/17 perf: Add perf_output_skip function to skip bytes in sample 06/17 perf: Add ability to attach user stack dump to sample 07/17 perf: Add attribute to filter out callchains 08/17 perf, tool: Adding PERF_ATTR_SIZE_VER2 to the header swap check 09/17 perf, tool: Factor DSO symtab types to generic binary types 10/17 perf, tool: Add interface to read DSO image data 11/17 perf, tool: Add interface to arch registers sets 12/17 perf, tool: Add libunwind dependency for dwarf cfi unwinding 13/17 perf, tool: Support user regs and stack in sample parsing 14/17 perf, tool: Support for dwarf cfi unwinding on post processing 15/17 perf, tool: Support for dwarf mode callchain on perf record 16/17 perf, tool: Add dso data caching 17/17 perf, tool: Add dso data caching tests I tested on Fedora. There was not much gain on i386, because the binaries are compiled with frame pointers. Thought the dwarf backtrace is more accurate and unwraps calls in more details (functions that do not set the frame pointers). I could see some improvement on x86_64, where I got full backtrace where current code could got just the first address out of the instruction pointer. Example on x86_64: [dwarf] perf record -g dwarf -e syscalls:sys_enter_write date 100.00% date libc-2.14.90.so [.] __GI___libc_write | --- __GI___libc_write _IO_file_write@@GLIBC_2.2.5 new_do_write _IO_do_write@@GLIBC_2.2.5 _IO_file_overflow@@GLIBC_2.2.5 0x4022cd 0x401ee6 __libc_start_main 0x4020b9 [frame pointer] perf record -g fp -e syscalls:sys_enter_write date 100.00% date libc-2.14.90.so [.] __GI___libc_write | --- __GI___libc_write Also I tested on coreutils binaries mainly, but I could see getting wider backtraces with dwarf unwind for more complex application like firefox. Attached patches should work on both x86 and x86_64. The unwind backtrace can be interrupted by following reasons: - bug in unwind information of processed shared library - bug in unwind processing code (most likely ;) ) - insufficient dump stack size - until full syscall register storage and vdso support we could miss some related backtraces jirka --- arch/Kconfig |6 + arch/x86/Kconfig |1 + arch/x86/include/asm/perf_event.h |
[PATCH 04/17] perf: Factor __output_copy to be usable with specific copy function
From: Frederic Weisbecker fweis...@gmail.com Adding a generic way to use __output_copy function with specific copy function via DEFINE_PERF_OUTPUT_COPY macro. Using this to add new __output_copy_user function, that provides output copy from user pointers. For x86 the copy_from_user_nmi_nochk function is used and __copy_from_user_inatomic for the rest of the architectures. This new function will be used in user stack dump on sample, coming in next patches. Signed-off-by: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Jiri Olsa jo...@redhat.com --- arch/x86/include/asm/perf_event.h |2 + include/linux/perf_event.h|2 +- kernel/events/internal.h | 62 kernel/events/ring_buffer.c |4 +- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index c78f14a..ada1cab 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -257,4 +257,6 @@ static inline void perf_check_microcode(void) { } static inline void amd_pmu_disable_virt(void) { } #endif +#define arch_perf_out_copy_user copy_from_user_nmi_nochk + #endif /* _ASM_X86_PERF_EVENT_H */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 57f209d..432227b 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1303,7 +1303,7 @@ static inline bool has_branch_stack(struct perf_event *event) extern int perf_output_begin(struct perf_output_handle *handle, struct perf_event *event, unsigned int size); extern void perf_output_end(struct perf_output_handle *handle); -extern void perf_output_copy(struct perf_output_handle *handle, +extern unsigned int perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len); extern int perf_swevent_get_recursion_context(void); extern void perf_swevent_put_recursion_context(int rctx); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index b0b107f..2206a0f 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -2,6 +2,7 @@ #define _KERNEL_EVENTS_INTERNAL_H #include linux/hardirq.h +#include linux/uaccess.h /* Buffer handling */ @@ -76,30 +77,49 @@ static inline unsigned long perf_data_size(struct ring_buffer *rb) return rb-nr_pages (PAGE_SHIFT + page_order(rb)); } -static inline void -__output_copy(struct perf_output_handle *handle, - const void *buf, unsigned int len) +#define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \ +static inline unsigned int \ +func_name(struct perf_output_handle *handle, \ + const void *buf, unsigned int len)\ +{ \ + unsigned long size, written;\ + \ + do {\ + size = min_t(unsigned long, handle-size, len); \ + \ + written = memcpy_func(handle-addr, buf, size); \ + \ + len -= written; \ + handle-addr += written;\ + buf += written; \ + handle-size -= written;\ + if (!handle-size) {\ + struct ring_buffer *rb = handle-rb;\ + \ + handle-page++; \ + handle-page = rb-nr_pages - 1; \ + handle-addr = rb-data_pages[handle-page];\ + handle-size = PAGE_SIZE page_order(rb); \ + } \ + } while (len written == size); \ + \ + return len; \ +} + +static inline int memcpy_common(void *dst, const void *src, size_t n) { - do { - unsigned long size = min_t(unsigned long, handle-size, len); - - memcpy(handle-addr, buf, size); - - len -= size; - handle-addr += size; - buf += size; - handle-size -= size; - if (!handle-size) { - struct
[PATCH 03/17] perf, x86: Add copy_from_user_nmi_nochk for best effort copy
Adding copy_from_user_nmi_nochk that provides the best effort copy regardless the requesting size crossing the task boundary. This is going to be useful for stack dump we need in post DWARF CFI based unwind, where we have predefined size of the user stack to dump, and we need to store the most of the requested dump size, regardless this size is crossing the task boundary. Signed-off-by: Jiri Olsa jo...@redhat.com --- arch/x86/include/asm/uaccess.h |2 ++ arch/x86/lib/usercopy.c| 15 +++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index e1f3a17..d8d6bcd 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -562,6 +562,8 @@ struct __large_struct { unsigned long buf[100]; }; #endif /* CONFIG_X86_WP_WORKS_OK */ extern unsigned long +copy_from_user_nmi_nochk(void *to, const void __user *from, unsigned long n); +extern unsigned long copy_from_user_nmi(void *to, const void __user *from, unsigned long n); extern __must_check long strncpy_from_user(char *dst, const char __user *src, long count); diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index 4f74d94..29ca1c7 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -14,7 +14,7 @@ * best effort, GUP based copy_from_user() that is NMI-safe */ unsigned long -copy_from_user_nmi(void *to, const void __user *from, unsigned long n) +copy_from_user_nmi_nochk(void *to, const void __user *from, unsigned long n) { unsigned long offset, addr = (unsigned long)from; unsigned long size, len = 0; @@ -22,9 +22,6 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) void *map; int ret; - if (__range_not_ok(from, n, TASK_SIZE)) - return len; - do { ret = __get_user_pages_fast(addr, 1, 0, page); if (!ret) @@ -46,4 +43,14 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) return len; } +EXPORT_SYMBOL_GPL(copy_from_user_nmi_nochk); + +unsigned long +copy_from_user_nmi(void *to, const void __user *from, unsigned long n) +{ + if (__range_not_ok(from, n, TASK_SIZE) == 0) + return 0; + + return copy_from_user_nmi_nochk(to, from, n); +} EXPORT_SYMBOL_GPL(copy_from_user_nmi); -- 1.7.7.6 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 04/11] perf kvm: fix bug resolving guest kernel syms - v2
On Fri, Jul 20, 2012 at 05:25:49PM -0600, David Ahern wrote: Guest kernel symbols are not resolved despite passing the information needed to resolve them. e.g., perf kvm --guest --guestmount=/tmp/guest-mount record -a -- sleep 1 perf kvm --guest --guestmount=/tmp/guest-mount report --stdio 36.55% [guest/11399] [unknown] [g] 0x81600bc8 33.19% [guest/10474] [unknown] [g] 0xc0116e00 30.26% [guest/11094] [unknown] [g] 0x8100a288 43.69% [guest/10474] [unknown] [g] 0xc0103d90 37.38% [guest/11399] [unknown] [g] 0x81600bc8 12.24% [guest/11094] [unknown] [g] 0x810aa91d 6.69% [guest/11094] [unknown] [u] 0x7fa784d721c3 which is just pathetic. After a maddening 2 days sifting through perf minutia I found it -- id_hdr_size is not initialized for guest machines. This shows up on the report side as random garbage for the cpu and timestamp, e.g., 29816 7310572949125804849 0x1ac0 [0x50]: PERF_RECORD_MMAP ... That messes up the sample sorting such that synthesized guest maps are processed last. With this patch you get a much more helpful report: 12.11% [guest/11399] [guest.kernel.kallsyms.11399] [g] irqtime_account_process_tick 10.58% [guest/11399] [guest.kernel.kallsyms.11399] [g] run_timer_softirq 6.95% [guest/11094] [guest.kernel.kallsyms.11094] [g] printk_needs_cpu 6.50% [guest/11094] [guest.kernel.kallsyms.11094] [g] do_timer 6.45% [guest/11399] [guest.kernel.kallsyms.11399] [g] idle_balance 4.90% [guest/11094] [guest.kernel.kallsyms.11094] [g] native_read_tsc ... v2: - changed rbtree walk to use rb_first per Namhyung's suggestion Signed-off-by: David Ahern dsah...@gmail.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Ingo Molnar mi...@kernel.org Cc: Jiri Olsa jo...@redhat.com Tested-by: Jiri Olsa jo...@redhat.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 02/11] perf kvm: set name for VM process in guest machine
On Fri, Jul 20, 2012 at 05:25:47PM -0600, David Ahern wrote: COMM events are not generated in the context of a guest machine, so the thread name is never set for the VMM process. For example, the qemu-kvm name applies to the process in the host machine, not the guest machine. So, samples for guest machines are currently displayed as: 99.67% :5671 [unknown] [g] 0x81366b41 where 5671 is the pid of the VMM. With this patch the samples in the guest machine are shown as: 18.43% [guest/5671] [unknown] [g] 0x810d68b7 Tested-by: Jiri Olsa jo...@redhat.com Signed-off-by: David Ahern dsah...@gmail.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Ingo Molnar mi...@kernel.org Cc: Jiri Olsa jo...@redhat.com Cc: Namhyung Kim namhy...@kernel.org Cc: Frederic Weisbecker fweis...@gmail.com Cc: Peter Zijlstra pet...@infradead.org --- tools/perf/util/map.c | 17 - 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index a1f4e36..8668569 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -7,6 +7,7 @@ #include stdio.h #include unistd.h #include map.h +#include thread.h const char *map_type__name[MAP__NR_TYPES] = { [MAP__FUNCTION] = Functions, @@ -585,7 +586,21 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid) self-kmaps.machine = self; self-pid = pid; self-root_dir = strdup(root_dir); - return self-root_dir == NULL ? -ENOMEM : 0; + if (self-root_dir == NULL) + return -ENOMEM; + + if (pid != HOST_KERNEL_ID) { + struct thread *thread = machine__findnew_thread(self, pid); + char comm[64]; + + if (thread == NULL) + return -ENOMEM; + + snprintf(comm, sizeof(comm), [guest/%d], pid); + thread__set_comm(thread, comm); + } + + return 0; } static void dsos__delete(struct list_head *self) -- 1.7.10.1 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/11] perf kvm: guest userspace samples should not be lumped with host uspace
On Fri, Jul 20, 2012 at 05:25:48PM -0600, David Ahern wrote: e.g., perf kvm --host --guest report -i perf.data --stdio -D shows: 1 599127912065356 0x143b8 [0x48]: PERF_RECORD_SAMPLE(IP, 5): 5671/5676: 0x7fdf95a061c0 period: 1 addr: 0 ... chain: nr:2 . 0: ff80 . 1: fe00 ... thread: qemu-kvm:5671 .. dso: not found (IP, 5) means sample in guest userspace. Those samples should not be lumped into the VMM's host thread. i.e, the report output: 56.86% qemu-kvm [unknown] [u] 0x7fdf95a061c0 With this patch the output emphasizes it is a guest userspace hit: 56.86% [guest/5671] [unknown] [u] 0x7fdf95a061c0 Looking at 3 VMs (2 64-bit, 1 32-bit) with each running a CPU bound process (openssl speed), perf report currently shows: 93.84% 117726 qemu-kvm [unknown] [u] 0x7fd7dcaea8e5 which is wrong. With this patch you get: 31.50% 39258 [guest/18772] [unknown] [u] 0x7fd7dcaea8e5 31.50% 39236 [guest/11230] [unknown] [u] 0x00a57340 30.84% 39232 [guest/18395] [unknown] [u] 0x7f66f641e107 Tested-by: Jiri Olsa jo...@redhat.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 06/12] perf header: Reconstruct group relationship by parsing cmdline
On Tue, Jul 24, 2012 at 06:01:27PM +0900, Namhyung Kim wrote: In order to support the event group viewer, their group relationship is needed. Since it's not recorded explicitly anywhere in the perf.data we should parse saved cmdline and apply the result to the evlist. It is assumed that parsed entries are in a same order with the originals. I know it's fragile but hard to find other way to do it in the current condition. :( How about storing grouping details in new perf.data feature? As you said reparsing looks too fragile. jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/3] perf hists: Link hist entries before inserting to an output tree
On Wed, Dec 05, 2012 at 03:56:42PM +0900, Namhyung Kim wrote: From: Namhyung Kim namhyung@lge.com SNIP - struct rb_node *next = rb_first(hists-entries); + struct rb_root *root; + struct rb_node *next; + + if (sort__need_collapse) + root = hists-entries_collapsed; + else + root = hists-entries_in; + next = rb_first(root); while (next != NULL) { - struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); + struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in); - next = rb_next(he-rb_node); + next = rb_next(he-rb_node_in); if (!hist_entry__next_pair(he)) { - rb_erase(he-rb_node, hists-entries); + rb_erase(he-rb_node_in, root); hist_entry__free(he); } } @@ -481,6 +459,11 @@ static void hists__process(struct hists *old, struct hists *new) else hists__link(new, old); + hists__output_resort(new); + + if (show_displacement) + hists__compute_position(new); + Computing the position after hists__link screws up the position data, because we likely have new entries in. However, I wonder if anyone is actualy using displacement info..? jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/3] perf hists: Link hist entries before inserting to an output tree
On Wed, Dec 05, 2012 at 08:06:46PM +0100, Jiri Olsa wrote: On Wed, Dec 05, 2012 at 03:56:42PM +0900, Namhyung Kim wrote: From: Namhyung Kim namhyung@lge.com SNIP - struct rb_node *next = rb_first(hists-entries); + struct rb_root *root; + struct rb_node *next; + + if (sort__need_collapse) + root = hists-entries_collapsed; + else + root = hists-entries_in; + next = rb_first(root); while (next != NULL) { - struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); + struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in); - next = rb_next(he-rb_node); + next = rb_next(he-rb_node_in); if (!hist_entry__next_pair(he)) { - rb_erase(he-rb_node, hists-entries); + rb_erase(he-rb_node_in, root); hist_entry__free(he); } } @@ -481,6 +459,11 @@ static void hists__process(struct hists *old, struct hists *new) else hists__link(new, old); + hists__output_resort(new); + + if (show_displacement) + hists__compute_position(new); + Computing the position after hists__link screws up the position data, because we likely have new entries in. However, I wonder if anyone is actualy using displacement info..? hum, the point of the displacement is to show how far is the matching entry in baseline wrt report output - after hists__output_resort.. that goes in opposite way of what we try do to in here. Anyone else in favour of removing 'Displ.' column? ;-) jirka -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf diff: Removing displacement output option
On Wed, Dec 05, 2012 at 04:12:09PM -0300, Arnaldo Carvalho de Melo wrote: Em Wed, Dec 05, 2012 at 08:06:46PM +0100, Jiri Olsa escreveu: On Wed, Dec 05, 2012 at 03:56:42PM +0900, Namhyung Kim wrote: From: Namhyung Kim namhyung@lge.com @@ -481,6 +459,11 @@ static void hists__process(struct hists *old, struct hists *new) else hists__link(new, old); + hists__output_resort(new); + + if (show_displacement) + hists__compute_position(new); + Computing the position after hists__link screws up the position data, because we likely have new entries in. However, I wonder if anyone is actualy using displacement info..? IIRC that was used long ago in the first version of 'perf diff', that is not the default, probably we can just ditch it to simplify things, can you check? you're right, it's there since vert beggining.. and now it's gone ;) attached jirka --- Removing displacement output option. It seems not very useful, because it's possible and event more convenient to lookup related symbol by name. Also the output value for both 'baseline' and 'new' data is quite apparent from diff output. And above all it complicates hist code factoring ;) Ditching out PERF_HPP__DISPL column with related output functions. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@redhat.com Cc: Namhyung Kim namhy...@kernel.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Ingo Molnar mi...@elte.hu Cc: Namhyung Kim namhy...@kernel.org Cc: Paul Mackerras pau...@samba.org Cc: Peter Zijlstra a.p.zijls...@chello.nl --- tools/perf/Documentation/perf-diff.txt | 4 tools/perf/builtin-diff.c | 29 +++-- tools/perf/ui/hist.c | 25 - tools/perf/util/hist.h | 1 - 4 files changed, 7 insertions(+), 52 deletions(-) diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index 194f37d..5b3123d 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt @@ -22,10 +22,6 @@ specified perf.data files. OPTIONS --- --M:: ---displacement:: -Show position displacement relative to baseline. - -D:: --dump-raw-trace:: Dump raw trace in ASCII. diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index d869029..b2e7d39 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -23,7 +23,6 @@ static char const *input_old = perf.data.old, *input_new = perf.data; static char diff__default_sort_order[] = dso,symbol; static bool force; -static bool show_displacement; static bool show_period; static bool show_formula; static bool show_baseline_only; @@ -296,9 +295,8 @@ static void insert_hist_entry_by_name(struct rb_root *root, rb_insert_color(he-rb_node, root); } -static void hists__name_resort(struct hists *self, bool sort) +static void hists__name_resort(struct hists *self) { - unsigned long position = 1; struct rb_root tmp = RB_ROOT; struct rb_node *next = rb_first(self-entries); @@ -306,16 +304,12 @@ static void hists__name_resort(struct hists *self, bool sort) struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); next = rb_next(n-rb_node); - n-position = position++; - if (sort) { - rb_erase(n-rb_node, self-entries); - insert_hist_entry_by_name(tmp, n); - } + rb_erase(n-rb_node, self-entries); + insert_hist_entry_by_name(tmp, n); } - if (sort) - self-entries = tmp; + self-entries = tmp; } static struct perf_evsel *evsel_match(struct perf_evsel *evsel, @@ -339,12 +333,8 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name) hists__output_resort(hists); - /* -* The hists__name_resort only sets possition -* if name is false. -*/ - if (name || ((!name) show_displacement)) - hists__name_resort(hists, name); + if (name) + hists__name_resort(hists); } } @@ -549,8 +539,6 @@ static const char * const diff_usage[] = { static const struct option options[] = { OPT_INCR('v', verbose, verbose, be more verbose (show symbol address, etc)), - OPT_BOOLEAN('M', displacement, show_displacement, - Show position displacement relative to baseline), OPT_BOOLEAN('b', baseline-only, show_baseline_only, Show only items with match in baseline), OPT_CALLBACK('c', compute, compute, @@ -585,7 +573,7 @@ static const struct option options[] = { static void ui_init(void
Re: [PATCH 3/5] perf hists: Link hist entries before inserting to an output tree
On Fri, Dec 07, 2012 at 12:09:39AM +0900, Namhyung Kim wrote: From: Namhyung Kim namhyung@lge.com For matching and/or linking hist entries, they need to be sorted by given sort keys. However current hists__match/link did this on the output trees, so that the entries in the output tree need to be resort before doing it. This looks not so good since we have trees for collecting or collapsing entries before passing them to an output tree and they're already sorted by the given sort keys. Since we don't need to print anything at the time of matching/linking, we can use these internal trees directly instead of bothering with double resort on the output tree. this patch also makes diff working over collapsed entries, which was not possible before.. nice ;) outputs like: [jolsa@krava perf]$ ./perf diff -s comm # Event 'cycles:u' # # BaselineDelta Command # ... ... # 5.24% +68.96% firefox 2.34% +5.66%X 48.51% -41.53% mocp 14.98% -11.53%skype 18.01% -15.35% plugin-containe 1.03% +1.48%xchat 5.54% -4.61% gkrellm 1.41% -0.93%xterm +0.33% xmonad-x86_64-l +0.23% vim +0.07% xscreensaver 0.19% -0.14% swapper 1.00% -0.97% NetworkManager 0.28% -0.25% ssh 0.11% -0.09%sleep 0.84% -0.83% dbus-daemon 0.02% -0.01% perf 0.40% -0.40% wpa_supplicant 0.05% -0.05% gpm 0.04% -0.04%crond small nitpick below, otherwise Acked-by: Jiri Olsa jo...@redhat.com Its only user - at the time of this writing - perf diff can be easily converted to use the internal tree and can save some lines too by getting rid of unnecessary resorting codes. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 65 - tools/perf/util/hist.c| 49 +- 2 files changed, 54 insertions(+), 60 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index b2e7d39f099b..044ad99dcc90 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -275,43 +275,6 @@ static struct perf_tool tool = { return NULL;A SNIP } -static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name) +static void perf_evlist__resort_hists(struct perf_evlist *evlist) this could be called 'perf_evlist__collapse_resort' now { struct perf_evsel *evsel; list_for_each_entry(evsel, evlist-entries, node) { struct hists *hists = evsel-hists; - hists__output_resort(hists); - - if (name) - hists__name_resort(hists); + hists__collapse_resort(hists); } } SNIP -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] perf diff: Use internal rb tree for compute resort
On Fri, Dec 07, 2012 at 12:09:40AM +0900, Namhyung Kim wrote: From: Namhyung Kim namhyung@lge.com There's no reason to run hists_compute_resort() using output tree. Convert it to use internal tree so that it can remove unnecessary _output_resort. I have another patch in queue ommiting dummy entries to display number in the compute column, so we don't have confusing 'sorted' outputs like: [jolsa@krava perf]$ ./perf diff -c+delta # Event 'cycles:u' # # BaselineDelta Shared Object Symbol # ... . .. # 17.92% -17.92% libc-2.15.so [.] _IO_link_in +77.54% libc-2.15.so [.] __fprintf_chk 15.64% -15.64% libc-2.15.so [.] _dl_addr 0.08% +0.61% ld-2.15.so [.] _start 12.16% -12.16% ld-2.15.so [.] dl_main 15.39% -15.39% ld-2.15.so [.] _dl_check_map_versions 38.81% -17.04% [kernel.kallsyms] [k] page_fault just in case anyone actualy tries and wonders ;) We need following change as well, because output resort does also col width recalc. Please add it if you respin, or I can send it later. other than that: Acked-by: Jiri Olsa jo...@redhat.com thanks, jirka --- diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index f66968e..6f56f78 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -425,12 +425,15 @@ static void hists__compute_resort(struct hists *hists) hists-entries = RB_ROOT; next = rb_first(root); + hists__reset_col_len(hists); + while (next != NULL) { struct hist_entry *he; he = rb_entry(next, struct hist_entry, rb_node_in); next = rb_next(he-rb_node_in); + hists__calc_col_len(hists, he); insert_hist_entry_by_compute(hists-entries, he, compute); } } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/5] perf hists: Exchange order of comparing items when collapsing hists
On Fri, Dec 07, 2012 at 12:09:38AM +0900, Namhyung Kim wrote: From: Namhyung Kim namhyung@lge.com When comparing entries for collapsing put the given entry first, and then the iterated entry. This is not the case of hist_entry__cmp() when called if given sort keys don't require collapsing. So change the order for the sake of consistency. It will be required for matching and/or linking multiple hist entries. As discussed with Arnadlo, this change seems like changing the sort order... could you ellaborate how it is usefull in future? thanks, jirka Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c |6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 82df1b26f0d4..d4471c21ed17 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -285,7 +285,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, parent = *p; he = rb_entry(parent, struct hist_entry, rb_node_in); - cmp = hist_entry__cmp(entry, he); + cmp = hist_entry__cmp(he, entry); if (!cmp) { he_stat__add_period(he-stat, period); @@ -729,7 +729,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, parent = *p; he = rb_entry(parent, struct hist_entry, rb_node); - cmp = hist_entry__cmp(pair, he); + cmp = hist_entry__cmp(he, pair); if (!cmp) goto out; @@ -759,7 +759,7 @@ static struct hist_entry *hists__find_entry(struct hists *hists, while (n) { struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node); - int64_t cmp = hist_entry__cmp(he, iter); + int64_t cmp = hist_entry__cmp(iter, he); if (cmp 0) n = n-rb_left; -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/5] perf hists: Exchange order of comparing items when collapsing hists
On Fri, Dec 07, 2012 at 05:38:22PM +0900, Namhyung Kim wrote: Hi Arnaldo, SNIP @@ -739,6 +739,10 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, cmp = hist_entry__collapse(he, pair); + if (sort__need_collapse) + cmp = hist_entry__collapse(he, pair); + else + cmp = hist_entry__cmp(pair, he); if (!cmp) goto out; @@ -772,7 +776,12 @@ static struct hist_entry *hists__find_entry(struct hists *hists, while (n) { struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node_in); - int64_t cmp = hist_entry__collapse(iter, he); + int64_t cmp; + + if (sort__need_collapse) + cmp = hist_entry__collapse(iter, he); + else + cmp = hist_entry__cmp(he, iter); if (cmp 0) n = n-rb_left; It doesn't look good, especially hist_entry__collapse will be same as hist_entry__cmp if 'sort__need_collapse' is false. If we can make the order consistent, it'd be converted to a sigle _collapse() call without the conditional. Thanks, Namhyung I've got non matching entries in diff after applying just patch 2/5, and it's caused by missing he/iter swap in initial name resort in insert_hist_entry_by_name function. I understand that function goes away in your next patch while add_hist_entry (swap ok) being the one doing initial name resort, but still.. took me some time to figure this out ;) jirka --- diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index b2e7d39..4dda6f4 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -285,7 +285,7 @@ static void insert_hist_entry_by_name(struct rb_root *root, while (*p != NULL) { parent = *p; iter = rb_entry(parent, struct hist_entry, rb_node); - if (hist_entry__cmp(he, iter) 0) + if (hist_entry__cmp(iter, he) 0) p = (*p)-rb_left; else p = (*p)-rb_right; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/4] perf hists: Exchange order of comparing items when collapsing hists
On Mon, Dec 10, 2012 at 05:29:54PM +0900, Namhyung Kim wrote: From: Namhyung Kim namhyung@lge.com When comparing entries for collapsing put the given entry first, and then the iterated entry. This is not the case of hist_entry__cmp() when called if given sort keys don't require collapsing. So change the order for the sake of consistency. It will be required for matching and/or linking multiple hist entries. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org Acked-by: Jiri Olsa jo...@redhat.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 01/14] perf tool: Introduce perf_hpp__list for period related columns
Adding perf_hpp__list list to register and contain all period related columns the command is interested in. This way we get rid of static array holding all possible columns and enable commands to register their own columns. It'll be handy for diff command in future to process and display data for multiple files. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 21 - tools/perf/builtin-report.c| 1 + tools/perf/ui/browsers/hists.c | 18 +--- tools/perf/ui/gtk/browser.c| 28 +--- tools/perf/ui/hist.c | 96 +++--- tools/perf/ui/setup.c | 1 + tools/perf/ui/stdio/hist.c | 17 +++- tools/perf/util/hist.h | 11 - 8 files changed, 99 insertions(+), 94 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 93b852f..9fbbc01 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -597,40 +597,35 @@ static const struct option options[] = { static void ui_init(void) { - perf_hpp__init(); - - /* No overhead column. */ - perf_hpp__column_enable(PERF_HPP__OVERHEAD, false); - /* * Display baseline/delta/ratio/displacement/ * formula/periods columns. */ - perf_hpp__column_enable(PERF_HPP__BASELINE, true); + perf_hpp__column_enable(PERF_HPP__BASELINE); switch (compute) { case COMPUTE_DELTA: - perf_hpp__column_enable(PERF_HPP__DELTA, true); + perf_hpp__column_enable(PERF_HPP__DELTA); break; case COMPUTE_RATIO: - perf_hpp__column_enable(PERF_HPP__RATIO, true); + perf_hpp__column_enable(PERF_HPP__RATIO); break; case COMPUTE_WEIGHTED_DIFF: - perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true); + perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF); break; default: BUG_ON(1); }; if (show_displacement) - perf_hpp__column_enable(PERF_HPP__DISPL, true); + perf_hpp__column_enable(PERF_HPP__DISPL); if (show_formula) - perf_hpp__column_enable(PERF_HPP__FORMULA, true); + perf_hpp__column_enable(PERF_HPP__FORMULA); if (show_period) { - perf_hpp__column_enable(PERF_HPP__PERIOD, true); - perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true); + perf_hpp__column_enable(PERF_HPP__PERIOD); + perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE); } } diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index fc25100..5134acf 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -692,6 +692,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) setup_browser(true); else { use_browser = 0; + perf_hpp__column_enable(PERF_HPP__OVERHEAD); perf_hpp__init(); } diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index ccc4bd1..96fdbc8 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -587,6 +587,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us) void hist_browser__init_hpp(void) { + perf_hpp__column_enable(PERF_HPP__OVERHEAD); + perf_hpp__init(); perf_hpp__format[PERF_HPP__OVERHEAD].color = @@ -607,12 +609,13 @@ static int hist_browser__show_entry(struct hist_browser *browser, { char s[256]; double percent; - int i, printed = 0; + int printed = 0; int width = browser-b.width; char folded_sign = ' '; bool current_entry = ui_browser__is_current_entry(browser-b, row); off_t row_offset = entry-row_offset; bool first = true; + struct perf_hpp_fmt *fmt; if (current_entry) { browser-he_selection = entry; @@ -629,12 +632,11 @@ static int hist_browser__show_entry(struct hist_browser *browser, .buf= s, .size = sizeof(s), }; + int i = 0; ui_browser__gotorc(browser-b, row, 0); - for (i = 0; i PERF_HPP__MAX_INDEX; i++) { - if (!perf_hpp__format[i].cond) - continue; + perf_hpp__for_each_format(fmt) { if (!first) { slsmg_printf( ); @@ -642,10 +644,10 @@ static int hist_browser__show_entry
[PATCH 04/14] perf diff: Remove displacement from struct hist_entry_diff
Removing displacement from struct hist_entry_diff, because it's not used. Displacement is not used for sorting, so there's no reason to pre-calculate it. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/util/sort.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index b4e8c3b..a884be2 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -55,9 +55,6 @@ struct he_stat { struct hist_entry_diff { boolcomputed; - /* PERF_HPP__DISPL */ - int displacement; - /* PERF_HPP__DELTA */ double period_ratio_delta; -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 02/14] perf tool: Add struct perf_hpp_fmt into hpp callbacks
Adding 'struct perf_hpp_fmt' into hpp callbacks, so commands can access their private data. It'll be handy for diff command in future to be able to access file related data for each column. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/browsers/hists.c | 10 ++- tools/perf/ui/hist.c | 169 +++-- tools/perf/ui/stdio/hist.c | 4 +- tools/perf/util/hist.h | 10 ++- 4 files changed, 127 insertions(+), 66 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 96fdbc8..4e06ba5 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -568,8 +568,10 @@ static int hist_browser__show_callchain(struct hist_browser *browser, } #define HPP__COLOR_FN(_name, _field) \ -static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ -struct hist_entry *he) \ +static int hist_browser__hpp_color_ ## _name( \ + struct perf_hpp_fmt *fmt __maybe_unused,\ + struct perf_hpp *hpp, \ + struct hist_entry *he) \ { \ struct hists *hists = he-hists;\ double percent = 100.0 * he-stat._field / hists-stats.total_period; \ @@ -647,7 +649,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, if (fmt-color) { hpp.ptr = percent; /* It will set percent for us. See HPP__COLOR_FN above. */ - width -= fmt-color(hpp, entry); + width -= fmt-color(fmt, hpp, entry); ui_browser__set_percent_color(browser-b, percent, current_entry); @@ -661,7 +663,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, if (!current_entry || !browser-b.navkeypressed) ui_browser__set_color(browser-b, HE_COLORSET_NORMAL); } else { - width -= fmt-entry(hpp, entry); + width -= fmt-entry(fmt, hpp, entry); slsmg_printf(%s, s); } diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 0a5281f..5452960 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -6,17 +6,20 @@ /* hist period print (hpp) functions */ -static int hpp__header_overhead(struct perf_hpp *hpp) +static int hpp__header_overhead(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp) { return scnprintf(hpp-buf, hpp-size, Overhead); } -static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_overhead(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp __maybe_unused) { return 8; } -static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__color_overhead(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { struct hists *hists = he-hists; double percent = 100.0 * he-stat.period / hists-stats.total_period; @@ -24,7 +27,8 @@ static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) return percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); } -static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__entry_overhead(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { struct hists *hists = he-hists; double percent = 100.0 * he-stat.period / hists-stats.total_period; @@ -33,19 +37,22 @@ static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) return scnprintf(hpp-buf, hpp-size, fmt, percent); } -static int hpp__header_overhead_sys(struct perf_hpp *hpp) +static int hpp__header_overhead_sys(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? %s : %7s; return scnprintf(hpp-buf, hpp-size, fmt, sys); } -static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_overhead_sys(struct perf_hpp_fmt *fmt
[PATCH 09/14] perf diff: Update perf diff documentation for multiple data comparison
Updating perf diff documentation to include multiple perf data files comparison. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/Documentation/perf-diff.txt | 73 +- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index 194f37d..ab5b79e 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt @@ -3,17 +3,17 @@ perf-diff(1) NAME -perf-diff - Read two perf.data files and display the differential profile +perf-diff - Read perf.data files and display the differential profile SYNOPSIS [verse] -'perf diff' [oldfile] [newfile] +'perf diff' [baseline file] [data file1] [[data file2] ... ] DESCRIPTION --- -This command displays the performance difference amongst two perf.data files -captured via perf record. +This command displays the performance difference amongst two or more perf.data +files captured via perf record. If no parameters are passed it will assume perf.data.old and perf.data. @@ -91,6 +91,59 @@ OPTIONS --formula:: Show formula for given computation. +COMPARISON +-- +The comparison is governed by the baseline file. The baseline perf.data +file is iterated for samples. All other perf.data files specified on +the command line are searched for the baseline sample pair. If the pair +is found, specified computation is made and result is displayed. + +All samples from non-baseline perf.data files, that do not match any +baseline entry, are displayed with empty space within baseline column +and possible computation results (delta) in their related column. + +Example files samples: +- file A with samples f1, f2, f3, f4,f6 +- file B with samples f2, f4, f5 +- file C with samples f1, f2, f5 + +Example output: + x - computation takes place for pair + b - baseline sample percentage + +- perf diff A B C + + baseline/A compute/B compute/C samples + --- + bx f1 + b x x f2 + b f3 + b xf4 + b f6 + x x f5 + +- perf diff B A C + + baseline/B compute/A compute/C samples + --- + b x x f2 + b xf4 + bx f5 + x x f1 + xf3 + xf6 + +- perf diff C B A + + baseline/C compute/B compute/A samples + --- + bx f1 + b x x f2 + b xf5 + x f3 + x x f4 + x f6 + COMPARISON METHODS -- delta @@ -100,7 +153,7 @@ If specified the 'Delta' column is displayed with value 'd' computed as: d = A-period_percent - B-period_percent with: - - A/B being matching hist entry from first/second file specified + - A/B being matching hist entry from data/baseline file specified (or perf.data/perf.data.old) respectively. - period_percent being the % of the hist entry period value within @@ -113,24 +166,26 @@ If specified the 'Ratio' column is displayed with value 'r' computed as: r = A-period / B-period with: - - A/B being matching hist entry from first/second file specified + - A/B being matching hist entry from data/baseline file specified (or perf.data/perf.data.old) respectively. - period being the hist entry period value -wdiff -~ +wdiff:WEIGHT-B,WEIGHT-A +~~~ If specified the 'Weighted diff' column is displayed with value 'd' computed as: d = B-period * WEIGHT-A - A-period * WEIGHT-B - - A/B being matching hist entry from first/second file specified + - A/B being matching hist entry from data/baseline file specified (or perf.data/perf.data.old) respectively. - period being the hist entry period value - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option behind ':' separator like '-c wdiff:1,2'. +- WIEGHT-A being the weight of the data file +- WIEGHT-B being the weight of the baseline data file SEE ALSO -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ
[PATCH 11/14] perf diff: Making compute functions static
All compute functions are now local to the diff command, making them static. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 24 tools/perf/util/hist.h| 6 -- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 9f4ef76..81f7529 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -233,7 +233,7 @@ static double get_period_percent(struct hist_entry *he, u64 period) return (period * 100.0) / total; } -double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair) +static double compute_delta(struct hist_entry *he, struct hist_entry *pair) { double old_percent = get_period_percent(he, he-stat.period); double new_percent = get_period_percent(pair, pair-stat.period); @@ -243,7 +243,7 @@ double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair) return pair-diff.period_ratio_delta; } -double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair) +static double compute_ratio(struct hist_entry *he, struct hist_entry *pair) { double old_period = he-stat.period ?: 1; double new_period = pair-stat.period; @@ -253,7 +253,7 @@ double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair) return pair-diff.period_ratio; } -s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair) +static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair) { u64 old_period = he-stat.period; u64 new_period = pair-stat.period; @@ -295,8 +295,8 @@ static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair, new_period, compute_wdiff_w1, old_period, compute_wdiff_w2); } -int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair, - char *buf, size_t size) +static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair, + char *buf, size_t size) { switch (compute) { case COMPUTE_DELTA: @@ -457,13 +457,13 @@ static void __hists__precompute(struct hist_entry *he) switch (compute) { case COMPUTE_DELTA: - perf_diff__compute_delta(he, pair); + compute_delta(he, pair); break; case COMPUTE_RATIO: - perf_diff__compute_ratio(he, pair); + compute_ratio(he, pair); break; case COMPUTE_WEIGHTED_DIFF: - perf_diff__compute_wdiff(he, pair); + compute_wdiff(he, pair); break; default: BUG_ON(1); @@ -834,7 +834,7 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, if (pair-diff.computed) diff = pair-diff.period_ratio_delta; else - diff = perf_diff__compute_delta(he, pair); + diff = compute_delta(he, pair); if (fabs(diff) = 0.01) scnprintf(buf, size, %+4.2F%%, diff); @@ -844,7 +844,7 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, if (pair-diff.computed) ratio = pair-diff.period_ratio; else - ratio = perf_diff__compute_ratio(he, pair); + ratio = compute_ratio(he, pair); if (ratio 0.0) scnprintf(buf, size, %14.6F, ratio); @@ -854,7 +854,7 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, if (pair-diff.computed) wdiff = pair-diff.wdiff; else - wdiff = perf_diff__compute_wdiff(he, pair); + wdiff = compute_wdiff(he, pair); if (wdiff != 0) scnprintf(buf, size, %14ld, wdiff); @@ -868,7 +868,7 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, break; case PERF_HPP_DIFF__FORMULA: - perf_diff__formula(he, pair, buf, size); + formula_fprintf(he, pair, buf, size); break; case PERF_HPP_DIFF__PERIOD: diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index d4f19eb..e00b6b9 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -225,10 +225,4 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, #endif unsigned
[PATCH 12/14] perf diff: Display data file info ahead of the diff output
Data files are referenced through the index of the file on the command line. Adding list of data files for each index to ease up navigation. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 16 1 file changed, 16 insertions(+) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 81f7529..50e1ea3 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -632,6 +632,19 @@ static void hists__process(struct hists *hists) hists__fprintf(hists, true, 0, 0, stdout); } +static void data_fprintf(void) +{ + struct diff_data *d; + int i; + + fprintf(stdout, # Data files:\n); + + for_each_data(i, d) + fprintf(stdout, # [%d] %s\n, d-idx, d-file); + + fprintf(stdout, #\n); +} + static int data_process(void) { struct perf_evlist *evlist_base = data[0].session-evlist; @@ -662,6 +675,9 @@ static int data_process(void) fprintf(stdout, %s# Event '%s'\n#\n, first ? : \n, perf_evsel__name(evsel_base)); + if (data_cnt 2) + data_fprintf(); + hists__process(evsel_base-hists); first = false; -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 14/14] perf diff: Add generic order option for compute sorting
Adding option 'o' to allow sorting based on the input file number. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/Documentation/perf-diff.txt | 4 +++ tools/perf/builtin-diff.c | 53 +++--- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index ab5b79e..1402e14 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt @@ -91,6 +91,10 @@ OPTIONS --formula:: Show formula for given computation. +-o:: +--order:: + Specify compute sorting column number. + COMPARISON -- The comparison is governed by the baseline file. The baseline perf.data diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index b801d0c..1f98786 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -65,7 +65,7 @@ static bool show_displacement; static bool show_period; static bool show_formula; static bool show_baseline_only; -static bool sort_compute; +static unsigned int sort_compute; static s64 compute_wdiff_w1; static s64 compute_wdiff_w2; @@ -191,13 +191,6 @@ static int setup_compute(const struct option *opt, const char *str, return 0; } - if (*str == '+') { - sort_compute = true; - cstr = (char *) ++str; - if (!*str) - return 0; - } - option = strchr(str, ':'); if (option) { unsigned len = option++ - str; @@ -533,31 +526,27 @@ static int64_t hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, int c) { - int i; + struct hist_entry **pairs_left = left-pairs; + struct hist_entry **pairs_right = right-pairs; + struct hist_entry *p_right, *p_left; + static int64_t cmp; - for (i = 0; i data_cnt; i++) { - struct hist_entry **pairs_left = left-pairs; - struct hist_entry **pairs_right = right-pairs; - struct hist_entry *p_right, *p_left; - static int64_t cmp; + if (!pairs_left || !pairs_right) + return pairs_left ? -1 : 1; - if (!pairs_left || !pairs_right) - return pairs_right - pairs_left; + p_right = pairs_right[sort_compute]; + p_left = pairs_left[sort_compute]; - p_right = pairs_right[i]; - p_left = pairs_left[i]; + if (!p_left || !p_right) + return p_left ? -1 : 1; - if (!p_left || !p_right) - return p_right - p_left; - - /* -* If we differ, we are done, otherwise continue until all -* is processed or we find a difference. -*/ - cmp = __hist_entry__cmp_compute(p_left, p_right, c); - if (cmp) - return cmp; - } + /* +* If we differ, we are done, otherwise continue until all +* is processed or we find a difference. +*/ + cmp = __hist_entry__cmp_compute(p_left, p_right, c); + if (cmp) + return cmp; return 0; } @@ -759,6 +748,7 @@ static const struct option options[] = { columns '.' is reserved.), OPT_STRING(0, symfs, symbol_conf.symfs, directory, Look for files with symbols relative to this directory), + OPT_UINTEGER('o', order, sort_compute, Specify compute sorting.), OPT_END() }; @@ -1087,6 +1077,11 @@ static int data_init(int argc, const char **argv) d-idx = i; } + if (sort_compute = (unsigned int) data_cnt) { + pr_err(Order option out of limit.\n); + return -EINVAL; + } + return 0; } -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 08/14] perf diff: Change diff command to work over multiple data files
Adding diff command the flexibility to specify multiple data files on input. If not input file is given the standard behaviour stands and diff inspects 'perf.data' and 'perf.data.old' files. Also changing the processing and output display for data files. For 'perf diff A B' command: - the current way is to iterate over B data and display A (baseline) data (symbol samples) only if found in B - this patch iterates over A (baseline) data and display B data (symbol samples) only if found in A For 'perf diff A B C' command, the diff now iterates the A (baseline) data and display B and C data (symbol samples) only if they found in A (baseline) All other standard diff command computation features (delta,ratio,wdiff) stays. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 663 ++ tools/perf/ui/hist.c | 242 - tools/perf/util/hist.c| 6 +- tools/perf/util/hist.h| 9 +- tools/perf/util/sort.h| 32 +-- 5 files changed, 560 insertions(+), 392 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 6361b55..9f4ef76 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -18,11 +18,49 @@ #include util/util.h #include stdlib.h +#include math.h -static char const *input_old = perf.data.old, - *input_new = perf.data; -static char diff__default_sort_order[] = dso,symbol; -static bool force; +/* Diff command specific HPP columns. */ +enum { + PERF_HPP_DIFF__BASELINE, + PERF_HPP_DIFF__PERIOD, + PERF_HPP_DIFF__PERIOD_BASELINE, + PERF_HPP_DIFF__DELTA, + PERF_HPP_DIFF__RATIO, + PERF_HPP_DIFF__WEIGHTED_DIFF, + PERF_HPP_DIFF__DISPL, + PERF_HPP_DIFF__FORMULA, + + PERF_HPP_DIFF__MAX_INDEX +}; + +struct diff_data__fmt { + struct perf_hpp_fmt fmt; + int idx; + + char*header; + int header_width; +}; + +struct diff_data { + struct perf_session *session; + const char *file; + int idx; + + struct diff_data__fmtfmt[PERF_HPP_DIFF__MAX_INDEX]; +}; + +static struct diff_data *data; +static int data_cnt; + +#define for_each_data(i, d) \ + for (i = 0, d = data[0]; i data_cnt; i++, d = data[i]) + +#define for_each_data_new(i, d) \ + for (i = 1, d = data[1]; i data_cnt; i++, d = data[i]) + +static const char diff__default_sort_order[] = dso,symbol; +static bool force; static bool show_displacement; static bool show_period; static bool show_formula; @@ -39,12 +77,55 @@ enum { COMPUTE_MAX, }; +static int compute_2_hpp[COMPUTE_MAX] = { + [COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA, + [COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO, + [COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF, +}; + + const char *compute_names[COMPUTE_MAX] = { [COMPUTE_DELTA] = delta, [COMPUTE_RATIO] = ratio, [COMPUTE_WEIGHTED_DIFF] = wdiff, }; +static struct header_column { + const char *name; + int width; +} columns[PERF_HPP_DIFF__MAX_INDEX] = { + [PERF_HPP_DIFF__BASELINE] = { + .name = Baseline, + }, + [PERF_HPP_DIFF__PERIOD] = { + .name = Period, + }, + [PERF_HPP_DIFF__PERIOD_BASELINE] = { + .name = Base period, + }, + [PERF_HPP_DIFF__DELTA] = { + .name = Delta, + .width = 7, + }, + [PERF_HPP_DIFF__RATIO] = { + .name = Ratio, + .width = 14, + }, + [PERF_HPP_DIFF__WEIGHTED_DIFF] = { + .name = Weighted diff, + .width = 14, + }, + [PERF_HPP_DIFF__DISPL] = { + .name = Displ, + }, + [PERF_HPP_DIFF__FORMULA] = { + .name = Formula, + .width = 70, + } +}; + +#define MAX_COL_WIDTH 70 + static int compute; static int setup_compute_opt_wdiff(char *opt) @@ -146,7 +227,7 @@ static int setup_compute(const struct option *opt, const char *str, return -EINVAL; } -double perf_diff__period_percent(struct hist_entry *he, u64 period) +static double get_period_percent(struct hist_entry *he, u64 period) { u64 total = he-hists-stats.total_period; return (period * 100.0) / total; @@ -154,34 +235,34 @@ double perf_diff__period_percent(struct hist_entry *he, u64 period) double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair) { - double new_percent = perf_diff__period_percent(he, he
[PATCH 13/14] perf diff: Display zero calculation results
Forcing zero calculation outputs to appear in final output, so we can differ between zero output calculation result and empty space for missing pair of baseline hist_entry. Also skipping the compute and period output for dummy entries. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 24 +++- tools/perf/util/hist.c| 1 + tools/perf/util/sort.h| 3 +++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 50e1ea3..b801d0c 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -779,13 +779,15 @@ static int hpp__color_baseline(struct perf_hpp_fmt *fmt __maybe_unused, container_of(fmt, struct diff_data__fmt, fmt); char pfmt[20] = ; - if (percent) { + if (!he-dummy) { scnprintf(pfmt, 20, %%%d.2f, dfmt-header_width - 1); return percent_color_snprintf(hpp-buf, hpp-size, pfmt, percent); } else return scnprintf(hpp-buf, hpp-size, %*s, dfmt-header_width, pfmt); + + return percent_color_snprintf(hpp-buf, hpp-size, pfmt, percent); } static int hpp__entry_baseline(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp, @@ -797,7 +799,7 @@ static int hpp__entry_baseline(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp, const char *fmt = symbol_conf.field_sep ? %.2f : %6.2f%%; char buf[32] = ; - if ((percent he-pairs) || symbol_conf.field_sep) + if ((he-pairs) || symbol_conf.field_sep) return scnprintf(hpp-buf, hpp-size, fmt, percent); else return scnprintf(hpp-buf, hpp-size, %*s, @@ -828,7 +830,8 @@ hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size) { switch (idx) { case PERF_HPP_DIFF__PERIOD_BASELINE: - scnprintf(buf, size, % PRIu64, he-stat.period); + if (!he-dummy) + scnprintf(buf, size, % PRIu64, he-stat.period); break; default: @@ -852,28 +855,31 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, else diff = compute_delta(he, pair); - if (fabs(diff) = 0.01) - scnprintf(buf, size, %+4.2F%%, diff); + scnprintf(buf, size, %+4.2F%%, diff); break; case PERF_HPP_DIFF__RATIO: + if (he-dummy) + break; + if (pair-diff.computed) ratio = pair-diff.period_ratio; else ratio = compute_ratio(he, pair); - if (ratio 0.0) - scnprintf(buf, size, %14.6F, ratio); + scnprintf(buf, size, %14.6F, ratio); break; case PERF_HPP_DIFF__WEIGHTED_DIFF: + if (he-dummy) + break; + if (pair-diff.computed) wdiff = pair-diff.wdiff; else wdiff = compute_wdiff(he, pair); - if (wdiff != 0) - scnprintf(buf, size, %14ld, wdiff); + scnprintf(buf, size, %14ld, wdiff); break; case PERF_HPP_DIFF__DISPL: diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 25f94a4..531b5dc 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -745,6 +745,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, rb_link_node(he-rb_node, parent, p); rb_insert_color(he-rb_node, hists-entries); hists__inc_nr_entries(hists, he); + he-dummy = true; } out: return he; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 377b144..0e06872 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -93,6 +93,9 @@ struct hist_entry { unsigned long position; struct rb_root sorted_chain; + /* Added by hists__add_dummy_entry via hists__link */ + booldummy; + /* diff related */ union { struct hist_entry **pairs; -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 03/14] perf tool: Fix period symbol_conf.field_sep display
Currently we don't properly display hist data with symbol_conf.field_sep separator. We need to display either space or separator. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/hist.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 5452960..20a4392 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -523,17 +523,13 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, struct perf_hpp_fmt *fmt; char *start = hpp-buf; int ret; - bool first = true; if (symbol_conf.exclude_other !he-parent) return 0; perf_hpp__for_each_format(fmt) { - if (!sep || !first) { - ret = scnprintf(hpp-buf, hpp-size, %s, sep ?: ); - advance_hpp(hpp, ret); - first = false; - } + ret = scnprintf(hpp-buf, hpp-size, %s, sep ?: ); + advance_hpp(hpp, ret); if (color fmt-color) ret = fmt-color(fmt, hpp, he); -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 05/14] perf diff: Change compute methods to work with pair directly
Changing compute methods to operate over hist entry and its pair directly. This makes the code more obvious and readable, instead of all time checking for pair being != NULL. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 38 +- tools/perf/ui/hist.c | 40 +--- tools/perf/util/hist.h| 7 --- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 9fbbc01..342085a 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -146,47 +146,40 @@ static int setup_compute(const struct option *opt, const char *str, return -EINVAL; } -static double get_period_percent(struct hist_entry *he, u64 period) +double perf_diff__period_percent(struct hist_entry *he, u64 period) { u64 total = he-hists-stats.total_period; return (period * 100.0) / total; } -double perf_diff__compute_delta(struct hist_entry *he) +double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair) { - struct hist_entry *pair = hist_entry__next_pair(he); - double new_percent = get_period_percent(he, he-stat.period); - double old_percent = pair ? get_period_percent(pair, pair-stat.period) : 0.0; + double new_percent = perf_diff__period_percent(he, he-stat.period); + double old_percent = perf_diff__period_percent(pair, pair-stat.period); he-diff.period_ratio_delta = new_percent - old_percent; he-diff.computed = true; return he-diff.period_ratio_delta; } -double perf_diff__compute_ratio(struct hist_entry *he) +double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair) { - struct hist_entry *pair = hist_entry__next_pair(he); double new_period = he-stat.period; - double old_period = pair ? pair-stat.period : 0; + double old_period = pair-stat.period; he-diff.computed = true; - he-diff.period_ratio = pair ? (new_period / old_period) : 0; + he-diff.period_ratio = new_period / old_period; return he-diff.period_ratio; } -s64 perf_diff__compute_wdiff(struct hist_entry *he) +s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair) { - struct hist_entry *pair = hist_entry__next_pair(he); u64 new_period = he-stat.period; - u64 old_period = pair ? pair-stat.period : 0; + u64 old_period = pair-stat.period; he-diff.computed = true; - - if (!pair) - he-diff.wdiff = 0; - else - he-diff.wdiff = new_period * compute_wdiff_w2 - -old_period * compute_wdiff_w1; + he-diff.wdiff = new_period * compute_wdiff_w2 - +old_period * compute_wdiff_w1; return he-diff.wdiff; } @@ -385,18 +378,21 @@ static void hists__precompute(struct hists *hists) while (next != NULL) { struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); + struct hist_entry *pair = hist_entry__next_pair(he); next = rb_next(he-rb_node); + if (!pair) + continue; switch (compute) { case COMPUTE_DELTA: - perf_diff__compute_delta(he); + perf_diff__compute_delta(he, pair); break; case COMPUTE_RATIO: - perf_diff__compute_ratio(he); + perf_diff__compute_ratio(he, pair); break; case COMPUTE_WEIGHTED_DIFF: - perf_diff__compute_wdiff(he); + perf_diff__compute_wdiff(he, pair); break; default: BUG_ON(1); diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 20a4392..a64c7f9 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -314,14 +314,18 @@ static int hpp__width_delta(struct perf_hpp_fmt *fmt __maybe_unused, static int hpp__entry_delta(struct perf_hpp_fmt *_fmt __maybe_unused, struct perf_hpp *hpp, struct hist_entry *he) { + struct hist_entry *pair = hist_entry__next_pair(he); const char *fmt = symbol_conf.field_sep ? %s : %7.7s; char buf[32] = ; - double diff; + double diff = 0.0; - if (he-diff.computed) - diff = he-diff.period_ratio_delta; - else - diff = perf_diff__compute_delta(he); + if (pair) { + if (he-diff.computed
[PATCH 10/14] perf tool: Centralize default columns init in perf_hpp__init
Now when diff command is separated from other standard outputs, we can use perf_hpp__init to initialize all standard columns. Moving PERF_HPP__OVERHEAD column init back to perf_hpp__init, and removing extra enable calls. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c| 1 - tools/perf/ui/browsers/hists.c | 2 -- tools/perf/ui/gtk/browser.c| 2 -- tools/perf/ui/hist.c | 2 ++ tools/perf/ui/setup.c | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5134acf..fc25100 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -692,7 +692,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) setup_browser(true); else { use_browser = 0; - perf_hpp__column_enable(PERF_HPP__OVERHEAD); perf_hpp__init(); } diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 4e06ba5..9463280 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -589,8 +589,6 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us) void hist_browser__init_hpp(void) { - perf_hpp__column_enable(PERF_HPP__OVERHEAD); - perf_hpp__init(); perf_hpp__format[PERF_HPP__OVERHEAD].color = diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index c4aac7b..489a053 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -74,8 +74,6 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us) void perf_gtk__init_hpp(void) { - perf_hpp__column_enable(PERF_HPP__OVERHEAD); - perf_hpp__init(); perf_hpp__format[PERF_HPP__OVERHEAD].color = diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index a004f57..bec5299 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -253,6 +253,8 @@ LIST_HEAD(perf_hpp__list); void perf_hpp__init(void) { + perf_hpp__column_enable(PERF_HPP__OVERHEAD); + if (symbol_conf.show_cpu_utilization) { perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS); perf_hpp__column_enable(PERF_HPP__OVERHEAD_US); diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c index 166f13d..ebb4cc1 100644 --- a/tools/perf/ui/setup.c +++ b/tools/perf/ui/setup.c @@ -30,7 +30,6 @@ void setup_browser(bool fallback_to_pager) if (fallback_to_pager) setup_pager(); - perf_hpp__column_enable(PERF_HPP__OVERHEAD); perf_hpp__init(); break; } -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 06/14] perf diff: Change formula methods to work with pair directly
Changing formula methods to operate over hist entry and its pair directly. This makes the code more obvious and readable, instead of all time checking for pair being != NULL. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 35 +-- tools/perf/ui/hist.c | 5 - tools/perf/util/hist.h| 3 ++- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 342085a..d869029 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -184,13 +184,9 @@ s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair) return he-diff.wdiff; } -static int formula_delta(struct hist_entry *he, char *buf, size_t size) +static int formula_delta(struct hist_entry *he, struct hist_entry *pair, +char *buf, size_t size) { - struct hist_entry *pair = hist_entry__next_pair(he); - - if (!pair) - return -1; - return scnprintf(buf, size, (% PRIu64 * 100 / % PRIu64 ) - (% PRIu64 * 100 / % PRIu64 ), @@ -198,41 +194,36 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size) pair-stat.period, pair-hists-stats.total_period); } -static int formula_ratio(struct hist_entry *he, char *buf, size_t size) +static int formula_ratio(struct hist_entry *he, struct hist_entry *pair, +char *buf, size_t size) { - struct hist_entry *pair = hist_entry__next_pair(he); double new_period = he-stat.period; - double old_period = pair ? pair-stat.period : 0; - - if (!pair) - return -1; + double old_period = pair-stat.period; return scnprintf(buf, size, %.0F / %.0F, new_period, old_period); } -static int formula_wdiff(struct hist_entry *he, char *buf, size_t size) +static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair, +char *buf, size_t size) { - struct hist_entry *pair = hist_entry__next_pair(he); u64 new_period = he-stat.period; - u64 old_period = pair ? pair-stat.period : 0; - - if (!pair) - return -1; + u64 old_period = pair-stat.period; return scnprintf(buf, size, (% PRIu64 * % PRId64 ) - (% PRIu64 * % PRId64 ), new_period, compute_wdiff_w2, old_period, compute_wdiff_w1); } -int perf_diff__formula(char *buf, size_t size, struct hist_entry *he) +int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair, + char *buf, size_t size) { switch (compute) { case COMPUTE_DELTA: - return formula_delta(he, buf, size); + return formula_delta(he, pair, buf, size); case COMPUTE_RATIO: - return formula_ratio(he, buf, size); + return formula_ratio(he, pair, buf, size); case COMPUTE_WEIGHTED_DIFF: - return formula_wdiff(he, buf, size); + return formula_wdiff(he, pair, buf, size); default: BUG_ON(1); } diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index a64c7f9..d6fdb00 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -446,10 +446,13 @@ static int hpp__width_formula(struct perf_hpp_fmt *fmt __maybe_unused, static int hpp__entry_formula(struct perf_hpp_fmt *_fmt __maybe_unused, struct perf_hpp *hpp, struct hist_entry *he) { + struct hist_entry *pair = hist_entry__next_pair(he); const char *fmt = symbol_conf.field_sep ? %s : %-70s; char buf[96] = ; - perf_diff__formula(buf, sizeof(buf), he); + if (pair) + perf_diff__formula(he, pair, buf, sizeof(buf)); + return scnprintf(hpp-buf, hpp-size, fmt, buf); } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 53a1679..7f5cce8 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -231,6 +231,7 @@ unsigned int hists__sort_list_width(struct hists *self); double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair); double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair); s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair); -int perf_diff__formula(char *buf, size_t size, struct hist_entry *he); +int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair, + char *buf, size_t size); double perf_diff__period_percent(struct hist_entry *he, u64 period); #endif
[PATCH 07/14] perf diff: Add callback to hists__match/hists__link functions
It's possible different users of hists__match/hists__link will need specific processing of matching hists_entry data. Adding callback to hists__match/hists__link functions to allow that. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 11 +-- tools/perf/util/hist.c| 24 +--- tools/perf/util/hist.h| 8 ++-- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index d869029..6361b55 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -472,14 +472,21 @@ static void hists__compute_resort(struct hists *hists) hists-entries = tmp; } +static int match_cb(struct hist_entry *a, struct hist_entry *b, + void *data __maybe_unused) +{ + hist__entry_add_pair(a, b); + return 0; +} + static void hists__process(struct hists *old, struct hists *new) { - hists__match(new, old); + hists__match(new, old, match_cb, NULL); if (show_baseline_only) hists__baseline_only(new); else - hists__link(new, old); + hists__link(new, old, match_cb, NULL); if (sort_compute) { hists__precompute(new); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index cb17e2a..0c5843b 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -775,18 +775,24 @@ static struct hist_entry *hists__find_entry(struct hists *hists, /* * Look for pairs to link to the leader buckets (hist_entries): */ -void hists__match(struct hists *leader, struct hists *other) +int hists__match(struct hists *leader, struct hists *other, +hists__entry_cb cb, void *data) { struct rb_node *nd; struct hist_entry *pos, *pair; + int ret = 0; - for (nd = rb_first(leader-entries); nd; nd = rb_next(nd)) { + BUG_ON(!cb); + + for (nd = rb_first(leader-entries); nd !ret; nd = rb_next(nd)) { pos = rb_entry(nd, struct hist_entry, rb_node); pair = hists__find_entry(other, pos); if (pair) - hist__entry_add_pair(pos, pair); + ret = cb(pos, pair, data); } + + return ret; } /* @@ -794,21 +800,25 @@ void hists__match(struct hists *leader, struct hists *other) * we find them, just add a dummy entry on the leader hists, with period=0, * nr_events=0, to serve as the list header. */ -int hists__link(struct hists *leader, struct hists *other) +int hists__link(struct hists *leader, struct hists *other, + hists__entry_cb cb, void *data) { struct rb_node *nd; struct hist_entry *pos, *pair; + int ret = 0; - for (nd = rb_first(other-entries); nd; nd = rb_next(nd)) { + BUG_ON(!cb); + + for (nd = rb_first(other-entries); nd !ret; nd = rb_next(nd)) { pos = rb_entry(nd, struct hist_entry, rb_node); if (!hist_entry__has_pairs(pos)) { pair = hists__add_dummy_entry(leader, pos); if (pair == NULL) return -1; - hist__entry_add_pair(pair, pos); + ret = cb(pos, pair, data); } } - return 0; + return ret; } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 7f5cce8..eb4dc83 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -115,8 +115,12 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); void hists__reset_col_len(struct hists *hists); void hists__calc_col_len(struct hists *hists, struct hist_entry *he); -void hists__match(struct hists *leader, struct hists *other); -int hists__link(struct hists *leader, struct hists *other); +typedef int (hists__entry_cb)(struct hist_entry *a, struct hist_entry *b, + void *data); +int hists__match(struct hists *leader, struct hists *other, +hists__entry_cb cb, void *data); +int hists__link(struct hists *leader, struct hists *other, + hists__entry_cb cb, void *data); struct perf_hpp { char *buf; -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH/RFC 00/14] perf, tool: Fix endian issues
hi, adding support to display diff for more than 2 perf.data files. Sending as RFC, since the change touches lot of hists code, so I might be breaking something I missed.. still testing. Also it could colide with Namhyung changes for group report wrt patches 7 and 8, where I changed the linking of matching hists entries. The doc was updated with info about current perf diff processing. Attached patches: 01/14 perf tool: Introduce perf_hpp__list for period related columns 02/14 perf tool: Add struct perf_hpp_fmt into hpp callbacks 03/14 perf tool: Fix period symbol_conf.field_sep display 04/14 perf diff: Remove displacement from struct hist_entry_diff 05/14 perf diff: Change compute methods to work with pair directly 06/14 perf diff: Change formula methods to work with pair directly 07/14 perf diff: Add callback to hists__match/hists__link functions 08/14 perf diff: Change diff command to work over multiple data files 09/14 perf diff: Update perf diff documentation for multiple data comparison 10/14 perf tool: Centralize default columns init in perf_hpp__init 11/14 perf diff: Making compute functions static 12/14 perf diff: Display data file info ahead of the diff output 13/14 perf diff: Display zero calculation results 14/14 perf diff: Add generic order option for compute sorting Example of multiple perf diff output: $ perf diff perf.data.[123456] # Event 'cycles:u' # # Data files: # [0] perf.data.1 # [1] perf.data.2 # [2] perf.data.3 # [3] perf.data.4 # [4] perf.data.5 # [5] perf.data.6 # # Baseline/0 Delta/1 Delta/2 Delta/3 Delta/4 Delta/5 Shared Object Symbol # .. ... ... ... ... ... . . # +73.05% [kernel.kallsyms] [k] page_fault +26.16% ld-2.15.so [.] _dl_next_ld_env_entry +15.40% ld-2.15.so [.] _dl_sysdep_start 71.48% -26.52% libc-2.15.so [.] __strcmp_sse2 27.69% -1.65%-4.83% -4.68% ld-2.15.so [.] dl_main 0.82% -0.05% -0.34% -0.15% -0.13% -0.03% ld-2.15.so [.] _start +39.15% libc-2.15.so [.] error_tail +73.18% libc-2.15.so [.] __strcasecmp_l_sse2 +76.30% libc-2.15.so [.] __stpcpy_sse2 +76.46%libc-2.15.so [.] _IO_getline_info thanks, jirka Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org --- tools/perf/Documentation/perf-diff.txt | 77 -- tools/perf/builtin-diff.c | 747 ++--- tools/perf/ui/browsers/hists.c | 22 +-- tools/perf/ui/gtk/browser.c| 26 +--- tools/perf/ui/hist.c | 392 ++- tools/perf/ui/stdio/hist.c | 17 +-- tools/perf/util/hist.c | 29 ++-- tools/perf/util/hist.h | 42 ++--- tools/perf/util/sort.h | 38 ++--- 9 files changed, 855 insertions(+), 535 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/