Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1232818 > unrolled thread
| Started by | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| First post | 2015-09-25 15:30 +0200 |
| Last post | 2015-09-29 13:20 +0200 |
| Articles | 17 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH 00/25] perf tools: minor improvements to Intel PT related stuff Adrian Hunter <adrian.hunter@intel.com> - 2015-09-25 15:30 +0200
[PATCH 01/25] perf auxtrace: Fix 'instructions' period of zero Adrian Hunter <adrian.hunter@intel.com> - 2015-09-25 15:30 +0200
Re: [PATCH 01/25] perf auxtrace: Fix 'instructions' period of zero Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-09-28 16:20 +0200
Re: [PATCH 01/25] perf auxtrace: Fix 'instructions' period of zero Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-09-28 16:20 +0200
[tip:perf/core] perf auxtrace: Fix 'instructions' period of zero tip-bot for Adrian Hunter <tipbot@zytor.com> - 2015-09-29 11:00 +0200
[PATCH 12/25] perf inject: Set branch stack feature flag when synthesizing branch stacks Adrian Hunter <adrian.hunter@intel.com> - 2015-09-25 15:30 +0200
[tip:perf/core] perf inject: Set branch stack feature flag when synthesizing branch stacks tip-bot for Adrian Hunter <tipbot@zytor.com> - 2015-09-29 10:50 +0200
[PATCH 04/25] perf intel-pt: Make logging slightly more efficient Adrian Hunter <adrian.hunter@intel.com> - 2015-09-25 15:30 +0200
[tip:perf/core] perf intel-pt: Make logging slightly more efficient tip-bot for Adrian Hunter <tipbot@zytor.com> - 2015-09-29 10:50 +0200
[PATCH 07/25] perf tools: Add more documentation to export-to-postgresql.py script Adrian Hunter <adrian.hunter@intel.com> - 2015-09-25 15:30 +0200
[tip:perf/core] perf tools: Add more documentation to export-to-postgresql.py script tip-bot for Adrian Hunter <tipbot@zytor.com> - 2015-09-29 10:50 +0200
[PATCH 21/25] perf tools: Add perf_evlist__id2evsel_strict() Adrian Hunter <adrian.hunter@intel.com> - 2015-09-25 15:30 +0200
[tip:perf/core] perf evlist: Add perf_evlist__id2evsel_strict() tip-bot for Adrian Hunter <tipbot@zytor.com> - 2015-09-29 10:50 +0200
[PATCH 14/25] perf intel-pt: Support generating branch stack Adrian Hunter <adrian.hunter@intel.com> - 2015-09-25 15:30 +0200
[tip:perf/core] perf intel-pt: Support generating branch stack tip-bot for Adrian Hunter <tipbot@zytor.com> - 2015-09-29 10:50 +0200
Re: [PATCH 00/25] perf tools: minor improvements to Intel PT related stuff Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-09-28 22:40 +0200
Re: [PATCH 00/25] perf tools: minor improvements to Intel PT related stuff Adrian Hunter <adrian.hunter@intel.com> - 2015-09-29 13:20 +0200
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-09-25 15:30 +0200 |
| Subject | [PATCH 00/25] perf tools: minor improvements to Intel PT related stuff |
| Message-ID | <qcB4S-2t3-5@gated-at.bofh.it> |
Hi
Here are some minor improvements to Intel PT related stuff.
First 3 patches are minor fixes:
perf auxtrace: Fix 'instructions' period of zero
perf report: Fix sample type validation for synthesized callchains
perf intel-pt: Fix potential loop forever
Next 4 are minor improvements:
perf intel-pt: Make logging slightly more efficient
perf script: Allow time to be displayed in nanoseconds
perf tools: Warn when AUX data has been lost
perf tools: Add more documentation to export-to-postgresql.py script
Next 7 add support for branch stacks:
perf auxtrace: Add option to synthesize branch stacks on samples
perf report: Adjust sample type validation for synthesized branch stacks
perf report: Also do default setup for synthesized branch stacks
perf report: Skip events with null branch stacks
perf inject: Set branch stack feature flag when synthesizing branch stacks
perf intel-pt: Move branch filter logic
perf intel-pt: Support generating branch stack
Next 6 allow for arbitrary-sized call stacks:
perf report: Make max_stack value allow for synthesized callchains
perf hists: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
perf callchain: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
perf script: Add a setting for maximum stack depth
perf scripting python: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
perf script: Make scripting_max_stack value allow for synthesized callchains
Final 5 let Intel PT be used with autofdo:
perf tools: Add perf_evlist__id2evsel_strict()
perf tools: Add perf_evlist__del()
perf inject: Remove more aux-related stuff when processing instruction traces
perf inject: Add --strip option to strip out non-synthesized events
perf intel-pt: Add mispred-all config option to aid use with autofdo
Adrian Hunter (25):
perf auxtrace: Fix 'instructions' period of zero
perf report: Fix sample type validation for synthesized callchains
perf intel-pt: Fix potential loop forever
perf intel-pt: Make logging slightly more efficient
perf script: Allow time to be displayed in nanoseconds
perf tools: Warn when AUX data has been lost
perf tools: Add more documentation to export-to-postgresql.py script
perf auxtrace: Add option to synthesize branch stacks on samples
perf report: Adjust sample type validation for synthesized branch stacks
perf report: Also do default setup for synthesized branch stacks
perf report: Skip events with null branch stacks
perf inject: Set branch stack feature flag when synthesizing branch stacks
perf intel-pt: Move branch filter logic
perf intel-pt: Support generating branch stack
perf report: Make max_stack value allow for synthesized callchains
perf hists: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
perf callchain: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
perf script: Add a setting for maximum stack depth
perf scripting python: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
perf script: Make scripting_max_stack value allow for synthesized callchains
perf tools: Add perf_evlist__id2evsel_strict()
perf tools: Add perf_evlist__del()
perf inject: Remove more aux-related stuff when processing instruction traces
perf inject: Add --strip option to strip out non-synthesized events
perf intel-pt: Add mispred-all config option to aid use with autofdo
tools/perf/Documentation/intel-pt.txt | 39 ++++
tools/perf/Documentation/itrace.txt | 4 +
tools/perf/Documentation/perf-inject.txt | 3 +
tools/perf/Documentation/perf-script.txt | 3 +
tools/perf/builtin-inject.c | 125 +++++++++++-
tools/perf/builtin-report.c | 31 ++-
tools/perf/builtin-script.c | 18 +-
tools/perf/scripts/python/export-to-postgresql.py | 221 +++++++++++++++++++++
tools/perf/util/auxtrace.c | 24 ++-
tools/perf/util/auxtrace.h | 4 +
tools/perf/util/event.h | 1 +
tools/perf/util/evlist.c | 23 +++
tools/perf/util/evlist.h | 3 +
tools/perf/util/hist.c | 6 +-
tools/perf/util/hist.h | 1 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 4 +-
tools/perf/util/intel-pt-decoder/intel-pt-log.c | 21 +-
tools/perf/util/intel-pt-decoder/intel-pt-log.h | 38 +++-
tools/perf/util/intel-pt.c | 135 ++++++++++++-
tools/perf/util/machine.c | 2 +-
.../util/scripting-engines/trace-event-python.c | 2 +-
tools/perf/util/session.c | 12 +-
tools/perf/util/trace-event.h | 2 +
23 files changed, 686 insertions(+), 36 deletions(-)
Regards
Adrian
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-09-25 15:30 +0200 |
| Subject | [PATCH 01/25] perf auxtrace: Fix 'instructions' period of zero |
| Message-ID | <qcBez-2Eq-61@gated-at.bofh.it> |
| In reply to | #1232818 |
Instruction tracing options (i.e. --itrace) include an option for
sampling instructions at an arbitrary period. e.g.
--itrace=i10us
means make an 'instructions' sample for every 10us of trace.
Currently the logic does not distinguish between a period of
zero and no period being specified at all, so it gets treated
as the default period which is 100000. That doesn't really
make sense.
Fix it so that zero period is accepted and treated as meaning
"as often as possible".
In the case of Intel PT that is the same as a period of 1 and
a unit of 'instructions' (i.e. --itrace=i1i).
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/util/auxtrace.c | 4 +++-
tools/perf/util/intel-pt.c | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index a980e7c50ee0..c4993b2e6c50 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -950,6 +950,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
const char *p;
char *endptr;
bool period_type_set = false;
+ bool period_set = false;
synth_opts->set = true;
@@ -971,6 +972,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
p += 1;
if (isdigit(*p)) {
synth_opts->period = strtoull(p, &endptr, 10);
+ period_set = true;
p = endptr;
while (*p == ' ' || *p == ',')
p += 1;
@@ -1053,7 +1055,7 @@ out:
if (!period_type_set)
synth_opts->period_type =
PERF_ITRACE_DEFAULT_PERIOD_TYPE;
- if (!synth_opts->period)
+ if (!period_set)
synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
}
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 38942e1eac8f..c8bb5ca6a157 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -720,7 +720,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
if (!params.period) {
params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS;
- params.period = 1000;
+ params.period = 1;
}
}
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-09-28 16:20 +0200 |
| Subject | Re: [PATCH 01/25] perf auxtrace: Fix 'instructions' period of zero |
| Message-ID | <qdHrA-1Q9-11@gated-at.bofh.it> |
| In reply to | #1232819 |
Em Mon, Sep 28, 2015 at 11:12:16AM -0300, Arnaldo Carvalho de Melo escreveu: > Em Fri, Sep 25, 2015 at 04:15:32PM +0300, Adrian Hunter escreveu: > > Instruction tracing options (i.e. --itrace) include an option for > > sampling instructions at an arbitrary period. e.g. > > > > --itrace=i10us > > > > means make an 'instructions' sample for every 10us of trace. > > > > Currently the logic does not distinguish between a period of > > zero and no period being specified at all, so it gets treated > > as the default period which is 100000. That doesn't really > > make sense. > > > > Fix it so that zero period is accepted and treated as meaning > > "as often as possible". > > Don't we have to update the documentation for this? > > > In the case of Intel PT that is the same as a period of 1 and > > a unit of 'instructions' (i.e. --itrace=i1i). I.e. may I fold the following patch into this one? Should we update the per tool man page? diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt index 4a0501d7a3b4..05707d9bfdda 100644 --- a/tools/perf/Documentation/intel-pt.txt +++ b/tools/perf/Documentation/intel-pt.txt @@ -722,6 +722,11 @@ on the sample is *not* adjusted and reflects the last known value of TSC. For Intel PT, the default period is 100us. +Setting it to a zero period means "as often as possible". + +In the case of Intel PT that is the same as a period of 1 and a unit of +'instructions' (i.e. --itrace=i1i). + Also the call chain size (default 16, max. 1024) for instructions or transactions events can be specified. e.g. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-09-28 16:20 +0200 |
| Subject | Re: [PATCH 01/25] perf auxtrace: Fix 'instructions' period of zero |
| Message-ID | <qdHrA-1Q9-13@gated-at.bofh.it> |
| In reply to | #1232819 |
Em Fri, Sep 25, 2015 at 04:15:32PM +0300, Adrian Hunter escreveu:
> Instruction tracing options (i.e. --itrace) include an option for
> sampling instructions at an arbitrary period. e.g.
>
> --itrace=i10us
>
> means make an 'instructions' sample for every 10us of trace.
>
> Currently the logic does not distinguish between a period of
> zero and no period being specified at all, so it gets treated
> as the default period which is 100000. That doesn't really
> make sense.
>
> Fix it so that zero period is accepted and treated as meaning
> "as often as possible".
Don't we have to update the documentation for this?
> In the case of Intel PT that is the same as a period of 1 and
> a unit of 'instructions' (i.e. --itrace=i1i).
>
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
> tools/perf/util/auxtrace.c | 4 +++-
> tools/perf/util/intel-pt.c | 2 +-
> 2 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
> index a980e7c50ee0..c4993b2e6c50 100644
> --- a/tools/perf/util/auxtrace.c
> +++ b/tools/perf/util/auxtrace.c
> @@ -950,6 +950,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
> const char *p;
> char *endptr;
> bool period_type_set = false;
> + bool period_set = false;
>
> synth_opts->set = true;
>
> @@ -971,6 +972,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
> p += 1;
> if (isdigit(*p)) {
> synth_opts->period = strtoull(p, &endptr, 10);
> + period_set = true;
> p = endptr;
> while (*p == ' ' || *p == ',')
> p += 1;
> @@ -1053,7 +1055,7 @@ out:
> if (!period_type_set)
> synth_opts->period_type =
> PERF_ITRACE_DEFAULT_PERIOD_TYPE;
> - if (!synth_opts->period)
> + if (!period_set)
> synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
> }
>
> diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
> index 38942e1eac8f..c8bb5ca6a157 100644
> --- a/tools/perf/util/intel-pt.c
> +++ b/tools/perf/util/intel-pt.c
> @@ -720,7 +720,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
>
> if (!params.period) {
> params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS;
> - params.period = 1000;
> + params.period = 1;
> }
> }
>
> --
> 1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Adrian Hunter <tipbot@zytor.com> |
|---|---|
| Date | 2015-09-29 11:00 +0200 |
| Subject | [tip:perf/core] perf auxtrace: Fix 'instructions' period of zero |
| Message-ID | <qdYVu-1z1-29@gated-at.bofh.it> |
| In reply to | #1232819 |
Commit-ID: e1791347b5d57d13326cf0114df1a3f3b1c4ca24
Gitweb: http://git.kernel.org/tip/e1791347b5d57d13326cf0114df1a3f3b1c4ca24
Author: Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 25 Sep 2015 16:15:32 +0300
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 28 Sep 2015 15:50:56 -0300
perf auxtrace: Fix 'instructions' period of zero
Instruction tracing options (i.e. --itrace) include an option for
sampling instructions at an arbitrary period. e.g.
--itrace=i10us
means make an 'instructions' sample for every 10us of trace.
Currently the logic does not distinguish between a period of
zero and no period being specified at all, so it gets treated
as the default period which is 100000. That doesn't really
make sense.
Fix it so that zero period is accepted and treated as meaning
"as often as possible".
In the case of Intel PT that is the same as a period of 1 and
a unit of 'instructions' (i.e. --itrace=i1i).
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-2-git-send-email-adrian.hunter@intel.com
[ Add a few lines describing this in the Documentation/intel-pt.txt file ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/intel-pt.txt | 5 +++++
tools/perf/util/auxtrace.c | 4 +++-
tools/perf/util/intel-pt.c | 2 +-
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index c94c9de..886612b 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -707,6 +707,11 @@ on the sample is *not* adjusted and reflects the last known value of TSC.
For Intel PT, the default period is 100us.
+Setting it to a zero period means "as often as possible".
+
+In the case of Intel PT that is the same as a period of 1 and a unit of
+'instructions' (i.e. --itrace=i1i).
+
Also the call chain size (default 16, max. 1024) for instructions or
transactions events can be specified. e.g.
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index a980e7c..c4993b2 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -950,6 +950,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
const char *p;
char *endptr;
bool period_type_set = false;
+ bool period_set = false;
synth_opts->set = true;
@@ -971,6 +972,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
p += 1;
if (isdigit(*p)) {
synth_opts->period = strtoull(p, &endptr, 10);
+ period_set = true;
p = endptr;
while (*p == ' ' || *p == ',')
p += 1;
@@ -1053,7 +1055,7 @@ out:
if (!period_type_set)
synth_opts->period_type =
PERF_ITRACE_DEFAULT_PERIOD_TYPE;
- if (!synth_opts->period)
+ if (!period_set)
synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
}
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 38942e1..c8bb5ca 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -720,7 +720,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
if (!params.period) {
params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS;
- params.period = 1000;
+ params.period = 1;
}
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-09-25 15:30 +0200 |
| Subject | [PATCH 12/25] perf inject: Set branch stack feature flag when synthesizing branch stacks |
| Message-ID | <qcBez-2Eq-55@gated-at.bofh.it> |
| In reply to | #1232818 |
The branch stack feature flag is set by 'perf record' when recording
data that contains branch stacks. Consequently, when 'perf inject'
synthesizes branch stacks, the feature flag should be set also.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/builtin-inject.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index f62c49b35be0..8638fad8a085 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -537,9 +537,13 @@ static int __cmd_inject(struct perf_inject *inject)
* The AUX areas have been removed and replaced with
* synthesized hardware events, so clear the feature flag.
*/
- if (inject->itrace_synth_opts.set)
+ if (inject->itrace_synth_opts.set) {
perf_header__clear_feat(&session->header,
HEADER_AUXTRACE);
+ if (inject->itrace_synth_opts.last_branch)
+ perf_header__set_feat(&session->header,
+ HEADER_BRANCH_STACK);
+ }
session->header.data_offset = output_data_offset;
session->header.data_size = inject->bytes_written;
perf_session__write_header(session, session->evlist, fd, true);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Adrian Hunter <tipbot@zytor.com> |
|---|---|
| Date | 2015-09-29 10:50 +0200 |
| Subject | [tip:perf/core] perf inject: Set branch stack feature flag when synthesizing branch stacks |
| Message-ID | <qdYLP-1nH-69@gated-at.bofh.it> |
| In reply to | #1232820 |
Commit-ID: 051a01b9a2c1c1ef3049973a43d9ed4ddcc946f3
Gitweb: http://git.kernel.org/tip/051a01b9a2c1c1ef3049973a43d9ed4ddcc946f3
Author: Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 25 Sep 2015 16:15:43 +0300
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 28 Sep 2015 16:57:59 -0300
perf inject: Set branch stack feature flag when synthesizing branch stacks
The branch stack feature flag is set by 'perf record' when recording
data that contains branch stacks. Consequently, when 'perf inject'
synthesizes branch stacks, the feature flag should be set also.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-13-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-inject.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index f62c49b..8638fad 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -537,9 +537,13 @@ static int __cmd_inject(struct perf_inject *inject)
* The AUX areas have been removed and replaced with
* synthesized hardware events, so clear the feature flag.
*/
- if (inject->itrace_synth_opts.set)
+ if (inject->itrace_synth_opts.set) {
perf_header__clear_feat(&session->header,
HEADER_AUXTRACE);
+ if (inject->itrace_synth_opts.last_branch)
+ perf_header__set_feat(&session->header,
+ HEADER_BRANCH_STACK);
+ }
session->header.data_offset = output_data_offset;
session->header.data_size = inject->bytes_written;
perf_session__write_header(session, session->evlist, fd, true);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-09-25 15:30 +0200 |
| Subject | [PATCH 04/25] perf intel-pt: Make logging slightly more efficient |
| Message-ID | <qcBez-2Eq-57@gated-at.bofh.it> |
| In reply to | #1232818 |
Logging is only used for debugging. Use macros to save
calling into the functions only to return immediately
when logging is not enabled.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/util/intel-pt-decoder/intel-pt-log.c | 21 +++++++-------
tools/perf/util/intel-pt-decoder/intel-pt-log.h | 38 +++++++++++++++++++++----
2 files changed, 43 insertions(+), 16 deletions(-)
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index d09c7d9f9050..319bef33a64b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -29,18 +29,18 @@
static FILE *f;
static char log_name[MAX_LOG_NAME];
-static bool enable_logging;
+bool intel_pt_enable_logging;
void intel_pt_log_enable(void)
{
- enable_logging = true;
+ intel_pt_enable_logging = true;
}
void intel_pt_log_disable(void)
{
if (f)
fflush(f);
- enable_logging = false;
+ intel_pt_enable_logging = false;
}
void intel_pt_log_set_name(const char *name)
@@ -80,7 +80,7 @@ static void intel_pt_print_no_data(uint64_t pos, int indent)
static int intel_pt_log_open(void)
{
- if (!enable_logging)
+ if (!intel_pt_enable_logging)
return -1;
if (f)
@@ -91,15 +91,15 @@ static int intel_pt_log_open(void)
f = fopen(log_name, "w+");
if (!f) {
- enable_logging = false;
+ intel_pt_enable_logging = false;
return -1;
}
return 0;
}
-void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
- uint64_t pos, const unsigned char *buf)
+void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
+ uint64_t pos, const unsigned char *buf)
{
char desc[INTEL_PT_PKT_DESC_MAX];
@@ -111,7 +111,7 @@ void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
fprintf(f, "%s\n", desc);
}
-void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
+void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
{
char desc[INTEL_PT_INSN_DESC_MAX];
size_t len = intel_pt_insn->length;
@@ -128,7 +128,8 @@ void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
fprintf(f, "Bad instruction!\n");
}
-void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
+void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
+ uint64_t ip)
{
char desc[INTEL_PT_INSN_DESC_MAX];
@@ -142,7 +143,7 @@ void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
fprintf(f, "Bad instruction!\n");
}
-void intel_pt_log(const char *fmt, ...)
+void __intel_pt_log(const char *fmt, ...)
{
va_list args;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
index db3942f83677..debe751dc3d6 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
@@ -25,20 +25,46 @@ void intel_pt_log_enable(void);
void intel_pt_log_disable(void);
void intel_pt_log_set_name(const char *name);
-void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
- uint64_t pos, const unsigned char *buf);
+void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
+ uint64_t pos, const unsigned char *buf);
struct intel_pt_insn;
-void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
-void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
- uint64_t ip);
+void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
+void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
+ uint64_t ip);
__attribute__((format(printf, 1, 2)))
-void intel_pt_log(const char *fmt, ...);
+void __intel_pt_log(const char *fmt, ...);
+
+#define intel_pt_log(fmt, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_packet(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_packet(arg, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_insn(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_insn(arg, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_insn_no_data(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_insn_no_data(arg, ##__VA_ARGS__); \
+ } while (0)
#define x64_fmt "0x%" PRIx64
+extern bool intel_pt_enable_logging;
+
static inline void intel_pt_log_at(const char *msg, uint64_t u)
{
intel_pt_log("%s at " x64_fmt "\n", msg, u);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Adrian Hunter <tipbot@zytor.com> |
|---|---|
| Date | 2015-09-29 10:50 +0200 |
| Subject | [tip:perf/core] perf intel-pt: Make logging slightly more efficient |
| Message-ID | <qdYLO-1nH-63@gated-at.bofh.it> |
| In reply to | #1232821 |
Commit-ID: 116f349c5bf8c7aec4047dd6e06c310354b46e4f
Gitweb: http://git.kernel.org/tip/116f349c5bf8c7aec4047dd6e06c310354b46e4f
Author: Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 25 Sep 2015 16:15:35 +0300
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 28 Sep 2015 16:45:26 -0300
perf intel-pt: Make logging slightly more efficient
Logging is only used for debugging. Use macros to save calling into the
functions only to return immediately when logging is not enabled.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-5-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/intel-pt-decoder/intel-pt-log.c | 21 +++++++-------
tools/perf/util/intel-pt-decoder/intel-pt-log.h | 38 +++++++++++++++++++++----
2 files changed, 43 insertions(+), 16 deletions(-)
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index d09c7d9..319bef3 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -29,18 +29,18 @@
static FILE *f;
static char log_name[MAX_LOG_NAME];
-static bool enable_logging;
+bool intel_pt_enable_logging;
void intel_pt_log_enable(void)
{
- enable_logging = true;
+ intel_pt_enable_logging = true;
}
void intel_pt_log_disable(void)
{
if (f)
fflush(f);
- enable_logging = false;
+ intel_pt_enable_logging = false;
}
void intel_pt_log_set_name(const char *name)
@@ -80,7 +80,7 @@ static void intel_pt_print_no_data(uint64_t pos, int indent)
static int intel_pt_log_open(void)
{
- if (!enable_logging)
+ if (!intel_pt_enable_logging)
return -1;
if (f)
@@ -91,15 +91,15 @@ static int intel_pt_log_open(void)
f = fopen(log_name, "w+");
if (!f) {
- enable_logging = false;
+ intel_pt_enable_logging = false;
return -1;
}
return 0;
}
-void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
- uint64_t pos, const unsigned char *buf)
+void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
+ uint64_t pos, const unsigned char *buf)
{
char desc[INTEL_PT_PKT_DESC_MAX];
@@ -111,7 +111,7 @@ void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
fprintf(f, "%s\n", desc);
}
-void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
+void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
{
char desc[INTEL_PT_INSN_DESC_MAX];
size_t len = intel_pt_insn->length;
@@ -128,7 +128,8 @@ void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
fprintf(f, "Bad instruction!\n");
}
-void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
+void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
+ uint64_t ip)
{
char desc[INTEL_PT_INSN_DESC_MAX];
@@ -142,7 +143,7 @@ void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
fprintf(f, "Bad instruction!\n");
}
-void intel_pt_log(const char *fmt, ...)
+void __intel_pt_log(const char *fmt, ...)
{
va_list args;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
index db3942f..debe751 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
@@ -25,20 +25,46 @@ void intel_pt_log_enable(void);
void intel_pt_log_disable(void);
void intel_pt_log_set_name(const char *name);
-void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
- uint64_t pos, const unsigned char *buf);
+void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
+ uint64_t pos, const unsigned char *buf);
struct intel_pt_insn;
-void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
-void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
- uint64_t ip);
+void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
+void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
+ uint64_t ip);
__attribute__((format(printf, 1, 2)))
-void intel_pt_log(const char *fmt, ...);
+void __intel_pt_log(const char *fmt, ...);
+
+#define intel_pt_log(fmt, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_packet(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_packet(arg, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_insn(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_insn(arg, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_insn_no_data(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_insn_no_data(arg, ##__VA_ARGS__); \
+ } while (0)
#define x64_fmt "0x%" PRIx64
+extern bool intel_pt_enable_logging;
+
static inline void intel_pt_log_at(const char *msg, uint64_t u)
{
intel_pt_log("%s at " x64_fmt "\n", msg, u);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-09-25 15:30 +0200 |
| Subject | [PATCH 07/25] perf tools: Add more documentation to export-to-postgresql.py script |
| Message-ID | <qcBez-2Eq-59@gated-at.bofh.it> |
| In reply to | #1232818 |
Add some comments to the script and some 'views' to the created
database that better illustrate the database structure and how it
can be used.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/scripts/python/export-to-postgresql.py | 221 ++++++++++++++++++++++
1 file changed, 221 insertions(+)
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 84a32037a80f..1b02cdc0cab6 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -61,6 +61,142 @@ import datetime
#
# An example of using the database is provided by the script
# call-graph-from-postgresql.py. Refer to that script for details.
+#
+# Tables:
+#
+# The tables largely correspond to perf tools' data structures. They are largely self-explanatory.
+#
+# samples
+#
+# 'samples' is the main table. It represents what instruction was executing at a point in time
+# when something (a selected event) happened. The memory address is the instruction pointer or 'ip'.
+#
+# calls
+#
+# 'calls' represents function calls and is related to 'samples' by 'call_id' and 'return_id'.
+# 'calls' is only created when the 'calls' option to this script is specified.
+#
+# call_paths
+#
+# 'call_paths' represents all the call stacks. Each 'call' has an associated record in 'call_paths'.
+# 'calls_paths' is only created when the 'calls' option to this script is specified.
+#
+# branch_types
+#
+# 'branch_types' provides descriptions for each type of branch.
+#
+# comm_threads
+#
+# 'comm_threads' shows how 'comms' relates to 'threads'.
+#
+# comms
+#
+# 'comms' contains a record for each 'comm' - the name given to the executable that is running.
+#
+# dsos
+#
+# 'dsos' contains a record for each executable file or library.
+#
+# machines
+#
+# 'machines' can be used to distinguish virtual machines if virtualization is supported.
+#
+# selected_events
+#
+# 'selected_events' contains a record for each kind of event that has been sampled.
+#
+# symbols
+#
+# 'symbols' contains a record for each symbol. Only symbols that have samples are present.
+#
+# threads
+#
+# 'threads' contains a record for each thread.
+#
+# Views:
+#
+# Most of the tables have views for more friendly display. The views are:
+#
+# calls_view
+# call_paths_view
+# comm_threads_view
+# dsos_view
+# machines_view
+# samples_view
+# symbols_view
+# threads_view
+#
+# More examples of browsing the database with psql:
+# Note that some of the examples are not the most optimal SQL query.
+# Note that call information is only available if the script's 'calls' option has been used.
+#
+# Top 10 function calls (not aggregated by symbol):
+#
+# SELECT * FROM calls_view ORDER BY elapsed_time DESC LIMIT 10;
+#
+# Top 10 function calls (aggregated by symbol):
+#
+# SELECT symbol_id,(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,
+# SUM(elapsed_time) AS tot_elapsed_time,SUM(branch_count) AS tot_branch_count
+# FROM calls_view GROUP BY symbol_id ORDER BY tot_elapsed_time DESC LIMIT 10;
+#
+# Note that the branch count gives a rough estimation of cpu usage, so functions
+# that took a long time but have a relatively low branch count must have spent time
+# waiting.
+#
+# Find symbols by pattern matching on part of the name (e.g. names containing 'alloc'):
+#
+# SELECT * FROM symbols_view WHERE name LIKE '%alloc%';
+#
+# Top 10 function calls for a specific symbol (e.g. whose symbol_id is 187):
+#
+# SELECT * FROM calls_view WHERE symbol_id = 187 ORDER BY elapsed_time DESC LIMIT 10;
+#
+# Show function calls made by function in the same context (i.e. same call path) (e.g. one with call_path_id 254):
+#
+# SELECT * FROM calls_view WHERE parent_call_path_id = 254;
+#
+# Show branches made during a function call (e.g. where call_id is 29357 and return_id is 29370 and tid is 29670)
+#
+# SELECT * FROM samples_view WHERE id >= 29357 AND id <= 29370 AND tid = 29670 AND event LIKE 'branches%';
+#
+# Show transactions:
+#
+# SELECT * FROM samples_view WHERE event = 'transactions';
+#
+# Note transaction start has 'in_tx' true whereas, transaction end has 'in_tx' false.
+# Transaction aborts have branch_type_name 'transaction abort'
+#
+# Show transaction aborts:
+#
+# SELECT * FROM samples_view WHERE event = 'transactions' AND branch_type_name = 'transaction abort';
+#
+# To print a call stack requires walking the call_paths table. For example this python script:
+# #!/usr/bin/python2
+#
+# import sys
+# from PySide.QtSql import *
+#
+# if __name__ == '__main__':
+# if (len(sys.argv) < 3):
+# print >> sys.stderr, "Usage is: printcallstack.py <database name> <call_path_id>"
+# raise Exception("Too few arguments")
+# dbname = sys.argv[1]
+# call_path_id = sys.argv[2]
+# db = QSqlDatabase.addDatabase('QPSQL')
+# db.setDatabaseName(dbname)
+# if not db.open():
+# raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
+# query = QSqlQuery(db)
+# print " id ip symbol_id symbol dso_id dso_short_name"
+# while call_path_id != 0 and call_path_id != 1:
+# ret = query.exec_('SELECT * FROM call_paths_view WHERE id = ' + str(call_path_id))
+# if not ret:
+# raise Exception("Query failed: " + query.lastError().text())
+# if not query.next():
+# raise Exception("Query failed")
+# print "{0:>6} {1:>10} {2:>9} {3:<30} {4:>6} {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5))
+# call_path_id = query.value(6)
from PySide.QtSql import *
@@ -244,6 +380,91 @@ if perf_db_export_calls:
'parent_call_path_id bigint,'
'flags integer)')
+do_query(query, 'CREATE VIEW machines_view AS '
+ 'SELECT '
+ 'id,'
+ 'pid,'
+ 'root_dir,'
+ 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
+ ' FROM machines')
+
+do_query(query, 'CREATE VIEW dsos_view AS '
+ 'SELECT '
+ 'id,'
+ 'machine_id,'
+ '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
+ 'short_name,'
+ 'long_name,'
+ 'build_id'
+ ' FROM dsos')
+
+do_query(query, 'CREATE VIEW symbols_view AS '
+ 'SELECT '
+ 'id,'
+ 'name,'
+ '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
+ 'dso_id,'
+ 'sym_start,'
+ 'sym_end,'
+ 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
+ ' FROM symbols')
+
+do_query(query, 'CREATE VIEW threads_view AS '
+ 'SELECT '
+ 'id,'
+ 'machine_id,'
+ '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
+ 'process_id,'
+ 'pid,'
+ 'tid'
+ ' FROM threads')
+
+do_query(query, 'CREATE VIEW comm_threads_view AS '
+ 'SELECT '
+ 'comm_id,'
+ '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
+ 'thread_id,'
+ '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
+ '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
+ ' FROM comm_threads')
+
+if perf_db_export_calls:
+ do_query(query, 'CREATE VIEW call_paths_view AS '
+ 'SELECT '
+ 'c.id,'
+ 'to_hex(c.ip) AS ip,'
+ 'c.symbol_id,'
+ '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
+ '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
+ '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
+ 'c.parent_id,'
+ 'to_hex(p.ip) AS parent_ip,'
+ 'p.symbol_id AS parent_symbol_id,'
+ '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
+ '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
+ '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
+ ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
+ do_query(query, 'CREATE VIEW calls_view AS '
+ 'SELECT '
+ 'calls.id,'
+ 'thread_id,'
+ '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
+ '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
+ '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
+ 'call_path_id,'
+ 'to_hex(ip) AS ip,'
+ 'symbol_id,'
+ '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
+ 'call_time,'
+ 'return_time,'
+ 'return_time - call_time AS elapsed_time,'
+ 'branch_count,'
+ 'call_id,'
+ 'return_id,'
+ 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,'
+ 'parent_call_path_id'
+ ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
+
do_query(query, 'CREATE VIEW samples_view AS '
'SELECT '
'id,'
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Adrian Hunter <tipbot@zytor.com> |
|---|---|
| Date | 2015-09-29 10:50 +0200 |
| Subject | [tip:perf/core] perf tools: Add more documentation to export-to-postgresql.py script |
| Message-ID | <qdYLL-1nH-9@gated-at.bofh.it> |
| In reply to | #1232822 |
Commit-ID: 35ca01c117da9b8e5b60204f730cdde414735596
Gitweb: http://git.kernel.org/tip/35ca01c117da9b8e5b60204f730cdde414735596
Author: Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 25 Sep 2015 16:15:38 +0300
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 28 Sep 2015 16:53:07 -0300
perf tools: Add more documentation to export-to-postgresql.py script
Add some comments to the script and some 'views' to the created database
that better illustrate the database structure and how it can be used.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-8-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/scripts/python/export-to-postgresql.py | 221 ++++++++++++++++++++++
1 file changed, 221 insertions(+)
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 84a3203..1b02cdc 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -61,6 +61,142 @@ import datetime
#
# An example of using the database is provided by the script
# call-graph-from-postgresql.py. Refer to that script for details.
+#
+# Tables:
+#
+# The tables largely correspond to perf tools' data structures. They are largely self-explanatory.
+#
+# samples
+#
+# 'samples' is the main table. It represents what instruction was executing at a point in time
+# when something (a selected event) happened. The memory address is the instruction pointer or 'ip'.
+#
+# calls
+#
+# 'calls' represents function calls and is related to 'samples' by 'call_id' and 'return_id'.
+# 'calls' is only created when the 'calls' option to this script is specified.
+#
+# call_paths
+#
+# 'call_paths' represents all the call stacks. Each 'call' has an associated record in 'call_paths'.
+# 'calls_paths' is only created when the 'calls' option to this script is specified.
+#
+# branch_types
+#
+# 'branch_types' provides descriptions for each type of branch.
+#
+# comm_threads
+#
+# 'comm_threads' shows how 'comms' relates to 'threads'.
+#
+# comms
+#
+# 'comms' contains a record for each 'comm' - the name given to the executable that is running.
+#
+# dsos
+#
+# 'dsos' contains a record for each executable file or library.
+#
+# machines
+#
+# 'machines' can be used to distinguish virtual machines if virtualization is supported.
+#
+# selected_events
+#
+# 'selected_events' contains a record for each kind of event that has been sampled.
+#
+# symbols
+#
+# 'symbols' contains a record for each symbol. Only symbols that have samples are present.
+#
+# threads
+#
+# 'threads' contains a record for each thread.
+#
+# Views:
+#
+# Most of the tables have views for more friendly display. The views are:
+#
+# calls_view
+# call_paths_view
+# comm_threads_view
+# dsos_view
+# machines_view
+# samples_view
+# symbols_view
+# threads_view
+#
+# More examples of browsing the database with psql:
+# Note that some of the examples are not the most optimal SQL query.
+# Note that call information is only available if the script's 'calls' option has been used.
+#
+# Top 10 function calls (not aggregated by symbol):
+#
+# SELECT * FROM calls_view ORDER BY elapsed_time DESC LIMIT 10;
+#
+# Top 10 function calls (aggregated by symbol):
+#
+# SELECT symbol_id,(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,
+# SUM(elapsed_time) AS tot_elapsed_time,SUM(branch_count) AS tot_branch_count
+# FROM calls_view GROUP BY symbol_id ORDER BY tot_elapsed_time DESC LIMIT 10;
+#
+# Note that the branch count gives a rough estimation of cpu usage, so functions
+# that took a long time but have a relatively low branch count must have spent time
+# waiting.
+#
+# Find symbols by pattern matching on part of the name (e.g. names containing 'alloc'):
+#
+# SELECT * FROM symbols_view WHERE name LIKE '%alloc%';
+#
+# Top 10 function calls for a specific symbol (e.g. whose symbol_id is 187):
+#
+# SELECT * FROM calls_view WHERE symbol_id = 187 ORDER BY elapsed_time DESC LIMIT 10;
+#
+# Show function calls made by function in the same context (i.e. same call path) (e.g. one with call_path_id 254):
+#
+# SELECT * FROM calls_view WHERE parent_call_path_id = 254;
+#
+# Show branches made during a function call (e.g. where call_id is 29357 and return_id is 29370 and tid is 29670)
+#
+# SELECT * FROM samples_view WHERE id >= 29357 AND id <= 29370 AND tid = 29670 AND event LIKE 'branches%';
+#
+# Show transactions:
+#
+# SELECT * FROM samples_view WHERE event = 'transactions';
+#
+# Note transaction start has 'in_tx' true whereas, transaction end has 'in_tx' false.
+# Transaction aborts have branch_type_name 'transaction abort'
+#
+# Show transaction aborts:
+#
+# SELECT * FROM samples_view WHERE event = 'transactions' AND branch_type_name = 'transaction abort';
+#
+# To print a call stack requires walking the call_paths table. For example this python script:
+# #!/usr/bin/python2
+#
+# import sys
+# from PySide.QtSql import *
+#
+# if __name__ == '__main__':
+# if (len(sys.argv) < 3):
+# print >> sys.stderr, "Usage is: printcallstack.py <database name> <call_path_id>"
+# raise Exception("Too few arguments")
+# dbname = sys.argv[1]
+# call_path_id = sys.argv[2]
+# db = QSqlDatabase.addDatabase('QPSQL')
+# db.setDatabaseName(dbname)
+# if not db.open():
+# raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
+# query = QSqlQuery(db)
+# print " id ip symbol_id symbol dso_id dso_short_name"
+# while call_path_id != 0 and call_path_id != 1:
+# ret = query.exec_('SELECT * FROM call_paths_view WHERE id = ' + str(call_path_id))
+# if not ret:
+# raise Exception("Query failed: " + query.lastError().text())
+# if not query.next():
+# raise Exception("Query failed")
+# print "{0:>6} {1:>10} {2:>9} {3:<30} {4:>6} {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5))
+# call_path_id = query.value(6)
from PySide.QtSql import *
@@ -244,6 +380,91 @@ if perf_db_export_calls:
'parent_call_path_id bigint,'
'flags integer)')
+do_query(query, 'CREATE VIEW machines_view AS '
+ 'SELECT '
+ 'id,'
+ 'pid,'
+ 'root_dir,'
+ 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
+ ' FROM machines')
+
+do_query(query, 'CREATE VIEW dsos_view AS '
+ 'SELECT '
+ 'id,'
+ 'machine_id,'
+ '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
+ 'short_name,'
+ 'long_name,'
+ 'build_id'
+ ' FROM dsos')
+
+do_query(query, 'CREATE VIEW symbols_view AS '
+ 'SELECT '
+ 'id,'
+ 'name,'
+ '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
+ 'dso_id,'
+ 'sym_start,'
+ 'sym_end,'
+ 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
+ ' FROM symbols')
+
+do_query(query, 'CREATE VIEW threads_view AS '
+ 'SELECT '
+ 'id,'
+ 'machine_id,'
+ '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
+ 'process_id,'
+ 'pid,'
+ 'tid'
+ ' FROM threads')
+
+do_query(query, 'CREATE VIEW comm_threads_view AS '
+ 'SELECT '
+ 'comm_id,'
+ '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
+ 'thread_id,'
+ '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
+ '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
+ ' FROM comm_threads')
+
+if perf_db_export_calls:
+ do_query(query, 'CREATE VIEW call_paths_view AS '
+ 'SELECT '
+ 'c.id,'
+ 'to_hex(c.ip) AS ip,'
+ 'c.symbol_id,'
+ '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
+ '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
+ '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
+ 'c.parent_id,'
+ 'to_hex(p.ip) AS parent_ip,'
+ 'p.symbol_id AS parent_symbol_id,'
+ '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
+ '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
+ '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
+ ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
+ do_query(query, 'CREATE VIEW calls_view AS '
+ 'SELECT '
+ 'calls.id,'
+ 'thread_id,'
+ '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
+ '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
+ '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
+ 'call_path_id,'
+ 'to_hex(ip) AS ip,'
+ 'symbol_id,'
+ '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
+ 'call_time,'
+ 'return_time,'
+ 'return_time - call_time AS elapsed_time,'
+ 'branch_count,'
+ 'call_id,'
+ 'return_id,'
+ 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,'
+ 'parent_call_path_id'
+ ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
+
do_query(query, 'CREATE VIEW samples_view AS '
'SELECT '
'id,'
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-09-25 15:30 +0200 |
| Subject | [PATCH 21/25] perf tools: Add perf_evlist__id2evsel_strict() |
| Message-ID | <qcBez-2Eq-65@gated-at.bofh.it> |
| In reply to | #1232818 |
perf_evlist__id2evsel_strict() is the same as perf_evlist__id2evsel()
except that it ensures that the id must match.
This will be used by perf inject to find a specific evsel that is to
be deleted, hence the need to match exactly.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/util/evlist.c | 15 +++++++++++++++
tools/perf/util/evlist.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a8643735dcea..e6760380d731 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -617,6 +617,21 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
return NULL;
}
+struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
+ u64 id)
+{
+ struct perf_sample_id *sid;
+
+ if (!id)
+ return NULL;
+
+ sid = perf_evlist__id2sid(evlist, id);
+ if (sid)
+ return sid->evsel;
+
+ return NULL;
+}
+
static int perf_evlist__event2id(struct perf_evlist *evlist,
union perf_event *event, u64 *id)
{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 115d8b53c601..0edf0d4f4efa 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -104,6 +104,8 @@ int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mas
int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
+struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
+ u64 id);
struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Adrian Hunter <tipbot@zytor.com> |
|---|---|
| Date | 2015-09-29 10:50 +0200 |
| Subject | [tip:perf/core] perf evlist: Add perf_evlist__id2evsel_strict() |
| Message-ID | <qdYLN-1nH-37@gated-at.bofh.it> |
| In reply to | #1232823 |
Commit-ID: dddcf6abbf5946f9ec1183dd2099cede6dbe12fc
Gitweb: http://git.kernel.org/tip/dddcf6abbf5946f9ec1183dd2099cede6dbe12fc
Author: Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 25 Sep 2015 16:15:52 +0300
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 28 Sep 2015 17:11:00 -0300
perf evlist: Add perf_evlist__id2evsel_strict()
perf_evlist__id2evsel_strict() is the same as perf_evlist__id2evsel()
except that it ensures that the id must match.
This will be used by perf inject to find a specific evsel that is to be
deleted, hence the need to match exactly.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-22-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/evlist.c | 15 +++++++++++++++
tools/perf/util/evlist.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a864373..e676038 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -617,6 +617,21 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
return NULL;
}
+struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
+ u64 id)
+{
+ struct perf_sample_id *sid;
+
+ if (!id)
+ return NULL;
+
+ sid = perf_evlist__id2sid(evlist, id);
+ if (sid)
+ return sid->evsel;
+
+ return NULL;
+}
+
static int perf_evlist__event2id(struct perf_evlist *evlist,
union perf_event *event, u64 *id)
{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 115d8b5..0edf0d4 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -104,6 +104,8 @@ int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mas
int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
+struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
+ u64 id);
struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-09-25 15:30 +0200 |
| Subject | [PATCH 14/25] perf intel-pt: Support generating branch stack |
| Message-ID | <qcBez-2Eq-63@gated-at.bofh.it> |
| In reply to | #1232818 |
Add support for generating branch stack context for PT samples.
The decoder reports a configurable number of branches as branch
context for each sample. Internally it keeps track of them by
using a simple sliding window. We also flush the last branch
buffer on each sample to avoid overlapping intervals.
This is useful for:
- Reporting accurate basic block edge frequencies through the perf
report branch view
- Using with --branch-history to get the wider context of samples
- Other users of LBRs
Also the Documentation is updated.
Examples:
Record with Intel PT:
perf record -e intel_pt//u ls
Branch stacks are used by default if synthesized so:
perf report --itrace=ile
is the same as:
perf report --itrace=ile -b
Branch history can be requested also:
perf report --itrace=igle --branch-history
Based-on-patch-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/Documentation/intel-pt.txt | 10 +++
tools/perf/util/intel-pt.c | 115 ++++++++++++++++++++++++++++++++++
2 files changed, 125 insertions(+)
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index 4a0501d7a3b4..f4d8e706619c 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -686,6 +686,7 @@ The letters are:
e synthesize tracing error events
d create a debug log
g synthesize a call chain (use with i or x)
+ l synthesize last branch entries (use with i or x)
"Instructions" events look like they were recorded by "perf record -e
instructions".
@@ -728,6 +729,15 @@ transactions events can be specified. e.g.
--itrace=ig32
--itrace=xg32
+Also the number of last branch entries (default 64, max. 1024) for instructions or
+transactions events can be specified. e.g.
+
+ --itrace=il10
+ --itrace=xl10
+
+Note that last branch entries are cleared for each sample, so there is no overlap
+from one sample to the next.
+
To disable trace decoding entirely, use the option --no-itrace.
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 2c01e723826a..05e8fcc5188b 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -22,6 +22,7 @@
#include "../perf.h"
#include "session.h"
#include "machine.h"
+#include "sort.h"
#include "tool.h"
#include "event.h"
#include "evlist.h"
@@ -115,6 +116,9 @@ struct intel_pt_queue {
void *decoder;
const struct intel_pt_state *state;
struct ip_callchain *chain;
+ struct branch_stack *last_branch;
+ struct branch_stack *last_branch_rb;
+ size_t last_branch_pos;
union perf_event *event_buf;
bool on_heap;
bool stop;
@@ -675,6 +679,19 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
goto out_free;
}
+ if (pt->synth_opts.last_branch) {
+ size_t sz = sizeof(struct branch_stack);
+
+ sz += pt->synth_opts.last_branch_sz *
+ sizeof(struct branch_entry);
+ ptq->last_branch = zalloc(sz);
+ if (!ptq->last_branch)
+ goto out_free;
+ ptq->last_branch_rb = zalloc(sz);
+ if (!ptq->last_branch_rb)
+ goto out_free;
+ }
+
ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
if (!ptq->event_buf)
goto out_free;
@@ -732,6 +749,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
out_free:
zfree(&ptq->event_buf);
+ zfree(&ptq->last_branch);
+ zfree(&ptq->last_branch_rb);
zfree(&ptq->chain);
free(ptq);
return NULL;
@@ -746,6 +765,8 @@ static void intel_pt_free_queue(void *priv)
thread__zput(ptq->thread);
intel_pt_decoder_free(ptq->decoder);
zfree(&ptq->event_buf);
+ zfree(&ptq->last_branch);
+ zfree(&ptq->last_branch_rb);
zfree(&ptq->chain);
free(ptq);
}
@@ -876,6 +897,57 @@ static int intel_pt_setup_queues(struct intel_pt *pt)
return 0;
}
+static inline void intel_pt_copy_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ struct branch_stack *bs_src = ptq->last_branch_rb;
+ struct branch_stack *bs_dst = ptq->last_branch;
+ size_t nr = 0;
+
+ bs_dst->nr = bs_src->nr;
+
+ if (!bs_src->nr)
+ return;
+
+ nr = ptq->pt->synth_opts.last_branch_sz - ptq->last_branch_pos;
+ memcpy(&bs_dst->entries[0],
+ &bs_src->entries[ptq->last_branch_pos],
+ sizeof(struct branch_entry) * nr);
+
+ if (bs_src->nr >= ptq->pt->synth_opts.last_branch_sz) {
+ memcpy(&bs_dst->entries[nr],
+ &bs_src->entries[0],
+ sizeof(struct branch_entry) * ptq->last_branch_pos);
+ }
+}
+
+static inline void intel_pt_reset_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ ptq->last_branch_pos = 0;
+ ptq->last_branch_rb->nr = 0;
+}
+
+static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ const struct intel_pt_state *state = ptq->state;
+ struct branch_stack *bs = ptq->last_branch_rb;
+ struct branch_entry *be;
+
+ if (!ptq->last_branch_pos)
+ ptq->last_branch_pos = ptq->pt->synth_opts.last_branch_sz;
+
+ ptq->last_branch_pos -= 1;
+
+ be = &bs->entries[ptq->last_branch_pos];
+ be->from = state->from_ip;
+ be->to = state->to_ip;
+ be->flags.abort = !!(state->flags & INTEL_PT_ABORT_TX);
+ be->flags.in_tx = !!(state->flags & INTEL_PT_IN_TX);
+ /* No support for mispredict */
+
+ if (bs->nr < ptq->pt->synth_opts.last_branch_sz)
+ bs->nr += 1;
+}
+
static int intel_pt_inject_event(union perf_event *event,
struct perf_sample *sample, u64 type,
bool swapped)
@@ -890,6 +962,10 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
struct intel_pt *pt = ptq->pt;
union perf_event *event = ptq->event_buf;
struct perf_sample sample = { .ip = 0, };
+ struct dummy_branch_stack {
+ u64 nr;
+ struct branch_entry entries;
+ } dummy_bs;
if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
return 0;
@@ -912,6 +988,21 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
sample.flags = ptq->flags;
sample.insn_len = ptq->insn_len;
+ /*
+ * perf report cannot handle events without a branch stack when using
+ * SORT_MODE__BRANCH so make a dummy one.
+ */
+ if (pt->synth_opts.last_branch && sort__mode == SORT_MODE__BRANCH) {
+ dummy_bs = (struct dummy_branch_stack){
+ .nr = 1,
+ .entries = {
+ .from = sample.ip,
+ .to = sample.addr,
+ },
+ };
+ sample.branch_stack = (struct branch_stack *)&dummy_bs;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->branches_sample_type,
@@ -961,6 +1052,11 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
sample.callchain = ptq->chain;
}
+ if (pt->synth_opts.last_branch) {
+ intel_pt_copy_last_branch_rb(ptq);
+ sample.branch_stack = ptq->last_branch;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->instructions_sample_type,
@@ -974,6 +1070,9 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n",
ret);
+ if (pt->synth_opts.last_branch)
+ intel_pt_reset_last_branch_rb(ptq);
+
return ret;
}
@@ -1008,6 +1107,11 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
sample.callchain = ptq->chain;
}
+ if (pt->synth_opts.last_branch) {
+ intel_pt_copy_last_branch_rb(ptq);
+ sample.branch_stack = ptq->last_branch;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->transactions_sample_type,
@@ -1021,6 +1125,9 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n",
ret);
+ if (pt->synth_opts.callchain)
+ intel_pt_reset_last_branch_rb(ptq);
+
return ret;
}
@@ -1116,6 +1223,9 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
return err;
}
+ if (pt->synth_opts.last_branch)
+ intel_pt_update_last_branch_rb(ptq);
+
if (!pt->sync_switch)
return 0;
@@ -1763,6 +1873,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
pt->instructions_sample_period = attr.sample_period;
if (pt->synth_opts.callchain)
attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
+ if (pt->synth_opts.last_branch)
+ attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
@@ -1782,6 +1894,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
attr.sample_period = 1;
if (pt->synth_opts.callchain)
attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
+ if (pt->synth_opts.last_branch)
+ attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
@@ -1808,6 +1922,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
attr.sample_period = 1;
attr.sample_type |= PERF_SAMPLE_ADDR;
attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN;
+ attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Adrian Hunter <tipbot@zytor.com> |
|---|---|
| Date | 2015-09-29 10:50 +0200 |
| Subject | [tip:perf/core] perf intel-pt: Support generating branch stack |
| Message-ID | <qdYLM-1nH-27@gated-at.bofh.it> |
| In reply to | #1232824 |
Commit-ID: f14445ee72c59f32aa5cbf4d0f0330a5f62a752d
Gitweb: http://git.kernel.org/tip/f14445ee72c59f32aa5cbf4d0f0330a5f62a752d
Author: Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 25 Sep 2015 16:15:45 +0300
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 28 Sep 2015 16:59:14 -0300
perf intel-pt: Support generating branch stack
Add support for generating branch stack context for PT samples. The
decoder reports a configurable number of branches as branch context for
each sample. Internally it keeps track of them by using a simple sliding
window. We also flush the last branch buffer on each sample to avoid
overlapping intervals.
This is useful for:
- Reporting accurate basic block edge frequencies through the perf
report branch view
- Using with --branch-history to get the wider context of samples
- Other users of LBRs
Also the Documentation is updated.
Examples:
Record with Intel PT:
perf record -e intel_pt//u ls
Branch stacks are used by default if synthesized so:
perf report --itrace=ile
is the same as:
perf report --itrace=ile -b
Branch history can be requested also:
perf report --itrace=igle --branch-history
Based-on-patch-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-15-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/intel-pt.txt | 10 +++
tools/perf/util/intel-pt.c | 115 ++++++++++++++++++++++++++++++++++
2 files changed, 125 insertions(+)
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index 886612b..a0fbb5d 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -671,6 +671,7 @@ The letters are:
e synthesize tracing error events
d create a debug log
g synthesize a call chain (use with i or x)
+ l synthesize last branch entries (use with i or x)
"Instructions" events look like they were recorded by "perf record -e
instructions".
@@ -718,6 +719,15 @@ transactions events can be specified. e.g.
--itrace=ig32
--itrace=xg32
+Also the number of last branch entries (default 64, max. 1024) for instructions or
+transactions events can be specified. e.g.
+
+ --itrace=il10
+ --itrace=xl10
+
+Note that last branch entries are cleared for each sample, so there is no overlap
+from one sample to the next.
+
To disable trace decoding entirely, use the option --no-itrace.
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 2c01e72..05e8fcc51 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -22,6 +22,7 @@
#include "../perf.h"
#include "session.h"
#include "machine.h"
+#include "sort.h"
#include "tool.h"
#include "event.h"
#include "evlist.h"
@@ -115,6 +116,9 @@ struct intel_pt_queue {
void *decoder;
const struct intel_pt_state *state;
struct ip_callchain *chain;
+ struct branch_stack *last_branch;
+ struct branch_stack *last_branch_rb;
+ size_t last_branch_pos;
union perf_event *event_buf;
bool on_heap;
bool stop;
@@ -675,6 +679,19 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
goto out_free;
}
+ if (pt->synth_opts.last_branch) {
+ size_t sz = sizeof(struct branch_stack);
+
+ sz += pt->synth_opts.last_branch_sz *
+ sizeof(struct branch_entry);
+ ptq->last_branch = zalloc(sz);
+ if (!ptq->last_branch)
+ goto out_free;
+ ptq->last_branch_rb = zalloc(sz);
+ if (!ptq->last_branch_rb)
+ goto out_free;
+ }
+
ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
if (!ptq->event_buf)
goto out_free;
@@ -732,6 +749,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
out_free:
zfree(&ptq->event_buf);
+ zfree(&ptq->last_branch);
+ zfree(&ptq->last_branch_rb);
zfree(&ptq->chain);
free(ptq);
return NULL;
@@ -746,6 +765,8 @@ static void intel_pt_free_queue(void *priv)
thread__zput(ptq->thread);
intel_pt_decoder_free(ptq->decoder);
zfree(&ptq->event_buf);
+ zfree(&ptq->last_branch);
+ zfree(&ptq->last_branch_rb);
zfree(&ptq->chain);
free(ptq);
}
@@ -876,6 +897,57 @@ static int intel_pt_setup_queues(struct intel_pt *pt)
return 0;
}
+static inline void intel_pt_copy_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ struct branch_stack *bs_src = ptq->last_branch_rb;
+ struct branch_stack *bs_dst = ptq->last_branch;
+ size_t nr = 0;
+
+ bs_dst->nr = bs_src->nr;
+
+ if (!bs_src->nr)
+ return;
+
+ nr = ptq->pt->synth_opts.last_branch_sz - ptq->last_branch_pos;
+ memcpy(&bs_dst->entries[0],
+ &bs_src->entries[ptq->last_branch_pos],
+ sizeof(struct branch_entry) * nr);
+
+ if (bs_src->nr >= ptq->pt->synth_opts.last_branch_sz) {
+ memcpy(&bs_dst->entries[nr],
+ &bs_src->entries[0],
+ sizeof(struct branch_entry) * ptq->last_branch_pos);
+ }
+}
+
+static inline void intel_pt_reset_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ ptq->last_branch_pos = 0;
+ ptq->last_branch_rb->nr = 0;
+}
+
+static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ const struct intel_pt_state *state = ptq->state;
+ struct branch_stack *bs = ptq->last_branch_rb;
+ struct branch_entry *be;
+
+ if (!ptq->last_branch_pos)
+ ptq->last_branch_pos = ptq->pt->synth_opts.last_branch_sz;
+
+ ptq->last_branch_pos -= 1;
+
+ be = &bs->entries[ptq->last_branch_pos];
+ be->from = state->from_ip;
+ be->to = state->to_ip;
+ be->flags.abort = !!(state->flags & INTEL_PT_ABORT_TX);
+ be->flags.in_tx = !!(state->flags & INTEL_PT_IN_TX);
+ /* No support for mispredict */
+
+ if (bs->nr < ptq->pt->synth_opts.last_branch_sz)
+ bs->nr += 1;
+}
+
static int intel_pt_inject_event(union perf_event *event,
struct perf_sample *sample, u64 type,
bool swapped)
@@ -890,6 +962,10 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
struct intel_pt *pt = ptq->pt;
union perf_event *event = ptq->event_buf;
struct perf_sample sample = { .ip = 0, };
+ struct dummy_branch_stack {
+ u64 nr;
+ struct branch_entry entries;
+ } dummy_bs;
if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
return 0;
@@ -912,6 +988,21 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
sample.flags = ptq->flags;
sample.insn_len = ptq->insn_len;
+ /*
+ * perf report cannot handle events without a branch stack when using
+ * SORT_MODE__BRANCH so make a dummy one.
+ */
+ if (pt->synth_opts.last_branch && sort__mode == SORT_MODE__BRANCH) {
+ dummy_bs = (struct dummy_branch_stack){
+ .nr = 1,
+ .entries = {
+ .from = sample.ip,
+ .to = sample.addr,
+ },
+ };
+ sample.branch_stack = (struct branch_stack *)&dummy_bs;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->branches_sample_type,
@@ -961,6 +1052,11 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
sample.callchain = ptq->chain;
}
+ if (pt->synth_opts.last_branch) {
+ intel_pt_copy_last_branch_rb(ptq);
+ sample.branch_stack = ptq->last_branch;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->instructions_sample_type,
@@ -974,6 +1070,9 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n",
ret);
+ if (pt->synth_opts.last_branch)
+ intel_pt_reset_last_branch_rb(ptq);
+
return ret;
}
@@ -1008,6 +1107,11 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
sample.callchain = ptq->chain;
}
+ if (pt->synth_opts.last_branch) {
+ intel_pt_copy_last_branch_rb(ptq);
+ sample.branch_stack = ptq->last_branch;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->transactions_sample_type,
@@ -1021,6 +1125,9 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n",
ret);
+ if (pt->synth_opts.callchain)
+ intel_pt_reset_last_branch_rb(ptq);
+
return ret;
}
@@ -1116,6 +1223,9 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
return err;
}
+ if (pt->synth_opts.last_branch)
+ intel_pt_update_last_branch_rb(ptq);
+
if (!pt->sync_switch)
return 0;
@@ -1763,6 +1873,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
pt->instructions_sample_period = attr.sample_period;
if (pt->synth_opts.callchain)
attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
+ if (pt->synth_opts.last_branch)
+ attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
@@ -1782,6 +1894,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
attr.sample_period = 1;
if (pt->synth_opts.callchain)
attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
+ if (pt->synth_opts.last_branch)
+ attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
@@ -1808,6 +1922,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
attr.sample_period = 1;
attr.sample_type |= PERF_SAMPLE_ADDR;
attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN;
+ attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-09-28 22:40 +0200 |
| Subject | Re: [PATCH 00/25] perf tools: minor improvements to Intel PT related stuff |
| Message-ID | <qdNnk-1Sz-21@gated-at.bofh.it> |
| In reply to | #1232818 |
Em Fri, Sep 25, 2015 at 04:15:31PM +0300, Adrian Hunter escreveu: > Hi > > Here are some minor improvements to Intel PT related stuff. Thanks, applied all but: [PATCH 17/25] perf callchain: Allow for max_stack greater than PERF_MAX_STACK_DEPTH Please take a look at the comments I made on this and a few others that I applied, - Arnaldo > First 3 patches are minor fixes: > > perf auxtrace: Fix 'instructions' period of zero > perf report: Fix sample type validation for synthesized callchains > perf intel-pt: Fix potential loop forever > > Next 4 are minor improvements: > > perf intel-pt: Make logging slightly more efficient > perf script: Allow time to be displayed in nanoseconds > perf tools: Warn when AUX data has been lost > perf tools: Add more documentation to export-to-postgresql.py script > > Next 7 add support for branch stacks: > > perf auxtrace: Add option to synthesize branch stacks on samples > perf report: Adjust sample type validation for synthesized branch stacks > perf report: Also do default setup for synthesized branch stacks > perf report: Skip events with null branch stacks > perf inject: Set branch stack feature flag when synthesizing branch stacks > perf intel-pt: Move branch filter logic > perf intel-pt: Support generating branch stack > > Next 6 allow for arbitrary-sized call stacks: > > perf report: Make max_stack value allow for synthesized callchains > perf hists: Allow for max_stack greater than PERF_MAX_STACK_DEPTH > perf callchain: Allow for max_stack greater than PERF_MAX_STACK_DEPTH > perf script: Add a setting for maximum stack depth > perf scripting python: Allow for max_stack greater than PERF_MAX_STACK_DEPTH > perf script: Make scripting_max_stack value allow for synthesized callchains > > Final 5 let Intel PT be used with autofdo: > > perf tools: Add perf_evlist__id2evsel_strict() > perf tools: Add perf_evlist__del() > perf inject: Remove more aux-related stuff when processing instruction traces > perf inject: Add --strip option to strip out non-synthesized events > perf intel-pt: Add mispred-all config option to aid use with autofdo > > > Adrian Hunter (25): > perf auxtrace: Fix 'instructions' period of zero > perf report: Fix sample type validation for synthesized callchains > perf intel-pt: Fix potential loop forever > perf intel-pt: Make logging slightly more efficient > perf script: Allow time to be displayed in nanoseconds > perf tools: Warn when AUX data has been lost > perf tools: Add more documentation to export-to-postgresql.py script > perf auxtrace: Add option to synthesize branch stacks on samples > perf report: Adjust sample type validation for synthesized branch stacks > perf report: Also do default setup for synthesized branch stacks > perf report: Skip events with null branch stacks > perf inject: Set branch stack feature flag when synthesizing branch stacks > perf intel-pt: Move branch filter logic > perf intel-pt: Support generating branch stack > perf report: Make max_stack value allow for synthesized callchains > perf hists: Allow for max_stack greater than PERF_MAX_STACK_DEPTH > perf callchain: Allow for max_stack greater than PERF_MAX_STACK_DEPTH > perf script: Add a setting for maximum stack depth > perf scripting python: Allow for max_stack greater than PERF_MAX_STACK_DEPTH > perf script: Make scripting_max_stack value allow for synthesized callchains > perf tools: Add perf_evlist__id2evsel_strict() > perf tools: Add perf_evlist__del() > perf inject: Remove more aux-related stuff when processing instruction traces > perf inject: Add --strip option to strip out non-synthesized events > perf intel-pt: Add mispred-all config option to aid use with autofdo > > tools/perf/Documentation/intel-pt.txt | 39 ++++ > tools/perf/Documentation/itrace.txt | 4 + > tools/perf/Documentation/perf-inject.txt | 3 + > tools/perf/Documentation/perf-script.txt | 3 + > tools/perf/builtin-inject.c | 125 +++++++++++- > tools/perf/builtin-report.c | 31 ++- > tools/perf/builtin-script.c | 18 +- > tools/perf/scripts/python/export-to-postgresql.py | 221 +++++++++++++++++++++ > tools/perf/util/auxtrace.c | 24 ++- > tools/perf/util/auxtrace.h | 4 + > tools/perf/util/event.h | 1 + > tools/perf/util/evlist.c | 23 +++ > tools/perf/util/evlist.h | 3 + > tools/perf/util/hist.c | 6 +- > tools/perf/util/hist.h | 1 + > .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 4 +- > tools/perf/util/intel-pt-decoder/intel-pt-log.c | 21 +- > tools/perf/util/intel-pt-decoder/intel-pt-log.h | 38 +++- > tools/perf/util/intel-pt.c | 135 ++++++++++++- > tools/perf/util/machine.c | 2 +- > .../util/scripting-engines/trace-event-python.c | 2 +- > tools/perf/util/session.c | 12 +- > tools/perf/util/trace-event.h | 2 + > 23 files changed, 686 insertions(+), 36 deletions(-) > > > Regards > Adrian -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-09-29 13:20 +0200 |
| Subject | Re: [PATCH 00/25] perf tools: minor improvements to Intel PT related stuff |
| Message-ID | <qe16V-4Sg-3@gated-at.bofh.it> |
| In reply to | #1234430 |
On 28/09/15 23:33, Arnaldo Carvalho de Melo wrote: > Em Fri, Sep 25, 2015 at 04:15:31PM +0300, Adrian Hunter escreveu: >> Hi >> >> Here are some minor improvements to Intel PT related stuff. > > Thanks, applied all but: > > [PATCH 17/25] perf callchain: Allow for max_stack greater than PERF_MAX_STACK_DEPTH > > Please take a look at the comments I made on this and a few others that > I applied, I checked the final patches. Everything looks good. Thank you! -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web