perf tools: Add support for using symbols in address filters
Adrian Hunter
reviewercover perf tools: Add support for using symbols in address filters
Hi
Here are some patches that add support for using symbols in address filters. There are also some fixes for other things that I came across during testing.
Finally there are patches for Intel PT, mainly to fix an issue with address filters, but also these two:
perf intel-pt: Fix snapshot overlap detection decoder errors perf intel-pt: Add support for recording the max non-turbo ratio
The patches are on top of Mathieu's patches:
perf tools: adding support for address filters perf tools: new tracepoint specific function perf tools: making perf_evsel__append_filter() generic
Adrian Hunter (16):
perf record: Fix documentation 'event_sources' -> 'event_source' perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change perf script: Fix vanished idle symbols
perf record: Rename label 'out_symbol_exit'
perf record: Fix error paths
perf symbols: Add dso__last_symbol()
perf record: Add support for using symbols in address filters perf tools: Increase debug level of SDT debug messages perf intel-pt: Fix snapshot overlap detection decoder errors perf intel-pt: Add support for recording the max non-turbo ratio perf intel-pt: Fix missing error codes processing auxtrace_info perf intel-pt: Add a helper function for processing AUXTRACE_INFO perf intel-pt: Record address filter in AUXTRACE_INFO event perf intel-pt: Read address filter from AUXTRACE_INFO event perf intel-pt: Enable decoder to handle TIP.PGD with missing IP perf intel-pt: Fix decoding when there are address filters
tools/perf/Documentation/perf-record.txt | 61 +- tools/perf/arch/x86/util/intel-pt.c | 57 +- tools/perf/builtin-record.c | 32 +- tools/perf/util/auxtrace.c | 737 +++++++++++++++++++++ tools/perf/util/auxtrace.h | 54 ++ tools/perf/util/build-id.c | 4 +- tools/perf/util/event.c | 3 +- tools/perf/util/evsel_fprintf.c | 7 +- .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 30 + .../perf/util/intel-pt-decoder/intel-pt-decoder.h | 1 + tools/perf/util/intel-pt.c | 172 ++++- tools/perf/util/intel-pt.h | 4 +- tools/perf/util/probe-file.c | 2 +- tools/perf/util/symbol.c | 15 + tools/perf/util/symbol.h | 1 + 15 files changed, 1143 insertions(+), 37 deletions(-)
Regards
Adrian
Adrian Hunter
reviewerPATCH 1/16 perf record: Fix documentation 'event_sources' -> 'event_source'
Change '/sys/bus/event_sources' to the correct path which is '/sys/bus/event_source'.
--- tools/perf/Documentation/perf-record.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-record.txt +3 -3
@@ -35,15 +35,15 @@ OPTIONS - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where 'param1', 'param2', etc are defined as formats for the PMU in - /sys/bus/event_sources/devices/<pmu>/format/*. + /sys/bus/event_source/devices/<pmu>/format/*. - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/' where M, N, K are numbers (in decimal, hex, octal format). Acceptable values for each of 'config', 'config1' and 'config2' are defined by - corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/* + corresponding entries in /sys/bus/event_source/devices/<pmu>/format/* param1 and param2 are defined as formats for the PMU in: - /sys/bus/event_sources/devices/<pmu>/format/* + /sys/bus/event_source/devices/<pmu>/format/* There are also some params which are not defined in .../<pmu>/format/*. These params can be used to overload default config values per event.
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf record: Fix documentation 'event_sources' -> 'event_source'
perf record: Fix documentation 'event_sources' -> 'event_source'
Commit-ID: a9e57009dacd58052755cf58463ce41a14a01db5 Gitweb: http://git.kernel.org/tip/a9e57009dacd58052755cf58463ce41a14a01db5 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:33 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 27 Sep 2016 15:00:29 -0300
perf record: Fix documentation 'event_sources' -> 'event_source'
Change '/sys/bus/event_sources' to the correct path which is '/sys/bus/event_source'.
--- tools/perf/Documentation/perf-record.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-record.txt +3 -3
@@ -35,15 +35,15 @@ OPTIONS - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where 'param1', 'param2', etc are defined as formats for the PMU in - /sys/bus/event_sources/devices/<pmu>/format/*. + /sys/bus/event_source/devices/<pmu>/format/*. - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/' where M, N, K are numbers (in decimal, hex, octal format). Acceptable values for each of 'config', 'config1' and 'config2' are defined by - corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/* + corresponding entries in /sys/bus/event_source/devices/<pmu>/format/* param1 and param2 are defined as formats for the PMU in: - /sys/bus/event_sources/devices/<pmu>/format/* + /sys/bus/event_source/devices/<pmu>/format/* There are also some params which are not defined in .../<pmu>/format/*. These params can be used to overload default config values per event.
Adrian Hunter
reviewerPATCH 2/16 perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change
In reply to Adrian HunterPatch "perf record: Mark MAP_HUGETLB when synthesizing mmap events") breaks MMAP event synthesis. The executable name comparison will match any name if the length is zero, resulting in all the user space maps becoming anonymous. This is particularly noticeable with system-wide traces. Example:
perf record -a sleep 1 perf script --show-mmap-events
--- tools/perf/util/event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/event.c +2 -1
@@ -346,7 +346,8 @@ out:if (!strcmp (execname,"" ))strcpy (execname, anonstr); -if (!strncmp (execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) { +if (hugetlbfs_mnt_len && + !strncmp (execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {strcpy (execname, anonstr); event->mmap2.flags |=MAP_HUGETLB ; }
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change
perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change
Commit-ID: 973186ca7fe94d770a9847d7d530864de6ab638b Gitweb: http://git.kernel.org/tip/973186ca7fe94d770a9847d7d530864de6ab638b Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:34 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 28 Sep 2016 10:21:15 -0300
perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change
Patch "perf record: Mark MAP_HUGETLB when synthesizing mmap events") breaks MMAP event synthesis. The executable name comparison will match any name if the length is zero, resulting in all the user space maps becoming anonymous. This is particularly noticeable with system-wide traces. Example:
perf record -a sleep 1 perf script --show-mmap-events
Committer note:
That is not the case when, say, one has a qemu instance and libvirt actually mounts hugetlbfs. To test this I had to first umount it:
[root@jouet ~]# mount | grep hugetlbfs
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,seclabel) [root@jouet ~]#
After unmount it the error fixed by this patch manifests itself:
# perf record -a sleep 1
# perf script --show-mmap-events | grep PERF_RECORD_MMAP2 | head -5
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x557d47ed8000(0x167000) @ 0 fd:00 3146896 7362875424355726126]: r-xp //anon
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c488d000(0x4000) @ 0 fd:00 3153214 7362875424355726126]: r-xp //anon
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4a92000(0x3d000) @ 0 fd:00 3159276 7362875424355726126]: r-xp //anon
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4cd5000(0x15000) @ 0 fd:00 3153725 7362875424355726126]: r-xp //anon
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4eeb000(0x25000) @ 0 fd:00 3153260 7362875424355726126]: r-xp //anon
#Fixed version:
# perf record -a sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.419 MB perf.data (182 samples) ]
# perf script --show-mmap-events | grep PERF_RECORD_MMAP2 | head -5
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x557d47ed8000(0x167000) @ 0 fd:00 3146896 7362875424355726126]: r-xp /usr/lib/systemd/systemd
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c488d000(0x4000) @ 0 fd:00 3153214 7362875424355726126]: r-xp /usr/lib64/libuuid.so.1.3.0
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4a92000(0x3d000) @ 0 fd:00 3159276 7362875424355726126]: r-xp /usr/lib64/libblkid.so.1.1.0
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4cd5000(0x15000) @ 0 fd:00 3153725 7362875424355726126]: r-xp /usr/lib64/libz.so.1.2.8
systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4eeb000(0x25000) @ 0 fd:00 3153260 7362875424355726126]: r-xp /usr/lib64/liblzma.so.5.2.2
[root@jouet ~]#--- tools/perf/util/event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/event.c +2 -1
@@ -346,7 +346,8 @@ out:if (!strcmp (execname,"" ))strcpy (execname, anonstr); -if (!strncmp (execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) { +if (hugetlbfs_mnt_len && + !strncmp (execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {strcpy (execname, anonstr); event->mmap2.flags |=MAP_HUGETLB ; }
Adrian Hunter
reviewerPATCH 3/16 perf script: Fix vanished idle symbols
In reply to Adrian HunterPatch "perf symbols: Mark if a symbol is idle in the library" causes idle symbols to vanish from perf script output. That is because print functions suppress symbols marked as 'idle'. However, suppression of 'idle' functions is only used by 'perf top' and 'perf top' does not use the print functions. Consequently that functionality can simply be removed from the print functions.
--- tools/perf/util/evsel_fprintf.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
tools/perf/util/evsel_fprintf.c +2 -5
@@ -122,9 +122,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,if (!node)break ; -if (node->sym && node->sym->idle) - goto next; - printed +=fprintf (fp,"%-*.*s" , left_alignment, left_alignment," " );if (print_ip)
@@ -158,7 +155,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,if (!print_oneline) printed +=fprintf (fp,"\n" ); -next: +callchain_cursor_advance (cursor); } }
@@ -181,7 +178,7 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,if (cursor !=NULL ) { printed +=sample__fprintf_callchain (sample, left_alignment, print_opts, cursor, fp); - }else if (!(al->sym && al->sym->idle)) { + }else { printed +=fprintf (fp,"%-*.*s" , left_alignment, left_alignment," " );if (print_ip)
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf script: Fix vanished idle symbols
perf script: Fix vanished idle symbols
Commit-ID: e7a06a5353574cac3a34211bd4e514bb8d00d766 Gitweb: http://git.kernel.org/tip/e7a06a5353574cac3a34211bd4e514bb8d00d766 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:35 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:00 -0300
perf script: Fix vanished idle symbols
Commit 608c34de0b3d ("perf symbols: Mark if a symbol is idle in the library") causes idle symbols to vanish from perf script output. That is because print functions suppress symbols marked as 'idle'.
However, suppression of 'idle' functions is only used by 'perf top' and 'perf top' does not use the print functions. Consequently that functionality can simply be removed from the print functions.
--- tools/perf/util/evsel_fprintf.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
tools/perf/util/evsel_fprintf.c +2 -5
@@ -122,9 +122,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,if (!node)break ; -if (node->sym && node->sym->idle) - goto next; - printed +=fprintf (fp,"%-*.*s" , left_alignment, left_alignment," " );if (print_ip)
@@ -158,7 +155,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,if (!print_oneline) printed +=fprintf (fp,"\n" ); -next: +callchain_cursor_advance (cursor); } }
@@ -181,7 +178,7 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,if (cursor !=NULL ) { printed +=sample__fprintf_callchain (sample, left_alignment, print_opts, cursor, fp); - }else if (!(al->sym && al->sym->idle)) { + }else { printed +=fprintf (fp,"%-*.*s" , left_alignment, left_alignment," " );if (print_ip)
Adrian Hunter
reviewerPATCH 4/16 perf record: Rename label 'out_symbol_exit'
In reply to Adrian HunterIn preparation for fixing the error paths, rename label 'out_symbol_exit' to be 'out' because that error path can be used irrespective of whether symbols (or anything else) has been initialized.
--- tools/perf/builtin-record.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
tools/perf/builtin-record.c +5 -5
@@ -1643,7 +1643,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (rec->evlist->nr_entries ==0 &&perf_evlist__add_default (rec->evlist) <0 ) {pr_err ("Not enough memory for event selector list\n" ); - goto out_symbol_exit; + goto out; }if (rec->opts.target.tid && !rec->opts.no_inherit_set)
@@ -1663,7 +1663,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)ui__error ("%s" , errbuf); err = -saved_errno; - goto out_symbol_exit; + goto out; } err = -ENOMEM ;
@@ -1672,7 +1672,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) err =auxtrace_record__options (rec->itr, rec->evlist, &rec->opts);if (err) - goto out_symbol_exit; + goto out;/* * We take all buildids when the file contains
@@ -1684,11 +1684,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (record_opts__config (&rec->opts)) { err = -EINVAL ; - goto out_symbol_exit; + goto out; } err =__cmd_record (&record, argc, argv); -out_symbol_exit: +out:perf_evlist__delete (rec->evlist);symbol__exit ();auxtrace_record__free (rec->itr);
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf record: Rename label 'out_symbol_exit'
perf record: Rename label 'out_symbol_exit'
Commit-ID: 394c01ed8aafdf0f14fb18c6d320d8a783da243c Gitweb: http://git.kernel.org/tip/394c01ed8aafdf0f14fb18c6d320d8a783da243c Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:36 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:00 -0300
perf record: Rename label 'out_symbol_exit'
In preparation for fixing the error paths, rename label 'out_symbol_exit' to be 'out' because that error path can be used irrespective of whether symbols (or anything else) has been initialized.
--- tools/perf/builtin-record.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
tools/perf/builtin-record.c +5 -5
@@ -1643,7 +1643,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (rec->evlist->nr_entries ==0 &&perf_evlist__add_default (rec->evlist) <0 ) {pr_err ("Not enough memory for event selector list\n" ); - goto out_symbol_exit; + goto out; }if (rec->opts.target.tid && !rec->opts.no_inherit_set)
@@ -1663,7 +1663,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)ui__error ("%s" , errbuf); err = -saved_errno; - goto out_symbol_exit; + goto out; } err = -ENOMEM ;
@@ -1672,7 +1672,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) err =auxtrace_record__options (rec->itr, rec->evlist, &rec->opts);if (err) - goto out_symbol_exit; + goto out;/* * We take all buildids when the file contains
@@ -1684,11 +1684,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (record_opts__config (&rec->opts)) { err = -EINVAL ; - goto out_symbol_exit; + goto out; } err =__cmd_record (&record, argc, argv); -out_symbol_exit: +out:perf_evlist__delete (rec->evlist);symbol__exit ();auxtrace_record__free (rec->itr);
Adrian Hunter
reviewerPATCH 5/16 perf record: Fix error paths
In reply to Adrian HunterSome error paths do not tidy-up. Fix that.
--- tools/perf/builtin-record.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/perf/builtin-record.c +4 -4
@@ -1573,23 +1573,23 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (!rec->itr) { rec->itr =auxtrace_record__init (rec->evlist, &err);if (err) -return err; + goto out; } err =auxtrace_parse_snapshot_options (rec->itr, &rec->opts, rec->opts.auxtrace_snapshot_opts);if (err) -return err; + goto out;if (dry_run) -return 0 ; + goto out; err =bpf__setup_stdout (rec->evlist);if (err) {bpf__strerror_setup_stdout (rec->evlist, err, errbuf,sizeof (errbuf));pr_err ("ERROR: Setup BPF stdout failed: %s\n" , errbuf); -return err; + goto out; } err = -ENOMEM ;
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf record: Fix error paths
perf record: Fix error paths
Commit-ID: 5c01ad60b8a23f8ff59b9a5a756f07ed08f0b6d1 Gitweb: http://git.kernel.org/tip/5c01ad60b8a23f8ff59b9a5a756f07ed08f0b6d1 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:37 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:01 -0300
perf record: Fix error paths
Some error paths do not tidy-up. Fix that.
--- tools/perf/builtin-record.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/perf/builtin-record.c +4 -4
@@ -1573,23 +1573,23 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (!rec->itr) { rec->itr =auxtrace_record__init (rec->evlist, &err);if (err) -return err; + goto out; } err =auxtrace_parse_snapshot_options (rec->itr, &rec->opts, rec->opts.auxtrace_snapshot_opts);if (err) -return err; + goto out;if (dry_run) -return 0 ; + goto out; err =bpf__setup_stdout (rec->evlist);if (err) {bpf__strerror_setup_stdout (rec->evlist, err, errbuf,sizeof (errbuf));pr_err ("ERROR: Setup BPF stdout failed: %s\n" , errbuf); -return err; + goto out; } err = -ENOMEM ;
Adrian Hunter
reviewerPATCH 6/16 perf symbols: Add dso__last_symbol()
In reply to Adrian HunterAdd a function to find the last symbol in a DSO. This will be used when parsing address filters to calculate a region that includes the entire DSO.
--- tools/perf/util/symbol.c | 15 +++++++++++++++ tools/perf/util/symbol.h | 1 + 2 files changed, 16 insertions(+)
tools/perf/util/symbol.c +15 -0
@@ -345,6 +345,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)return NULL ; } +static struct symbol *symbols__last (struct rb_root *symbols) +{ +struct rb_node *n =rb_last (symbols); + +if (n) + return rb_entry(n, struct symbol, rb_node); + +return NULL ; +} +static struct symbol *symbols__next (struct symbol *sym) {struct rb_node *n =rb_next (&sym->rb_node);
@@ -466,6 +476,11 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)return symbols__first (&dso->symbols[type]); } +struct symbol *dso__last_symbol (struct dso *dso,enum map_type type) +{ +return symbols__last (&dso->symbols[type]); +} +struct symbol *dso__next_symbol (struct symbol *sym) {return symbols__next (sym);
tools/perf/util/symbol.h +1 -0
@@ -259,6 +259,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,struct symbol *symbol__next_by_name (struct symbol *sym);struct symbol *dso__first_symbol (struct dso *dso,enum map_type type); +struct symbol *dso__last_symbol (struct dso *dso,enum map_type type);struct symbol *dso__next_symbol (struct symbol *sym);enum dso_type dso__type_fd (int fd);
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf symbols: Add dso__last_symbol()
perf symbols: Add dso__last_symbol()
Commit-ID: cd67f99fe90dcf515f1c70c474b84d56b6236cbb Gitweb: http://git.kernel.org/tip/cd67f99fe90dcf515f1c70c474b84d56b6236cbb Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:38 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:01 -0300
perf symbols: Add dso__last_symbol()
Add a function to find the last symbol in a DSO. This will be used when parsing address filters to calculate a region that includes the entire DSO.
--- tools/perf/util/symbol.c | 15 +++++++++++++++ tools/perf/util/symbol.h | 1 + 2 files changed, 16 insertions(+)
tools/perf/util/symbol.c +15 -0
@@ -345,6 +345,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)return NULL ; } +static struct symbol *symbols__last (struct rb_root *symbols) +{ +struct rb_node *n =rb_last (symbols); + +if (n) + return rb_entry(n, struct symbol, rb_node); + +return NULL ; +} +static struct symbol *symbols__next (struct symbol *sym) {struct rb_node *n =rb_next (&sym->rb_node);
@@ -466,6 +476,11 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)return symbols__first (&dso->symbols[type]); } +struct symbol *dso__last_symbol (struct dso *dso,enum map_type type) +{ +return symbols__last (&dso->symbols[type]); +} +struct symbol *dso__next_symbol (struct symbol *sym) {return symbols__next (sym);
tools/perf/util/symbol.h +1 -0
@@ -259,6 +259,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,struct symbol *symbol__next_by_name (struct symbol *sym);struct symbol *dso__first_symbol (struct dso *dso,enum map_type type); +struct symbol *dso__last_symbol (struct dso *dso,enum map_type type);struct symbol *dso__next_symbol (struct symbol *sym);enum dso_type dso__type_fd (int fd);
Adrian Hunter
reviewerPATCH 7/16 perf record: Add support for using symbols in address filters
In reply to Adrian HunterSymbols come from either the DSO or /proc/kallsyms for the kernel. Details of the functionality can be found in Documentation/perf-record.txt.
--- tools/perf/Documentation/perf-record.txt | 55 ++- tools/perf/builtin-record.c | 14 +- tools/perf/util/auxtrace.c | 737 +++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 54 +++ 4 files changed, 857 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-record.txt +54 -1
@@ -89,9 +89,62 @@ OPTIONS --filter=<filter>:: Event filter. This option should follow a event selector (-e) which - selects tracepoint event(s). Multiple '--filter' options are combined + selects either tracepoint event(s) or a hardware trace PMU + (e.g. Intel PT or CoreSight). + + - tracepoint filters + + In the case of tracepoints, multiple '--filter' options are combined using '&&'. + - address filters + + A hardware trace PMU advertises its ability to accept a number of + address filters by specifying a non-zero value in + /sys/bus/event_source/devices/<pmu>/nr_addr_filters. + + Address filters have the format: + + filter|start|stop|tracestop <start> [/ <size>] [@<file name>] + + Where: + - 'filter': defines a region that will be traced. + - 'start': defines an address at which tracing will begin. + - 'stop': defines an address at which tracing will stop. + - 'tracestop': defines a region in which tracing will stop. + + <file name> is the name of the object file, <start> is the offset to the + code to trace in that file, and <size> is the size of the region to + trace. 'start' and 'stop' filters need not specify a <size>. + + If no object file is specified then the kernel is assumed, in which case + the start address must be a current kernel memory address. + + <start> can also be specified by providing the name of a symbol. If the + symbol name is not unique, it can be disambiguated by inserting #n where + 'n' selects the n'th symbol in address order. Alternately #0, #g or #G + select only a global symbol. <size> can also be specified by providing + the name of a symbol, in which case the size is calculated to the end + of that symbol. For 'filter' and 'tracestop' filters, if <size> is + omitted and <start> is a symbol, then the size is calculated to the end + of that symbol. + + If <size> is omitted and <start> is '*', then the start and size will + be calculated from the first and last symbols, i.e. to trace the whole + file. + + If symbol names (or '*') are provided, they must be surrounded by white + space. + + The filter passed to the kernel is not necessarily the same as entered. + To see the filter that is passed, use the -v option. + + The kernel may not be able to configure a trace region if it is not + within a single mapping. MMAP events (or /proc/<pid>/maps) can be + examined to determine if that is a possibility. + + Multiple filters can be separated with space or comma. + --exclude-perf:: Don't record events issued by perf itself. This option should follow a event selector (-e) which selects tracepoint event(s). It adds a
tools/perf/builtin-record.c +12 -2
@@ -1581,6 +1581,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (err) goto out; +/* +* Allow aliases to facilitate the lookup of symbols for address +* filters. Refer to auxtrace_parse_filters(). +*/ + symbol_conf.allow_aliases = true; + +symbol__init (NULL ); + + err =auxtrace_parse_filters (rec->evlist); +if (err) + goto out; +if (dry_run) goto out;
@@ -1594,8 +1606,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) err = -ENOMEM ; -symbol__init (NULL ); -if (symbol_conf.kptr_restrict)pr_warning ( "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
tools/perf/util/auxtrace.c +737 -0
755 lines not on this page · raw message
tools/perf/util/auxtrace.h +54 -0
72 lines not on this page · raw message
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf record: Add support for using symbols in address filters
perf record: Add support for using symbols in address filters
Commit-ID: 1b36c03e356936d62abbe2accaae1573d3b66f14 Gitweb: http://git.kernel.org/tip/1b36c03e356936d62abbe2accaae1573d3b66f14 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:39 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:02 -0300
perf record: Add support for using symbols in address filters
Symbols come from either the DSO or /proc/kallsyms for the kernel. Details of the functionality can be found in Documentation/perf-record.txt.
--- tools/perf/Documentation/perf-record.txt | 55 ++- tools/perf/builtin-record.c | 14 +- tools/perf/util/auxtrace.c | 737 +++++++++++++++++++++++++++++++ tools/perf/util/auxtrace.h | 54 +++ 4 files changed, 857 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-record.txt +54 -1
@@ -89,9 +89,62 @@ OPTIONS --filter=<filter>:: Event filter. This option should follow a event selector (-e) which - selects tracepoint event(s). Multiple '--filter' options are combined + selects either tracepoint event(s) or a hardware trace PMU + (e.g. Intel PT or CoreSight). + + - tracepoint filters + + In the case of tracepoints, multiple '--filter' options are combined using '&&'. + - address filters + + A hardware trace PMU advertises its ability to accept a number of + address filters by specifying a non-zero value in + /sys/bus/event_source/devices/<pmu>/nr_addr_filters. + + Address filters have the format: + + filter|start|stop|tracestop <start> [/ <size>] [@<file name>] + + Where: + - 'filter': defines a region that will be traced. + - 'start': defines an address at which tracing will begin. + - 'stop': defines an address at which tracing will stop. + - 'tracestop': defines a region in which tracing will stop. + + <file name> is the name of the object file, <start> is the offset to the + code to trace in that file, and <size> is the size of the region to + trace. 'start' and 'stop' filters need not specify a <size>. + + If no object file is specified then the kernel is assumed, in which case + the start address must be a current kernel memory address. + + <start> can also be specified by providing the name of a symbol. If the + symbol name is not unique, it can be disambiguated by inserting #n where + 'n' selects the n'th symbol in address order. Alternately #0, #g or #G + select only a global symbol. <size> can also be specified by providing + the name of a symbol, in which case the size is calculated to the end + of that symbol. For 'filter' and 'tracestop' filters, if <size> is + omitted and <start> is a symbol, then the size is calculated to the end + of that symbol. + + If <size> is omitted and <start> is '*', then the start and size will + be calculated from the first and last symbols, i.e. to trace the whole + file. + + If symbol names (or '*') are provided, they must be surrounded by white + space. + + The filter passed to the kernel is not necessarily the same as entered. + To see the filter that is passed, use the -v option. + + The kernel may not be able to configure a trace region if it is not + within a single mapping. MMAP events (or /proc/<pid>/maps) can be + examined to determine if that is a possibility. + + Multiple filters can be separated with space or comma. + --exclude-perf:: Don't record events issued by perf itself. This option should follow a event selector (-e) which selects tracepoint event(s). It adds a
tools/perf/builtin-record.c +12 -2
@@ -1581,6 +1581,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (err) goto out; +/* +* Allow aliases to facilitate the lookup of symbols for address +* filters. Refer to auxtrace_parse_filters(). +*/ + symbol_conf.allow_aliases = true; + +symbol__init (NULL ); + + err =auxtrace_parse_filters (rec->evlist); +if (err) + goto out; +if (dry_run) goto out;
@@ -1594,8 +1606,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) err = -ENOMEM ; -symbol__init (NULL ); -if (symbol_conf.kptr_restrict)pr_warning ( "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
tools/perf/util/auxtrace.c +737 -0
755 lines not on this page · raw message
tools/perf/util/auxtrace.h +54 -0
72 lines not on this page · raw message
Adrian Hunter
reviewerPATCH 8/16 perf tools: Increase debug level of SDT debug messages
In reply to Adrian HunterTwo SDT debug messages can occur for every DSO which is too noisy. Consequently, increase debug level of SDT messages.
--- tools/perf/util/build-id.c | 4 ++-- tools/perf/util/probe-file.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
tools/perf/util/build-id.c +2 -2
@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id, ret =probe_cache__scan_sdt (cache, realname);if (ret >=0 ) { -pr_debug ("Found %d SDTs in %s\n" , ret, realname); +pr_debug4 ("Found %d SDTs in %s\n" , ret, realname);if (probe_cache__commit (cache) <0 ) ret =-1 ; }
@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,/* Update SDT cache : error is just warned */ if (build_id_cache__add_sdt_cache (sbuild_id, realname) <0 ) -pr_debug ("Failed to update/scan SDT cache for %s\n" , realname); +pr_debug4 ("Failed to update/scan SDT cache for %s\n" , realname); out_free:if (!is_kallsyms)
tools/perf/util/probe-file.c +1 -1
@@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)INIT_LIST_HEAD (&sdtlist); ret =get_sdt_note_list (&sdtlist, pathname);if (ret <0 ) { -pr_debug ("Failed to get sdt note: %d\n" , ret); +pr_debug4 ("Failed to get sdt note: %d\n" , ret);return ret; }list_for_each_entry (note, &sdtlist, note_list) {
Signature · 1 line
1.9.1
Re: [PATCH 08/16] perf tools: Increase debug level of SDT debug messages
Quoted 2 lines · On Fri, 23 Sep 2016 17:38:40 +0300 Adrian Hunter <[email protected]>…
Two SDT debug messages can occur for every DSO which is too noisy. Consequently, increase debug level of SDT messages.
OK, but why "4" would you choose?
Thanks,
Quoted 45 lines
Signed-off-by Adrian Hunter <[email protected]>--- tools/perf/util/build-id.c | 4 ++-- tools/perf/util/probe-file.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)tools/perf/util/build-id.c +2
-2@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id, ret =probe_cache__scan_sdt (cache, realname);if (ret >=0 ) { -pr_debug ("Found %d SDTs in %s\n" , ret, realname); +pr_debug4 ("Found %d SDTs in %s\n" , ret, realname);if (probe_cache__commit (cache) <0 ) ret =-1 ; }@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,/* Update SDT cache : error is just warned */ if (build_id_cache__add_sdt_cache (sbuild_id, realname) <0 ) -pr_debug ("Failed to update/scan SDT cache for %s\n" , realname); +pr_debug4 ("Failed to update/scan SDT cache for %s\n" , realname); out_free:if (!is_kallsyms)tools/perf/util/probe-file.c +1
-1@@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)INIT_LIST_HEAD (&sdtlist); ret =get_sdt_note_list (&sdtlist, pathname);if (ret <0 ) { -pr_debug ("Failed to get sdt note: %d\n" , ret); +pr_debug4 ("Failed to get sdt note: %d\n" , ret);return ret; }list_for_each_entry (note, &sdtlist, note_list) {Signature · 1 line
1.9.1
Signature · 1 line
Masami Hiramatsu <[email protected]>
Adrian Hunter
reviewerRe: [PATCH 08/16] perf tools: Increase debug level of SDT debug messages
Quoted 7 lines · Masami Hiramatsu
Quoted 2 lines · On Fri, 23 Sep 2016 17:38:40 +0300 Adrian Hunter <[email protected]>…
Two SDT debug messages can occur for every DSO which is too noisy. Consequently, increase debug level of SDT messages.
OK, but why "4" would you choose?
2 is used for displaying the event attributes, so it needs to be 3 or 4. I chose 4 because of the large number of messages and that the same messages appear every time.
Quoted 50 lines
Thanks,
Quoted 45 lines
Signed-off-by Adrian Hunter <[email protected]>--- tools/perf/util/build-id.c | 4 ++-- tools/perf/util/probe-file.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)tools/perf/util/build-id.c +2
-2@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id, ret =probe_cache__scan_sdt (cache, realname);if (ret >=0 ) { -pr_debug ("Found %d SDTs in %s\n" , ret, realname); +pr_debug4 ("Found %d SDTs in %s\n" , ret, realname);if (probe_cache__commit (cache) <0 ) ret =-1 ; }@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,/* Update SDT cache : error is just warned */ if (build_id_cache__add_sdt_cache (sbuild_id, realname) <0 ) -pr_debug ("Failed to update/scan SDT cache for %s\n" , realname); +pr_debug4 ("Failed to update/scan SDT cache for %s\n" , realname); out_free:if (!is_kallsyms)tools/perf/util/probe-file.c +1
-1@@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)INIT_LIST_HEAD (&sdtlist); ret =get_sdt_note_list (&sdtlist, pathname);if (ret <0 ) { -pr_debug ("Failed to get sdt note: %d\n" , ret); +pr_debug4 ("Failed to get sdt note: %d\n" , ret);return ret; }list_for_each_entry (note, &sdtlist, note_list) {Signature · 1 line
1.9.1
Masami Hiramatsu
Acked-byRe: [PATCH 08/16] perf tools: Increase debug level of SDT debug messages
Quoted 4 lines · On Mon, 26 Sep 2016 10:27:41 +0300 Adrian Hunter <[email protected]>…
Quoted 3 lines · Masami Hiramatsu
On Fri, 23 Sep 2016 17:38:40 +0300
Adrian Hunter <[email protected]> wrote:
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
Two SDT debug messages can occur for every DSO which is too noisy. Consequently, increase debug level of SDT messages.
OK, but why "4" would you choose?
2 is used for displaying the event attributes, so it needs to be 3 or 4. I chose 4 because of the large number of messages and that the same messages appear every time.
Hmm, yes, but this message is also useful for checking user to stack on retrieving SDT or not. I think it is a time to introduce debug printk like feature to perf, because we need to control on/off depending on which subcommand we are debugging.
Anyway, at this point it is OK for me.
Quoted 52 lines
Quoted 51 lines
Thanks,
Quoted 45 lines
Signed-off-by Adrian Hunter <[email protected]>--- tools/perf/util/build-id.c | 4 ++-- tools/perf/util/probe-file.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)tools/perf/util/build-id.c +2
-2@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id, ret =probe_cache__scan_sdt (cache, realname);if (ret >=0 ) { -pr_debug ("Found %d SDTs in %s\n" , ret, realname); +pr_debug4 ("Found %d SDTs in %s\n" , ret, realname);if (probe_cache__commit (cache) <0 ) ret =-1 ; }@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,/* Update SDT cache : error is just warned */ if (build_id_cache__add_sdt_cache (sbuild_id, realname) <0 ) -pr_debug ("Failed to update/scan SDT cache for %s\n" , realname); +pr_debug4 ("Failed to update/scan SDT cache for %s\n" , realname); out_free:if (!is_kallsyms)tools/perf/util/probe-file.c +1
-1@@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)INIT_LIST_HEAD (&sdtlist); ret =get_sdt_note_list (&sdtlist, pathname);if (ret <0 ) { -pr_debug ("Failed to get sdt note: %d\n" , ret); +pr_debug4 ("Failed to get sdt note: %d\n" , ret);return ret; }list_for_each_entry (note, &sdtlist, note_list) {Signature · 1 line
1.9.1
Signature · 1 line
Masami Hiramatsu <[email protected]>
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf probe: Increase debug level of SDT debug messages
In reply to Adrian Hunterperf probe: Increase debug level of SDT debug messages
Commit-ID: f9655200ecd2d6cc13900a727150177b94ca229e Gitweb: http://git.kernel.org/tip/f9655200ecd2d6cc13900a727150177b94ca229e Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:40 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:02 -0300
perf probe: Increase debug level of SDT debug messages
Two SDT debug messages can occur for every DSO which is too noisy. Consequently, increase debug level of SDT messages.
--- tools/perf/util/build-id.c | 4 ++-- tools/perf/util/probe-file.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
tools/perf/util/build-id.c +2 -2
@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id, ret =probe_cache__scan_sdt (cache, realname);if (ret >=0 ) { -pr_debug ("Found %d SDTs in %s\n" , ret, realname); +pr_debug4 ("Found %d SDTs in %s\n" , ret, realname);if (probe_cache__commit (cache) <0 ) ret =-1 ; }
@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,/* Update SDT cache : error is just warned */ if (build_id_cache__add_sdt_cache (sbuild_id, realname) <0 ) -pr_debug ("Failed to update/scan SDT cache for %s\n" , realname); +pr_debug4 ("Failed to update/scan SDT cache for %s\n" , realname); out_free:if (!is_kallsyms)
tools/perf/util/probe-file.c +1 -1
@@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)INIT_LIST_HEAD (&sdtlist); ret =get_sdt_note_list (&sdtlist, pathname);if (ret <0 ) { -pr_debug ("Failed to get sdt note: %d\n" , ret); +pr_debug4 ("Failed to get sdt note: %d\n" , ret);return ret; }list_for_each_entry (note, &sdtlist, note_list) {
Adrian Hunter
reviewerPATCH 9/16 perf intel-pt: Fix snapshot overlap detection decoder errors
In reply to Adrian HunterFix occasional decoder errors decoding trace data collected in snapshot mode.
Snapshot mode can take successive snapshots of trace which might overlap. The decoder checks whether there is an overlap but only looks at the current and previous buffer. However buffers that do not contain synchronization (i.e. PSB) packets cannot be decoded or used for overlap checking. That means the decoder actually needs to check overlaps between the current buffer and the previous buffer that contained usable data. Make that change.
--- tools/perf/util/intel-pt.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
tools/perf/util/intel-pt.c +11 -4
@@ -241,7 +241,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) } queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; - +next: buffer =auxtrace_buffer__next (queue, buffer);if (!buffer) {if (old_buffer)
@@ -264,9 +264,6 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))return -ENOMEM ; -if (old_buffer) -auxtrace_buffer__drop_data (old_buffer); -if (buffer->use_data) { b->len = buffer->use_size; b->buf = buffer->use_data;
@@ -276,6 +273,16 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) } b->ref_timestamp = buffer->reference; +/* +* If in snapshot mode and the buffer has no usable data, get next +* buffer and again check overlap against old_buffer. +*/ +if (ptq->pt->snapshot_mode && !b->len) + goto next; + +if (old_buffer) +auxtrace_buffer__drop_data (old_buffer); +if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode && !buffer->consecutive)) { b->consecutive = false;
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt: Fix snapshot overlap detection decoder errors
perf intel-pt: Fix snapshot overlap detection decoder errors
Commit-ID: 810c398bc09b2f2dfde52a7d2483a710612c5fb8 Gitweb: http://git.kernel.org/tip/810c398bc09b2f2dfde52a7d2483a710612c5fb8 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:41 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:03 -0300
perf intel-pt: Fix snapshot overlap detection decoder errors
Fix occasional decoder errors decoding trace data collected in snapshot mode.
Snapshot mode can take successive snapshots of trace which might overlap. The decoder checks whether there is an overlap but only looks at the current and previous buffer. However buffers that do not contain synchronization (i.e. PSB) packets cannot be decoded or used for overlap checking. That means the decoder actually needs to check overlaps between the current buffer and the previous buffer that contained usable data. Make that change.
--- tools/perf/util/intel-pt.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
tools/perf/util/intel-pt.c +11 -4
@@ -241,7 +241,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) } queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; - +next: buffer =auxtrace_buffer__next (queue, buffer);if (!buffer) {if (old_buffer)
@@ -264,9 +264,6 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))return -ENOMEM ; -if (old_buffer) -auxtrace_buffer__drop_data (old_buffer); -if (buffer->use_data) { b->len = buffer->use_size; b->buf = buffer->use_data;
@@ -276,6 +273,16 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) } b->ref_timestamp = buffer->reference; +/* +* If in snapshot mode and the buffer has no usable data, get next +* buffer and again check overlap against old_buffer. +*/ +if (ptq->pt->snapshot_mode && !b->len) + goto next; + +if (old_buffer) +auxtrace_buffer__drop_data (old_buffer); +if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode && !buffer->consecutive)) { b->consecutive = false;
Adrian Hunter
reviewerPATCH 10/16 perf intel-pt: Add support for recording the max non-turbo ratio
In reply to Adrian HunterPreviously the maximum non-turbo ratio was calculated from TSC assuming a 100 MHz multiplier which is correct for current hardware supporting Intel PT. However more recent kernels also now export the value, so use that in preference to the calculated value.
--- tools/perf/arch/x86/util/intel-pt.c | 6 ++++++ tools/perf/util/intel-pt.c | 14 +++++++++++++- tools/perf/util/intel-pt.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-)
tools/perf/arch/x86/util/intel-pt.c +6 -0
@@ -302,6 +302,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,bool cap_user_time_zero = false, per_cpu_mmaps;u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d; +unsigned long max_non_turbo_ratio;int err;if (priv_size !=INTEL_PT_AUXTRACE_PRIV_SIZE )
@@ -317,6 +318,10 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,intel_pt_tsc_ctc_ratio (&tsc_ctc_ratio_n, &tsc_ctc_ratio_d); +if (perf_pmu__scan_file (intel_pt_pmu,"max_nonturbo_ratio" , +"%lu" , &max_non_turbo_ratio) !=1 ) + max_non_turbo_ratio =0 ; +if (!session->evlist->nr_mmaps)return -EINVAL ;
@@ -351,6 +356,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, auxtrace_info->priv[INTEL_PT_TSC_CTC_N ] = tsc_ctc_ratio_n; auxtrace_info->priv[INTEL_PT_TSC_CTC_D ] = tsc_ctc_ratio_d; auxtrace_info->priv[INTEL_PT_CYC_BIT ] = cyc_bit; + auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO ] = max_non_turbo_ratio;return 0 ; }
tools/perf/util/intel-pt.c +13 -1
@@ -2023,6 +2023,7 @@ static const char * const intel_pt_info_fmts[] = { [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", + [INTEL_PT_MAX_NONTURBO_RATIO] = " Max non-turbo ratio %"PRIu64"\n", };static void intel_pt_print_info (u64 *arr,int start,int finish)
@@ -2087,6 +2088,15 @@ int intel_pt_process_auxtrace_info(union perf_event *event, INTEL_PT_CYC_BIT); } +if (auxtrace_info->header.size >=sizeof (struct auxtrace_info_event ) + + (sizeof (u64) *INTEL_PT_MAX_NONTURBO_RATIO )) { + pt->max_non_turbo_ratio = + auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO ]; +intel_pt_print_info (&auxtrace_info->priv[0 ], +INTEL_PT_MAX_NONTURBO_RATIO , +INTEL_PT_MAX_NONTURBO_RATIO ); + } + pt->timeless_decoding =intel_pt_timeless_decoding (pt); pt->have_tsc =intel_pt_have_tsc (pt); pt->sampling_mode = false;
@@ -2156,7 +2166,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,if (pt->tc.time_mult) {u64 tsc_freq =intel_pt_ns_to_ticks (pt,1000000000 ); - pt->max_non_turbo_ratio = (tsc_freq +50000000 ) /100000000 ; +if (!pt->max_non_turbo_ratio) + pt->max_non_turbo_ratio = + (tsc_freq +50000000 ) /100000000 ;intel_pt_log ("TSC frequency %" PRIu64"\n" , tsc_freq);intel_pt_log ("Maximum non-turbo ratio %u\n" , pt->max_non_turbo_ratio);
tools/perf/util/intel-pt.h +1 -0
@@ -34,6 +34,7 @@ enum {INTEL_PT_TSC_CTC_N ,INTEL_PT_TSC_CTC_D ,INTEL_PT_CYC_BIT , +INTEL_PT_MAX_NONTURBO_RATIO , INTEL_PT_AUXTRACE_PRIV_MAX, };
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt: Add support for recording the max non-turbo ratio
perf intel-pt: Add support for recording the max non-turbo ratio
Commit-ID: fa8025c37454501a2df4a90ae84ff01f4aff8ba8 Gitweb: http://git.kernel.org/tip/fa8025c37454501a2df4a90ae84ff01f4aff8ba8 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:42 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:03 -0300
perf intel-pt: Add support for recording the max non-turbo ratio
Previously the maximum non-turbo ratio was calculated from TSC assuming a 100 MHz multiplier which is correct for current hardware supporting Intel PT. However more recent kernels also now export the value, so use that in preference to the calculated value.
--- tools/perf/arch/x86/util/intel-pt.c | 6 ++++++ tools/perf/util/intel-pt.c | 14 +++++++++++++- tools/perf/util/intel-pt.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-)
tools/perf/arch/x86/util/intel-pt.c +6 -0
@@ -302,6 +302,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,bool cap_user_time_zero = false, per_cpu_mmaps;u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d; +unsigned long max_non_turbo_ratio;int err;if (priv_size !=INTEL_PT_AUXTRACE_PRIV_SIZE )
@@ -317,6 +318,10 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,intel_pt_tsc_ctc_ratio (&tsc_ctc_ratio_n, &tsc_ctc_ratio_d); +if (perf_pmu__scan_file (intel_pt_pmu,"max_nonturbo_ratio" , +"%lu" , &max_non_turbo_ratio) !=1 ) + max_non_turbo_ratio =0 ; +if (!session->evlist->nr_mmaps)return -EINVAL ;
@@ -351,6 +356,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, auxtrace_info->priv[INTEL_PT_TSC_CTC_N ] = tsc_ctc_ratio_n; auxtrace_info->priv[INTEL_PT_TSC_CTC_D ] = tsc_ctc_ratio_d; auxtrace_info->priv[INTEL_PT_CYC_BIT ] = cyc_bit; + auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO ] = max_non_turbo_ratio;return 0 ; }
tools/perf/util/intel-pt.c +13 -1
@@ -2023,6 +2023,7 @@ static const char * const intel_pt_info_fmts[] = { [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", + [INTEL_PT_MAX_NONTURBO_RATIO] = " Max non-turbo ratio %"PRIu64"\n", };static void intel_pt_print_info (u64 *arr,int start,int finish)
@@ -2087,6 +2088,15 @@ int intel_pt_process_auxtrace_info(union perf_event *event, INTEL_PT_CYC_BIT); } +if (auxtrace_info->header.size >=sizeof (struct auxtrace_info_event ) + + (sizeof (u64) *INTEL_PT_MAX_NONTURBO_RATIO )) { + pt->max_non_turbo_ratio = + auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO ]; +intel_pt_print_info (&auxtrace_info->priv[0 ], +INTEL_PT_MAX_NONTURBO_RATIO , +INTEL_PT_MAX_NONTURBO_RATIO ); + } + pt->timeless_decoding =intel_pt_timeless_decoding (pt); pt->have_tsc =intel_pt_have_tsc (pt); pt->sampling_mode = false;
@@ -2156,7 +2166,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,if (pt->tc.time_mult) {u64 tsc_freq =intel_pt_ns_to_ticks (pt,1000000000 ); - pt->max_non_turbo_ratio = (tsc_freq +50000000 ) /100000000 ; +if (!pt->max_non_turbo_ratio) + pt->max_non_turbo_ratio = + (tsc_freq +50000000 ) /100000000 ;intel_pt_log ("TSC frequency %" PRIu64"\n" , tsc_freq);intel_pt_log ("Maximum non-turbo ratio %u\n" , pt->max_non_turbo_ratio);
tools/perf/util/intel-pt.h +1 -0
@@ -34,6 +34,7 @@ enum {INTEL_PT_TSC_CTC_N ,INTEL_PT_TSC_CTC_D ,INTEL_PT_CYC_BIT , +INTEL_PT_MAX_NONTURBO_RATIO , INTEL_PT_AUXTRACE_PRIV_MAX, };
Adrian Hunter
reviewerPATCH 11/16 perf intel-pt: Fix missing error codes processing auxtrace_info
In reply to Adrian HunterFix 2 places where the err variable was not being set.
--- tools/perf/util/intel-pt.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/util/intel-pt.c +2 -0
@@ -2138,11 +2138,13 @@ int intel_pt_process_auxtrace_info(union perf_event *event, pt->switch_evsel =intel_pt_find_sched_switch (session->evlist);if (!pt->switch_evsel) {pr_err ("%s: missing sched_switch event\n" , __func__); + err = -EINVAL ; goto err_delete_thread; } }else if (pt->have_sched_switch ==2 && !intel_pt_find_switch (session->evlist)) {pr_err ("%s: missing context_switch attribute flag\n" , __func__); + err = -EINVAL ; goto err_delete_thread; }
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt: Fix missing error codes processing auxtrace_info
perf intel-pt: Fix missing error codes processing auxtrace_info
Commit-ID: 4d34e10a9f9a38c611cac0deda8f91b064282747 Gitweb: http://git.kernel.org/tip/4d34e10a9f9a38c611cac0deda8f91b064282747 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:43 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:04 -0300
perf intel-pt: Fix missing error codes processing auxtrace_info
Fix 2 places where the err variable was not being set.
--- tools/perf/util/intel-pt.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/util/intel-pt.c +2 -0
@@ -2138,11 +2138,13 @@ int intel_pt_process_auxtrace_info(union perf_event *event, pt->switch_evsel =intel_pt_find_sched_switch (session->evlist);if (!pt->switch_evsel) {pr_err ("%s: missing sched_switch event\n" , __func__); + err = -EINVAL ; goto err_delete_thread; } }else if (pt->have_sched_switch ==2 && !intel_pt_find_switch (session->evlist)) {pr_err ("%s: missing context_switch attribute flag\n" , __func__); + err = -EINVAL ; goto err_delete_thread; }
Adrian Hunter
reviewerPATCH 12/16 perf intel-pt: Add a helper function for processing AUXTRACE_INFO
In reply to Adrian HunterAdd a helper function 'intel_pt_has()' to make it easier to determine which members the AUXTRACE_INFO event contains.
--- tools/perf/util/intel-pt.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
tools/perf/util/intel-pt.c +8 -4
@@ -2037,6 +2037,12 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)fprintf (stdout, intel_pt_info_fmts[i], arr[i]); } +static bool intel_pt_has (struct auxtrace_info_event *auxtrace_info,int pos) +{ +return auxtrace_info->header.size >= +sizeof (struct auxtrace_info_event ) + (sizeof (u64) * (pos +1 )); +} +int intel_pt_process_auxtrace_info (union perf_event *event,struct perf_session *session) {
@@ -2077,8 +2083,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,intel_pt_print_info (&auxtrace_info->priv[0 ],INTEL_PT_PMU_TYPE ,INTEL_PT_PER_CPU_MMAPS ); -if (auxtrace_info->header.size >=sizeof (struct auxtrace_info_event ) + - (sizeof (u64) *INTEL_PT_CYC_BIT )) { +if (intel_pt_has (auxtrace_info,INTEL_PT_CYC_BIT )) { pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT ]; pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS ]; pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N ];
@@ -2088,8 +2093,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event, INTEL_PT_CYC_BIT); } -if (auxtrace_info->header.size >=sizeof (struct auxtrace_info_event ) + - (sizeof (u64) *INTEL_PT_MAX_NONTURBO_RATIO )) { +if (intel_pt_has (auxtrace_info,INTEL_PT_MAX_NONTURBO_RATIO )) { pt->max_non_turbo_ratio = auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO ]; intel_pt_print_info(&auxtrace_info->priv[0],
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt: Add a helper function for processing AUXTRACE_INFO
perf intel-pt: Add a helper function for processing AUXTRACE_INFO
Commit-ID: 40b746a06332799786ba557fe84184428bef62fb Gitweb: http://git.kernel.org/tip/40b746a06332799786ba557fe84184428bef62fb Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:44 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:04 -0300
perf intel-pt: Add a helper function for processing AUXTRACE_INFO
Add a helper function 'intel_pt_has()' to make it easier to determine which members the AUXTRACE_INFO event contains.
--- tools/perf/util/intel-pt.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
tools/perf/util/intel-pt.c +8 -4
@@ -2037,6 +2037,12 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)fprintf (stdout, intel_pt_info_fmts[i], arr[i]); } +static bool intel_pt_has (struct auxtrace_info_event *auxtrace_info,int pos) +{ +return auxtrace_info->header.size >= +sizeof (struct auxtrace_info_event ) + (sizeof (u64) * (pos +1 )); +} +int intel_pt_process_auxtrace_info (union perf_event *event,struct perf_session *session) {
@@ -2077,8 +2083,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,intel_pt_print_info (&auxtrace_info->priv[0 ],INTEL_PT_PMU_TYPE ,INTEL_PT_PER_CPU_MMAPS ); -if (auxtrace_info->header.size >=sizeof (struct auxtrace_info_event ) + - (sizeof (u64) *INTEL_PT_CYC_BIT )) { +if (intel_pt_has (auxtrace_info,INTEL_PT_CYC_BIT )) { pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT ]; pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS ]; pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N ];
@@ -2088,8 +2093,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event, INTEL_PT_CYC_BIT); } -if (auxtrace_info->header.size >=sizeof (struct auxtrace_info_event ) + - (sizeof (u64) *INTEL_PT_MAX_NONTURBO_RATIO )) { +if (intel_pt_has (auxtrace_info,INTEL_PT_MAX_NONTURBO_RATIO )) { pt->max_non_turbo_ratio = auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO ]; intel_pt_print_info(&auxtrace_info->priv[0],
Adrian Hunter
reviewerPATCH 13/16 perf intel-pt: Record address filter in AUXTRACE_INFO event
In reply to Adrian HunterThe address filter is needed to help decode the trace, so store it in the AUXTRACE_INFO event.
--- tools/perf/arch/x86/util/intel-pt.c | 51 ++++++++++++++++++++++++++++++++++--- tools/perf/util/intel-pt.h | 3 +-- 2 files changed, 48 insertions(+), 6 deletions(-)
tools/perf/arch/x86/util/intel-pt.c +47 -4
@@ -62,6 +62,7 @@ struct intel_pt_recording {size_t snapshot_ref_buf_size;int snapshot_ref_cnt;struct intel_pt_snapshot_ref *snapshot_refs; +size_t priv_size; }; static int intel_pt_parse_terms_with_default(struct list_head *formats,
@@ -273,11 +274,37 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)return attr; } +static const char *intel_pt_find_filter (struct perf_evlist *evlist, +struct perf_pmu *intel_pt_pmu) +{ +struct perf_evsel *evsel; + +evlist__for_each_entry (evlist, evsel) { +if (evsel->attr.type == intel_pt_pmu->type) +return evsel->filter; + } + +return NULL ; +} + +static size_t intel_pt_filter_bytes (const char *filter) +{ +size_t len = filter ?strlen (filter) :0 ; + +return len ?roundup (len +1 ,8 ) :0 ; +} +static size_t -intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused , -struct perf_evlist *evlist__maybe_unused ) +intel_pt_info_priv_size (struct auxtrace_record *itr,struct perf_evlist *evlist) { -return INTEL_PT_AUXTRACE_PRIV_SIZE ; +struct intel_pt_recording *ptr = + container_of(itr, struct intel_pt_recording, itr); +const char *filter =intel_pt_find_filter (evlist, ptr->intel_pt_pmu); + + ptr->priv_size = (INTEL_PT_AUXTRACE_PRIV_MAX *sizeof (u64)) + +intel_pt_filter_bytes (filter); + +return ptr->priv_size; }static void intel_pt_tsc_ctc_ratio (u32 *n,u32 *d)
@@ -303,9 +330,12 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;unsigned long max_non_turbo_ratio; +size_t filter_str_len; +const char *filter; +u64 *info;int err; -if (priv_size !=INTEL_PT_AUXTRACE_PRIV_SIZE ) +if (priv_size != ptr->priv_size)return -EINVAL ;intel_pt_parse_terms (&intel_pt_pmu->format,"tsc" , &tsc_bit);
@@ -322,6 +352,9 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, "%lu", &max_non_turbo_ratio) != 1) max_non_turbo_ratio =0 ; + filter =intel_pt_find_filter (session->evlist, ptr->intel_pt_pmu); + filter_str_len = filter ?strlen (filter) :0 ; +if (!session->evlist->nr_mmaps)return -EINVAL ;
@@ -357,6 +390,16 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, auxtrace_info->priv[INTEL_PT_TSC_CTC_D ] = tsc_ctc_ratio_d; auxtrace_info->priv[INTEL_PT_CYC_BIT ] = cyc_bit; auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO ] = max_non_turbo_ratio; + auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN ] = filter_str_len; + + info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN ] +1 ; + +if (filter_str_len) { +size_t len =intel_pt_filter_bytes (filter); + +strncpy ((char *)info, filter, len); + info += len >>3 ; + }return 0 ; }
tools/perf/util/intel-pt.h +1 -2
@@ -35,11 +35,10 @@ enum {INTEL_PT_TSC_CTC_D ,INTEL_PT_CYC_BIT ,INTEL_PT_MAX_NONTURBO_RATIO , +INTEL_PT_FILTER_STR_LEN , INTEL_PT_AUXTRACE_PRIV_MAX, }; -#define INTEL_PT_AUXTRACE_PRIV_SIZE (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64)) -struct auxtrace_record ;struct perf_tool ;union perf_event ;
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt: Record address filter in AUXTRACE_INFO event
perf intel-pt: Record address filter in AUXTRACE_INFO event
Commit-ID: c093f308cea3eb4be3ed6e7e9ad54bf67a26abe4 Gitweb: http://git.kernel.org/tip/c093f308cea3eb4be3ed6e7e9ad54bf67a26abe4 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:45 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:05 -0300
perf intel-pt: Record address filter in AUXTRACE_INFO event
The address filter is needed to help decode the trace, so store it in the AUXTRACE_INFO event.
--- tools/perf/arch/x86/util/intel-pt.c | 51 ++++++++++++++++++++++++++++++++++--- tools/perf/util/intel-pt.h | 3 +-- 2 files changed, 48 insertions(+), 6 deletions(-)
tools/perf/arch/x86/util/intel-pt.c +47 -4
@@ -62,6 +62,7 @@ struct intel_pt_recording {size_t snapshot_ref_buf_size;int snapshot_ref_cnt;struct intel_pt_snapshot_ref *snapshot_refs; +size_t priv_size; }; static int intel_pt_parse_terms_with_default(struct list_head *formats,
@@ -273,11 +274,37 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)return attr; } +static const char *intel_pt_find_filter (struct perf_evlist *evlist, +struct perf_pmu *intel_pt_pmu) +{ +struct perf_evsel *evsel; + +evlist__for_each_entry (evlist, evsel) { +if (evsel->attr.type == intel_pt_pmu->type) +return evsel->filter; + } + +return NULL ; +} + +static size_t intel_pt_filter_bytes (const char *filter) +{ +size_t len = filter ?strlen (filter) :0 ; + +return len ?roundup (len +1 ,8 ) :0 ; +} +static size_t -intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused , -struct perf_evlist *evlist__maybe_unused ) +intel_pt_info_priv_size (struct auxtrace_record *itr,struct perf_evlist *evlist) { -return INTEL_PT_AUXTRACE_PRIV_SIZE ; +struct intel_pt_recording *ptr = + container_of(itr, struct intel_pt_recording, itr); +const char *filter =intel_pt_find_filter (evlist, ptr->intel_pt_pmu); + + ptr->priv_size = (INTEL_PT_AUXTRACE_PRIV_MAX *sizeof (u64)) + +intel_pt_filter_bytes (filter); + +return ptr->priv_size; }static void intel_pt_tsc_ctc_ratio (u32 *n,u32 *d)
@@ -303,9 +330,12 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;unsigned long max_non_turbo_ratio; +size_t filter_str_len; +const char *filter; +u64 *info;int err; -if (priv_size !=INTEL_PT_AUXTRACE_PRIV_SIZE ) +if (priv_size != ptr->priv_size)return -EINVAL ;intel_pt_parse_terms (&intel_pt_pmu->format,"tsc" , &tsc_bit);
@@ -322,6 +352,9 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, "%lu", &max_non_turbo_ratio) != 1) max_non_turbo_ratio =0 ; + filter =intel_pt_find_filter (session->evlist, ptr->intel_pt_pmu); + filter_str_len = filter ?strlen (filter) :0 ; +if (!session->evlist->nr_mmaps)return -EINVAL ;
@@ -357,6 +390,16 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, auxtrace_info->priv[INTEL_PT_TSC_CTC_D ] = tsc_ctc_ratio_d; auxtrace_info->priv[INTEL_PT_CYC_BIT ] = cyc_bit; auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO ] = max_non_turbo_ratio; + auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN ] = filter_str_len; + + info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN ] +1 ; + +if (filter_str_len) { +size_t len =intel_pt_filter_bytes (filter); + +strncpy ((char *)info, filter, len); + info += len >>3 ; + }return 0 ; }
tools/perf/util/intel-pt.h +1 -2
@@ -35,11 +35,10 @@ enum {INTEL_PT_TSC_CTC_D ,INTEL_PT_CYC_BIT ,INTEL_PT_MAX_NONTURBO_RATIO , +INTEL_PT_FILTER_STR_LEN , INTEL_PT_AUXTRACE_PRIV_MAX, }; -#define INTEL_PT_AUXTRACE_PRIV_SIZE (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64)) -struct auxtrace_record ;struct perf_tool ;union perf_event ;
Adrian Hunter
reviewerPATCH 14/16 perf intel-pt: Read address filter from AUXTRACE_INFO event
In reply to Adrian HunterRead the address filter from the AUXTRACE_INFO event in preparation for using it to assist in decoding.
--- tools/perf/util/intel-pt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
tools/perf/util/intel-pt.c +51 -0
@@ -103,6 +103,8 @@ struct intel_pt {unsigned max_non_turbo_ratio;unsigned long num_events; + +char *filter; };enum switch_state {
@@ -1774,6 +1776,7 @@ static void intel_pt_free(struct perf_session *session)intel_pt_free_events (session); session->auxtrace =NULL ;thread__put (pt->unknown_thread); +zfree (&pt->filter);free (pt); }
@@ -2024,6 +2027,7 @@ static const char * const intel_pt_info_fmts[] = { [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", [INTEL_PT_MAX_NONTURBO_RATIO] = " Max non-turbo ratio %"PRIu64"\n", + [INTEL_PT_FILTER_STR_LEN] = " Filter string len. %"PRIu64"\n", };static void intel_pt_print_info (u64 *arr,int start,int finish)
@@ -2037,6 +2041,14 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)fprintf (stdout, intel_pt_info_fmts[i], arr[i]); } +static void intel_pt_print_info_str (const char *name,const char *str) +{ +if (!dump_trace) +return ; + +fprintf (stdout," %-20s%s\n" , name, str ? str :"" ); +} +static bool intel_pt_has (struct auxtrace_info_event *auxtrace_info,int pos) { return auxtrace_info->header.size >=
@@ -2049,6 +2061,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;size_t min_sz =sizeof (u64) *INTEL_PT_PER_CPU_MMAPS ;struct intel_pt *pt; +void *info_end; +u64 *info;int err; if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
@@ -2101,6 +2115,42 @@ int intel_pt_process_auxtrace_info(union perf_event *event, INTEL_PT_MAX_NONTURBO_RATIO); } + info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN ] +1 ; + info_end = (void *)info + auxtrace_info->header.size; + +if (intel_pt_has (auxtrace_info,INTEL_PT_FILTER_STR_LEN )) { +size_t len; + + len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN ]; +intel_pt_print_info (&auxtrace_info->priv[0 ], +INTEL_PT_FILTER_STR_LEN , +INTEL_PT_FILTER_STR_LEN ); +if (len) { +const char *filter = (const char *)info; + + len =roundup (len +1 ,8 ); + info += len >>3 ; +if ((void *)info > info_end) { +pr_err ("%s: bad filter string length\n" , __func__); + err = -EINVAL ; + goto err_free_queues; + } + pt->filter =memdup (filter, len); +if (!pt->filter) { + err = -ENOMEM ; + goto err_free_queues; + } +if (session->header.needs_swap) +mem_bswap_64 (pt->filter, len); +if (pt->filter[len -1 ]) { +pr_err ("%s: filter string not null terminated\n" , __func__); + err = -EINVAL ; + goto err_free_queues; + } + } +intel_pt_print_info_str ("Filter string" , pt->filter); + } + pt->timeless_decoding =intel_pt_timeless_decoding (pt); pt->have_tsc =intel_pt_have_tsc (pt); pt->sampling_mode = false;
@@ -2218,6 +2268,7 @@ err_free_queues:auxtrace_queues__free (&pt->queues); session->auxtrace =NULL ; err_free: +zfree (&pt->filter);free (pt);return err; }
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt: Read address filter from AUXTRACE_INFO event
perf intel-pt: Read address filter from AUXTRACE_INFO event
Commit-ID: 2b9e32c47fd3edb0373067de7a151775b0e005c2 Gitweb: http://git.kernel.org/tip/2b9e32c47fd3edb0373067de7a151775b0e005c2 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:46 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:05 -0300
perf intel-pt: Read address filter from AUXTRACE_INFO event
Read the address filter from the AUXTRACE_INFO event in preparation for using it to assist in decoding.
--- tools/perf/util/intel-pt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
tools/perf/util/intel-pt.c +51 -0
@@ -103,6 +103,8 @@ struct intel_pt {unsigned max_non_turbo_ratio;unsigned long num_events; + +char *filter; };enum switch_state {
@@ -1774,6 +1776,7 @@ static void intel_pt_free(struct perf_session *session)intel_pt_free_events (session); session->auxtrace =NULL ;thread__put (pt->unknown_thread); +zfree (&pt->filter);free (pt); }
@@ -2024,6 +2027,7 @@ static const char * const intel_pt_info_fmts[] = { [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", [INTEL_PT_MAX_NONTURBO_RATIO] = " Max non-turbo ratio %"PRIu64"\n", + [INTEL_PT_FILTER_STR_LEN] = " Filter string len. %"PRIu64"\n", };static void intel_pt_print_info (u64 *arr,int start,int finish)
@@ -2037,6 +2041,14 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)fprintf (stdout, intel_pt_info_fmts[i], arr[i]); } +static void intel_pt_print_info_str (const char *name,const char *str) +{ +if (!dump_trace) +return ; + +fprintf (stdout," %-20s%s\n" , name, str ? str :"" ); +} +static bool intel_pt_has (struct auxtrace_info_event *auxtrace_info,int pos) { return auxtrace_info->header.size >=
@@ -2049,6 +2061,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;size_t min_sz =sizeof (u64) *INTEL_PT_PER_CPU_MMAPS ;struct intel_pt *pt; +void *info_end; +u64 *info;int err; if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
@@ -2101,6 +2115,42 @@ int intel_pt_process_auxtrace_info(union perf_event *event, INTEL_PT_MAX_NONTURBO_RATIO); } + info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN ] +1 ; + info_end = (void *)info + auxtrace_info->header.size; + +if (intel_pt_has (auxtrace_info,INTEL_PT_FILTER_STR_LEN )) { +size_t len; + + len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN ]; +intel_pt_print_info (&auxtrace_info->priv[0 ], +INTEL_PT_FILTER_STR_LEN , +INTEL_PT_FILTER_STR_LEN ); +if (len) { +const char *filter = (const char *)info; + + len =roundup (len +1 ,8 ); + info += len >>3 ; +if ((void *)info > info_end) { +pr_err ("%s: bad filter string length\n" , __func__); + err = -EINVAL ; + goto err_free_queues; + } + pt->filter =memdup (filter, len); +if (!pt->filter) { + err = -ENOMEM ; + goto err_free_queues; + } +if (session->header.needs_swap) +mem_bswap_64 (pt->filter, len); +if (pt->filter[len -1 ]) { +pr_err ("%s: filter string not null terminated\n" , __func__); + err = -EINVAL ; + goto err_free_queues; + } + } +intel_pt_print_info_str ("Filter string" , pt->filter); + } + pt->timeless_decoding =intel_pt_timeless_decoding (pt); pt->have_tsc =intel_pt_have_tsc (pt); pt->sampling_mode = false;
@@ -2218,6 +2268,7 @@ err_free_queues:auxtrace_queues__free (&pt->queues); session->auxtrace =NULL ; err_free: +zfree (&pt->filter);free (pt);return err; }
Adrian Hunter
reviewerPATCH 15/16 perf intel-pt: Enable decoder to handle TIP.PGD with missing IP
In reply to Adrian HunterWhen address filters are used, the decoder must detect the end of a filter region (or a branch into a tracestop region) by matching Packet Generation Disabled (TIP.PGD) packets against the object code using the IP given in the packet. However, due to errata SKL014 "Intel PT TIP.PGD May Not Have Target IP Payload", that IP may not be present.
Enable the decoder to handle that by adding a new callback function 'pgd_ip()' which indicates whether the IP is not traced, in which case that is the point where the trace was disabled.
--- .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 30 ++++++++++++++++++++++ .../perf/util/intel-pt-decoder/intel-pt-decoder.h | 1 + 2 files changed, 31 insertions(+)
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +30 -0
@@ -80,6 +80,7 @@ struct intel_pt_decoder {int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,uint64_t *insn_cnt_ptr,uint64_t *ip,uint64_t to_ip,uint64_t max_insn_cnt,void *data); +bool (*pgd_ip)(uint64_t ip,void *data);void *data;struct intel_pt_state state;const unsigned char *buf;
@@ -186,6 +187,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) decoder->get_trace = params->get_trace; decoder->walk_insn = params->walk_insn; + decoder->pgd_ip = params->pgd_ip; decoder->data = params->data; decoder->return_compression = params->return_compression;
@@ -1008,6 +1010,19 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)int err; err =intel_pt_walk_insn (decoder, &intel_pt_insn,0 ); +if (err ==INTEL_PT_RETURN && + decoder->pgd_ip && + decoder->pkt_state ==INTEL_PT_STATE_TIP_PGD && + (decoder->state.type &INTEL_PT_BRANCH ) && + decoder->pgd_ip (decoder->state.to_ip, decoder->data)) { +/* Unconditional branch leaving filter region */ + decoder->no_progress =0 ; + decoder->pge = false; + decoder->continuous_period = false; + decoder->pkt_state =INTEL_PT_STATE_IN_SYNC ; + decoder->state.to_ip =0 ; +return 0 ; + }if (err ==INTEL_PT_RETURN )return 0 ;if (err)
@@ -1036,6 +1051,21 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder) }if (intel_pt_insn.branch ==INTEL_PT_BR_CONDITIONAL ) { +uint64_t to_ip = decoder->ip + intel_pt_insn.length + + intel_pt_insn.rel; + +if (decoder->pgd_ip && + decoder->pkt_state ==INTEL_PT_STATE_TIP_PGD && + decoder->pgd_ip (to_ip, decoder->data)) { +/* Conditional branch leaving filter region */ + decoder->pge = false; + decoder->continuous_period = false; + decoder->pkt_state =INTEL_PT_STATE_IN_SYNC ; + decoder->ip = to_ip; + decoder->state.from_ip = decoder->ip; + decoder->state.to_ip =0 ; +return 0 ; + }intel_pt_log_at ("ERROR: Conditional branch when expecting indirect branch" , decoder->ip); decoder->pkt_state =INTEL_PT_STATE_ERR_RESYNC ;
tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +1 -0
@@ -83,6 +83,7 @@ struct intel_pt_params {int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,uint64_t *insn_cnt_ptr,uint64_t *ip,uint64_t to_ip,uint64_t max_insn_cnt,void *data); +bool (*pgd_ip)(uint64_t ip,void *data);void *data;bool return_compression;uint64_t period;
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt: Enable decoder to handle TIP.PGD with missing IP
perf intel-pt: Enable decoder to handle TIP.PGD with missing IP
Commit-ID: 9f1d122b528ef3ffcef1bdcf6a3dddf9450a864e Gitweb: http://git.kernel.org/tip/9f1d122b528ef3ffcef1bdcf6a3dddf9450a864e Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:47 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:06 -0300
perf intel-pt: Enable decoder to handle TIP.PGD with missing IP
When address filters are used, the decoder must detect the end of a filter region (or a branch into a tracestop region) by matching Packet Generation Disabled (TIP.PGD) packets against the object code using the IP given in the packet. However, due to errata SKL014 "Intel PT TIP.PGD May Not Have Target IP Payload", that IP may not be present.
Enable the decoder to handle that by adding a new callback function 'pgd_ip()' which indicates whether the IP is not traced, in which case that is the point where the trace was disabled.
--- .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 30 ++++++++++++++++++++++ .../perf/util/intel-pt-decoder/intel-pt-decoder.h | 1 + 2 files changed, 31 insertions(+)
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +30 -0
@@ -80,6 +80,7 @@ struct intel_pt_decoder {int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,uint64_t *insn_cnt_ptr,uint64_t *ip,uint64_t to_ip,uint64_t max_insn_cnt,void *data); +bool (*pgd_ip)(uint64_t ip,void *data);void *data;struct intel_pt_state state;const unsigned char *buf;
@@ -186,6 +187,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) decoder->get_trace = params->get_trace; decoder->walk_insn = params->walk_insn; + decoder->pgd_ip = params->pgd_ip; decoder->data = params->data; decoder->return_compression = params->return_compression;
@@ -1008,6 +1010,19 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)int err; err =intel_pt_walk_insn (decoder, &intel_pt_insn,0 ); +if (err ==INTEL_PT_RETURN && + decoder->pgd_ip && + decoder->pkt_state ==INTEL_PT_STATE_TIP_PGD && + (decoder->state.type &INTEL_PT_BRANCH ) && + decoder->pgd_ip (decoder->state.to_ip, decoder->data)) { +/* Unconditional branch leaving filter region */ + decoder->no_progress =0 ; + decoder->pge = false; + decoder->continuous_period = false; + decoder->pkt_state =INTEL_PT_STATE_IN_SYNC ; + decoder->state.to_ip =0 ; +return 0 ; + }if (err ==INTEL_PT_RETURN )return 0 ;if (err)
@@ -1036,6 +1051,21 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder) }if (intel_pt_insn.branch ==INTEL_PT_BR_CONDITIONAL ) { +uint64_t to_ip = decoder->ip + intel_pt_insn.length + + intel_pt_insn.rel; + +if (decoder->pgd_ip && + decoder->pkt_state ==INTEL_PT_STATE_TIP_PGD && + decoder->pgd_ip (to_ip, decoder->data)) { +/* Conditional branch leaving filter region */ + decoder->pge = false; + decoder->continuous_period = false; + decoder->pkt_state =INTEL_PT_STATE_IN_SYNC ; + decoder->ip = to_ip; + decoder->state.from_ip = decoder->ip; + decoder->state.to_ip =0 ; +return 0 ; + }intel_pt_log_at ("ERROR: Conditional branch when expecting indirect branch" , decoder->ip); decoder->pkt_state =INTEL_PT_STATE_ERR_RESYNC ;
tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +1 -0
@@ -83,6 +83,7 @@ struct intel_pt_params {int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,uint64_t *insn_cnt_ptr,uint64_t *ip,uint64_t to_ip,uint64_t max_insn_cnt,void *data); +bool (*pgd_ip)(uint64_t ip,void *data);void *data;bool return_compression;uint64_t period;
Adrian Hunter
reviewerPATCH 16/16 perf intel-pt: Fix decoding when there are address filters
In reply to Adrian HunterDue to errata SKL014 "Intel PT TIP.PGD May Not Have Target IP Payload", the Intel PT decoder needs to match address filters against TIP.PGD packets. Parse the address filters and implement the decoder's 'pgd_ip()' callback to match the IP against the filter regions.
--- tools/perf/util/intel-pt.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
tools/perf/util/intel-pt.c +82 -0
@@ -105,6 +105,7 @@ struct intel_pt {unsigned long num_events;char *filter; +struct addr_filters filts; };enum switch_state {
@@ -550,6 +551,76 @@ out_no_cache:return 0 ; } +static bool intel_pt_match_pgd_ip (struct intel_pt *pt,uint64_t ip, +uint64_t offset,const char *filename) +{ +struct addr_filter *filt; +bool have_filter = false; +bool hit_tracestop = false; +bool hit_filter = false; + +list_for_each_entry (filt, &pt->filts.head, list) { +if (filt->start) + have_filter = true; + +if ((filename && !filt->filename) || + (!filename && filt->filename) || + (filename &&strcmp (filename, filt->filename))) +continue ; + +if (!(offset >= filt->addr && offset < filt->addr + filt->size)) +continue ; + +intel_pt_log ("TIP.PGD ip %#" PRIx64" offset %#" PRIx64" in %s hit filter: %s offset %#" PRIx64" size %#" PRIx64"\n" , + ip, offset, filename ? filename :"[kernel]" , + filt->start ?"filter" :"stop" , + filt->addr, filt->size); + +if (filt->start) + hit_filter = true; +else + hit_tracestop = true; + } + +if (!hit_tracestop && !hit_filter) +intel_pt_log ("TIP.PGD ip %#" PRIx64" offset %#" PRIx64" in %s is not in a filter region\n" , + ip, offset, filename ? filename :"[kernel]" ); + +return hit_tracestop || (have_filter && !hit_filter); +} + +static int __intel_pt_pgd_ip (uint64_t ip,void *data) +{ +struct intel_pt_queue *ptq = data; +struct thread *thread; +struct addr_location al; +u8 cpumode; +u64 offset; + +if (ip >= ptq->pt->kernel_start) +return intel_pt_match_pgd_ip (ptq->pt, ip, ip,NULL ); + + cpumode =PERF_RECORD_MISC_USER ; + + thread = ptq->thread; +if (!thread) +return -EINVAL ; + +thread__find_addr_map (thread, cpumode,MAP__FUNCTION , ip, &al); +if (!al.map || !al.map->dso) +return -EINVAL ; + + offset = al.map->map_ip (al.map, ip); + +return intel_pt_match_pgd_ip (ptq->pt, ip, offset, + al.map->dso->long_name); +} + +static bool intel_pt_pgd_ip (uint64_t ip,void *data) +{ +return __intel_pt_pgd_ip (ip, data) >0 ; +} +static bool intel_pt_get_config (struct intel_pt *pt,struct perf_event_attr *attr,u64 *config) {
@@ -726,6 +797,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d; +if (pt->filts.cnt >0 ) + params.pgd_ip = intel_pt_pgd_ip; +if (pt->synth_opts.instructions) {if (pt->synth_opts.period) {switch (pt->synth_opts.period_type) {
@@ -1776,6 +1850,7 @@ static void intel_pt_free(struct perf_session *session)intel_pt_free_events (session); session->auxtrace =NULL ;thread__put (pt->unknown_thread); +addr_filters__exit (&pt->filts);zfree (&pt->filter);free (pt); }
@@ -2073,6 +2148,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,if (!pt)return -ENOMEM ; +addr_filters__init (&pt->filts); +perf_config (intel_pt_perf_config, pt); err =auxtrace_queues__init (&pt->queues);
@@ -2147,6 +2224,10 @@ int intel_pt_process_auxtrace_info(union perf_event *event, err = -EINVAL ; goto err_free_queues; } + err =addr_filters__parse_bare_filter (&pt->filts, + filter); +if (err) + goto err_free_queues; }intel_pt_print_info_str ("Filter string" , pt->filter); }
@@ -2268,6 +2349,7 @@ err_free_queues:auxtrace_queues__free (&pt->queues); session->auxtrace =NULL ; err_free: +addr_filters__exit (&pt->filts);zfree (&pt->filter);free (pt);return err;
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt: Fix decoding when there are address filters
perf intel-pt: Fix decoding when there are address filters
Commit-ID: 2acee108f58045d07475516852d4282ab73904dc Gitweb: http://git.kernel.org/tip/2acee108f58045d07475516852d4282ab73904dc Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 23 Sep 2016 17:38:48 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Sep 2016 11:17:06 -0300
perf intel-pt: Fix decoding when there are address filters
Due to errata SKL014 "Intel PT TIP.PGD May Not Have Target IP Payload", the Intel PT decoder needs to match address filters against TIP.PGD packets. Parse the address filters and implement the decoder's 'pgd_ip()' callback to match the IP against the filter regions.
--- tools/perf/util/intel-pt.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
tools/perf/util/intel-pt.c +82 -0
@@ -105,6 +105,7 @@ struct intel_pt {unsigned long num_events;char *filter; +struct addr_filters filts; };enum switch_state {
@@ -550,6 +551,76 @@ out_no_cache:return 0 ; } +static bool intel_pt_match_pgd_ip (struct intel_pt *pt,uint64_t ip, +uint64_t offset,const char *filename) +{ +struct addr_filter *filt; +bool have_filter = false; +bool hit_tracestop = false; +bool hit_filter = false; + +list_for_each_entry (filt, &pt->filts.head, list) { +if (filt->start) + have_filter = true; + +if ((filename && !filt->filename) || + (!filename && filt->filename) || + (filename &&strcmp (filename, filt->filename))) +continue ; + +if (!(offset >= filt->addr && offset < filt->addr + filt->size)) +continue ; + +intel_pt_log ("TIP.PGD ip %#" PRIx64" offset %#" PRIx64" in %s hit filter: %s offset %#" PRIx64" size %#" PRIx64"\n" , + ip, offset, filename ? filename :"[kernel]" , + filt->start ?"filter" :"stop" , + filt->addr, filt->size); + +if (filt->start) + hit_filter = true; +else + hit_tracestop = true; + } + +if (!hit_tracestop && !hit_filter) +intel_pt_log ("TIP.PGD ip %#" PRIx64" offset %#" PRIx64" in %s is not in a filter region\n" , + ip, offset, filename ? filename :"[kernel]" ); + +return hit_tracestop || (have_filter && !hit_filter); +} + +static int __intel_pt_pgd_ip (uint64_t ip,void *data) +{ +struct intel_pt_queue *ptq = data; +struct thread *thread; +struct addr_location al; +u8 cpumode; +u64 offset; + +if (ip >= ptq->pt->kernel_start) +return intel_pt_match_pgd_ip (ptq->pt, ip, ip,NULL ); + + cpumode =PERF_RECORD_MISC_USER ; + + thread = ptq->thread; +if (!thread) +return -EINVAL ; + +thread__find_addr_map (thread, cpumode,MAP__FUNCTION , ip, &al); +if (!al.map || !al.map->dso) +return -EINVAL ; + + offset = al.map->map_ip (al.map, ip); + +return intel_pt_match_pgd_ip (ptq->pt, ip, offset, + al.map->dso->long_name); +} + +static bool intel_pt_pgd_ip (uint64_t ip,void *data) +{ +return __intel_pt_pgd_ip (ip, data) >0 ; +} +static bool intel_pt_get_config (struct intel_pt *pt,struct perf_event_attr *attr,u64 *config) {
@@ -726,6 +797,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d; +if (pt->filts.cnt >0 ) + params.pgd_ip = intel_pt_pgd_ip; +if (pt->synth_opts.instructions) {if (pt->synth_opts.period) {switch (pt->synth_opts.period_type) {
@@ -1776,6 +1850,7 @@ static void intel_pt_free(struct perf_session *session)intel_pt_free_events (session); session->auxtrace =NULL ;thread__put (pt->unknown_thread); +addr_filters__exit (&pt->filts);zfree (&pt->filter);free (pt); }
@@ -2073,6 +2148,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,if (!pt)return -ENOMEM ; +addr_filters__init (&pt->filts); +perf_config (intel_pt_perf_config, pt); err =auxtrace_queues__init (&pt->queues);
@@ -2147,6 +2224,10 @@ int intel_pt_process_auxtrace_info(union perf_event *event, err = -EINVAL ; goto err_free_queues; } + err =addr_filters__parse_bare_filter (&pt->filts, + filter); +if (err) + goto err_free_queues; }intel_pt_print_info_str ("Filter string" , pt->filter); }
@@ -2268,6 +2349,7 @@ err_free_queues:auxtrace_queues__free (&pt->queues); session->auxtrace =NULL ; err_free: +addr_filters__exit (&pt->filts);zfree (&pt->filter);free (pt);return err;