perf tools: Add Intel PT support for jitdump
Adrian Hunter
reviewercover perf tools: Add Intel PT support for jitdump
Hi
In order to use Intel PT with jitdump, changes are needed because Intel PT uses TSC as a timestamp not the monotonic clock.
These patches enable TSC to be used which allows the following using a simple HelloWorld java app:
perf record -e intel_pt//u -o java.perf.data java -agentpath:/home/ahunter/git/linux-perf/tools/perf/jvmti/libjvmti.so HelloWorldApp
perf inject -i java.perf.data --jit -o java.perf.data.jitted
perf report -i java.perf.data.jitted
perf script -i java.perf.data.jitted | less
Note, there will be some decoder errors because not all the generated code is reported to the agent.
Lazily, there is also an unrelated patch:
perf tools: Use 64-bit shifts with (TSC) time conversion"
Adrian Hunter (8):
perf inject: Hit all DSOs for AUX data in JIT and other cases perf session: Simplify tool stubs
perf tools: Add time conversion event
perf jit: Let jit_process() return errors
perf jit: Move clockid validation
perf jit: Add support for using TSC as a timestamp perf intel-pt/bts: Define JITDUMP_USE_ARCH_TIMESTAMP perf tools: Use 64-bit shifts with (TSC) time conversion
tools/perf/arch/x86/tests/rdpmc.c | 2 +- tools/perf/arch/x86/util/intel-bts.c | 5 +++ tools/perf/arch/x86/util/intel-pt.c | 5 +++ tools/perf/arch/x86/util/tsc.c | 31 +++++++++++++++++ tools/perf/builtin-inject.c | 53 ++++++++++++----------------- tools/perf/builtin-record.c | 15 +++++++++ tools/perf/jvmti/jvmti_agent.c | 43 ++++++++++++++++++++++-- tools/perf/util/event.c | 1 + tools/perf/util/event.h | 9 +++++ tools/perf/util/jitdump.c | 64 ++++++++++++++++++++++++++++++++---- tools/perf/util/jitdump.h | 3 ++ tools/perf/util/session.c | 46 ++++++++------------------ tools/perf/util/session.h | 1 + tools/perf/util/tool.h | 1 + tools/perf/util/tsc.c | 2 +- tools/perf/util/tsc.h | 10 ++++++ 16 files changed, 216 insertions(+), 75 deletions(-)
Regards
Adrian
Adrian Hunter
reviewerPATCH 1/8 perf inject: Hit all DSOs for AUX data in JIT and other cases
Currently, when injecting build ids, if there is AUX data then 'perf inject' hits all DSOs because it is not known which DSOs the trace data would hit.
That needs to be done for JIT injection also, and in fact there is no reason to distinguish what kind of injection is being done. That is, any time there is AUX data and the HEADER_BUID_ID feature flag is set, and the AUX data is not being processed, then hit all DSOs. This patch does that.
--- tools/perf/builtin-inject.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
tools/perf/builtin-inject.c +8 -4
@@ -679,12 +679,16 @@ static int __cmd_inject(struct perf_inject *inject) ret =perf_session__process_events (session);if (!file_out->is_pipe) { -if (inject->build_ids) { +if (inject->build_ids)perf_header__set_feat (&session->header,HEADER_BUILD_ID ); -if (inject->have_auxtrace) -dsos__hit_all (session); - } +/* +* Keep all buildids when there is unprocessed AUX data because +* it is not known which ones the AUX trace hits. +*/ +if (perf_header__has_feat (&session->header,HEADER_BUILD_ID ) && + inject->have_auxtrace && !inject->itrace_synth_opts.set) +dsos__hit_all (session);/* * The AUX areas have been removed and replaced with * synthesized hardware events, so clear the feature flag and
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf inject: Hit all DSOs for AUX data in JIT and other cases
perf inject: Hit all DSOs for AUX data in JIT and other cases
Commit-ID: 640dad47988ec4b734d71934be103bb6e931279f Gitweb: http://git.kernel.org/tip/640dad47988ec4b734d71934be103bb6e931279f Author: Adrian Hunter <[email protected]> AuthorDate: Mon, 7 Mar 2016 16:44:38 -0300 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 8 Mar 2016 10:11:16 +0100
perf inject: Hit all DSOs for AUX data in JIT and other cases
Currently, when injecting build ids, if there is AUX data then 'perf inject' hits all DSOs because it is not known which DSOs the trace data would hit.
That needs to be done for JIT injection also, and in fact there is no reason to distinguish what kind of injection is being done. That is, any time there is AUX data and the HEADER_BUID_ID feature flag is set, and the AUX data is not being processed, then hit all DSOs. This patch does that.
--- tools/perf/builtin-inject.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
tools/perf/builtin-inject.c +8 -4
@@ -679,12 +679,16 @@ static int __cmd_inject(struct perf_inject *inject) ret =perf_session__process_events (session);if (!file_out->is_pipe) { -if (inject->build_ids) { +if (inject->build_ids)perf_header__set_feat (&session->header,HEADER_BUILD_ID ); -if (inject->have_auxtrace) -dsos__hit_all (session); - } +/* +* Keep all buildids when there is unprocessed AUX data because +* it is not known which ones the AUX trace hits. +*/ +if (perf_header__has_feat (&session->header,HEADER_BUILD_ID ) && + inject->have_auxtrace && !inject->itrace_synth_opts.set) +dsos__hit_all (session);/* * The AUX areas have been removed and replaced with * synthesized hardware events, so clear the feature flag and
Adrian Hunter
reviewerPATCH 2/8 perf session: Simplify tool stubs
In reply to Adrian HunterFrom: Adrian Hunter <[email protected]>
Some of the stubs are identical so just have one function for them.
--- tools/perf/util/session.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-)
tools/perf/util/session.c +7 -33
@@ -240,14 +240,6 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,return 0 ; } -static int process_build_id_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} -static int process_finished_round_stub (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -260,23 +252,6 @@ static int process_finished_round(struct perf_tool *tool,union perf_event *event, struct ordered_events *oe); -static int process_id_index_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *perf_session -__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} - -static int process_event_auxtrace_info_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} -static int skipn (int fd,off_t n) {char buf[4096 ];
@@ -303,10 +278,9 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,return event->auxtrace.size; } -static -int process_event_auxtrace_error_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) +static int process_event_op2_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) {dump_printf (": unhandled!\n" );return 0 ;
@@ -410,7 +384,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)if (tool->tracing_data ==NULL ) tool->tracing_data = process_event_synth_tracing_data_stub;if (tool->build_id ==NULL ) - tool->build_id = process_build_id_stub; + tool->build_id = process_event_op2_stub;if (tool->finished_round ==NULL ) {if (tool->ordered_events) tool->finished_round = process_finished_round;
@@ -418,13 +392,13 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->finished_round = process_finished_round_stub; }if (tool->id_index ==NULL ) - tool->id_index = process_id_index_stub; + tool->id_index = process_event_op2_stub;if (tool->auxtrace_info ==NULL ) - tool->auxtrace_info = process_event_auxtrace_info_stub; + tool->auxtrace_info = process_event_op2_stub;if (tool->auxtrace ==NULL ) tool->auxtrace = process_event_auxtrace_stub;if (tool->auxtrace_error ==NULL ) - tool->auxtrace_error = process_event_auxtrace_error_stub; + tool->auxtrace_error = process_event_op2_stub;if (tool->thread_map ==NULL ) tool->thread_map = process_event_thread_map_stub;if (tool->cpu_map ==NULL )
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v2 2/8 perf session: Simplify tool stubs
Some of the stubs are identical so just have one function for them.
---
Changes in V2:
Fixed "From" and "Signed-off-by" email addresses
tools/perf/util/session.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-)
tools/perf/util/session.c +7 -33
@@ -240,14 +240,6 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,return 0 ; } -static int process_build_id_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} -static int process_finished_round_stub (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -260,23 +252,6 @@ static int process_finished_round(struct perf_tool *tool,union perf_event *event, struct ordered_events *oe); -static int process_id_index_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *perf_session -__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} - -static int process_event_auxtrace_info_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} -static int skipn (int fd,off_t n) {char buf[4096 ];
@@ -303,10 +278,9 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,return event->auxtrace.size; } -static -int process_event_auxtrace_error_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) +static int process_event_op2_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) {dump_printf (": unhandled!\n" );return 0 ;
@@ -410,7 +384,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)if (tool->tracing_data ==NULL ) tool->tracing_data = process_event_synth_tracing_data_stub;if (tool->build_id ==NULL ) - tool->build_id = process_build_id_stub; + tool->build_id = process_event_op2_stub;if (tool->finished_round ==NULL ) {if (tool->ordered_events) tool->finished_round = process_finished_round;
@@ -418,13 +392,13 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->finished_round = process_finished_round_stub; }if (tool->id_index ==NULL ) - tool->id_index = process_id_index_stub; + tool->id_index = process_event_op2_stub;if (tool->auxtrace_info ==NULL ) - tool->auxtrace_info = process_event_auxtrace_info_stub; + tool->auxtrace_info = process_event_op2_stub;if (tool->auxtrace ==NULL ) tool->auxtrace = process_event_auxtrace_stub;if (tool->auxtrace_error ==NULL ) - tool->auxtrace_error = process_event_auxtrace_error_stub; + tool->auxtrace_error = process_event_op2_stub;if (tool->thread_map ==NULL ) tool->thread_map = process_event_thread_map_stub;if (tool->cpu_map ==NULL )
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf session: Simplify tool stubs
In reply to Adrian Hunterperf session: Simplify tool stubs
Commit-ID: 5fb0ac16c5091f48eecf1a77e461f6957a463d61 Gitweb: http://git.kernel.org/tip/5fb0ac16c5091f48eecf1a77e461f6957a463d61 Author: Adrian Hunter <[email protected]> AuthorDate: Mon, 7 Mar 2016 16:44:39 -0300 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 8 Mar 2016 10:11:17 +0100
perf session: Simplify tool stubs
Some of the stubs are identical so just have one function for them.
--- tools/perf/util/session.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-)
tools/perf/util/session.c +7 -33
@@ -240,14 +240,6 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,return 0 ; } -static int process_build_id_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} -static int process_finished_round_stub (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -260,23 +252,6 @@ static int process_finished_round(struct perf_tool *tool,union perf_event *event, struct ordered_events *oe); -static int process_id_index_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *perf_session -__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} - -static int process_event_auxtrace_info_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} -static int skipn (int fd,off_t n) {char buf[4096 ];
@@ -303,10 +278,9 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,return event->auxtrace.size; } -static -int process_event_auxtrace_error_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) +static int process_event_op2_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) {dump_printf (": unhandled!\n" );return 0 ;
@@ -410,7 +384,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)if (tool->tracing_data ==NULL ) tool->tracing_data = process_event_synth_tracing_data_stub;if (tool->build_id ==NULL ) - tool->build_id = process_build_id_stub; + tool->build_id = process_event_op2_stub;if (tool->finished_round ==NULL ) {if (tool->ordered_events) tool->finished_round = process_finished_round;
@@ -418,13 +392,13 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->finished_round = process_finished_round_stub; }if (tool->id_index ==NULL ) - tool->id_index = process_id_index_stub; + tool->id_index = process_event_op2_stub;if (tool->auxtrace_info ==NULL ) - tool->auxtrace_info = process_event_auxtrace_info_stub; + tool->auxtrace_info = process_event_op2_stub;if (tool->auxtrace ==NULL ) tool->auxtrace = process_event_auxtrace_stub;if (tool->auxtrace_error ==NULL ) - tool->auxtrace_error = process_event_auxtrace_error_stub; + tool->auxtrace_error = process_event_op2_stub;if (tool->thread_map ==NULL ) tool->thread_map = process_event_thread_map_stub;if (tool->cpu_map ==NULL )
Adrian Hunter
reviewerPATCH 3/8 perf tools: Add time conversion event
In reply to Adrian HunterFrom: Adrian Hunter <[email protected]>
Intel PT uses the time members from the perf_event_mmap_page to convert between TSC and perf time.
Due to a lack of foresight when Intel PT was implemented, those time members were recorded in the (implementation dependent) AUXTRACE_INFO event, the structure of which is generally inaccessible outside of the Intel PT decoder. However now the conversion between TSC and perf time is needed when processing a jitdump file when Intel PT has been used for tracing.
So add a user event to record the time members. 'perf record' will synthesize the event if the information is available. And session processing will put a copy of the event on the session so that tools like 'perf inject' can easily access it.
--- tools/perf/arch/x86/util/tsc.c | 31 +++++++++++++++++++++++++++++++ tools/perf/builtin-inject.c | 1 + tools/perf/builtin-record.c | 15 +++++++++++++++ tools/perf/util/event.c | 1 + tools/perf/util/event.h | 9 +++++++++ tools/perf/util/session.c | 6 ++++++ tools/perf/util/session.h | 1 + tools/perf/util/tool.h | 1 + tools/perf/util/tsc.h | 10 ++++++++++ 9 files changed, 75 insertions(+)
tools/perf/arch/x86/util/tsc.c +31 -0
@@ -46,3 +46,34 @@ u64 rdtsc(void)return low | ((u64 )high) <<32 ; } + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine) +{ +union perf_event event = { + .time_conv = { + .header = { + .type =PERF_RECORD_TIME_CONV , + .size =sizeof (struct time_conv_event ), + }, + }, + }; +struct perf_tsc_conversion tc; +int err; + + err =perf_read_tsc_conversion (pc, &tc); +if (err == -EOPNOTSUPP ) +return 0 ; +if (err) +return err; + +pr_debug2 ("Synthesizing TSC conversion information\n" ); + + event.time_conv.time_mult = tc.time_mult; + event.time_conv.time_shift = tc.time_shift; + event.time_conv.time_zero = tc.time_zero; + +return process (tool, &event,NULL , machine); +}
tools/perf/builtin-inject.c +1 -0
@@ -761,6 +761,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__repipe_op2_synth, .auxtrace = perf_event__repipe_auxtrace, .auxtrace_error = perf_event__repipe_op2_synth, + .time_conv = perf_event__repipe_op2_synth, .finished_round = perf_event__repipe_oe_synth, .build_id = perf_event__repipe_op2_synth, .id_index = perf_event__repipe_op2_synth,
tools/perf/builtin-record.c +15 -0
@@ -29,6 +29,7 @@#include "util/data.h" #include "util/perf_regs.h" #include "util/auxtrace.h" +#include "util/tsc.h" #include "util/parse-branch-options.h" #include "util/parse-regs-options.h" #include "util/llvm-utils.h"
@@ -512,6 +513,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused,static void snapshot_sig_handler (int sig); +int __weak +perf_event__synth_time_conv (const struct perf_event_mmap_page *pc__maybe_unused , +struct perf_tool *tool__maybe_unused , +perf_event__handler_t process__maybe_unused , +struct machine *machine__maybe_unused ) +{ +return 0 ; +} +static int record__synthesize (struct record *rec) {struct perf_session *session = rec->session;
@@ -549,6 +559,11 @@ static int record__synthesize(struct record *rec) } } + err =perf_event__synth_time_conv (rec->evlist->mmap[0 ].base, tool, + process_synthesized_event, machine); +if (err) + goto out; +if (rec->opts.full_auxtrace) { err =perf_event__synthesize_auxtrace_info (rec->itr, tool, session, process_synthesized_event);
tools/perf/util/event.c +1 -0
@@ -45,6 +45,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT] = "STAT", [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", + [PERF_RECORD_TIME_CONV] = "TIME_CONV", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +9 -0
@@ -232,6 +232,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_STAT =76 ,PERF_RECORD_STAT_ROUND =77 ,PERF_RECORD_EVENT_UPDATE =78 , +PERF_RECORD_TIME_CONV =79 , PERF_RECORD_HEADER_MAX };
@@ -468,6 +469,13 @@ struct stat_round_event {u64 time; }; +struct time_conv_event { +struct perf_event_header header; +u64 time_shift; +u64 time_mult; +u64 time_zero; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -496,6 +504,7 @@ union perf_event {struct stat_config_event stat_config;struct stat_event stat;struct stat_round_event stat_round; +struct time_conv_event time_conv; };void perf_event__print_totals (void );
tools/perf/util/session.c +6 -0
@@ -409,6 +409,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->stat = process_stat_stub;if (tool->stat_round ==NULL ) tool->stat_round = process_stat_round_stub; +if (tool->time_conv ==NULL ) + tool->time_conv = process_event_op2_stub; }static void swap_sample_id_all (union perf_event *event,void *data)
@@ -794,6 +796,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT] = perf_event__stat_swap, [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, + [PERF_RECORD_TIME_CONV] = perf_event__all64_swap, [PERF_RECORD_HEADER_MAX] = NULL, };
@@ -1342,6 +1345,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,return tool->stat (tool, event, session);case PERF_RECORD_STAT_ROUND :return tool->stat_round (tool, event, session); +case PERF_RECORD_TIME_CONV : + session->time_conv = event->time_conv; +return tool->time_conv (tool, event, session);default :return -EINVAL ; }
tools/perf/util/session.h +1 -0
@@ -26,6 +26,7 @@ struct perf_session {struct itrace_synth_opts *itrace_synth_opts;struct list_head auxtrace_index;struct trace_event tevent; +struct time_conv_event time_conv;bool repipe;bool one_mmap;void *one_mmap_addr;
tools/perf/util/tool.h +1 -0
@@ -57,6 +57,7 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, + time_conv, thread_map, cpu_map, stat_config,
tools/perf/util/tsc.h +10 -0
@@ -3,10 +3,20 @@#include <linux/types.h> +#include "event.h" #include "../arch/x86/util/tsc.h" u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);u64 rdtsc (void ); +struct perf_event_mmap_page ; +struct perf_tool ; +struct machine ; + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine); +#endif
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v2 3/8 perf tools: Add time conversion event
Intel PT uses the time members from the perf_event_mmap_page to convert between TSC and perf time.
Due to a lack of foresight when Intel PT was implemented, those time members were recorded in the (implementation dependent) AUXTRACE_INFO event, the structure of which is generally inaccessible outside of the Intel PT decoder. However now the conversion between TSC and perf time is needed when processing a jitdump file when Intel PT has been used for tracing.
So add a user event to record the time members. 'perf record' will synthesize the event if the information is available. And session processing will put a copy of the event on the session so that tools like 'perf inject' can easily access it.
---
Changes in V2:
Fixed "From" and "Signed-off-by" email addresses
tools/perf/arch/x86/util/tsc.c | 31 +++++++++++++++++++++++++++++++ tools/perf/builtin-inject.c | 1 + tools/perf/builtin-record.c | 15 +++++++++++++++ tools/perf/util/event.c | 1 + tools/perf/util/event.h | 9 +++++++++ tools/perf/util/session.c | 6 ++++++ tools/perf/util/session.h | 1 + tools/perf/util/tool.h | 1 + tools/perf/util/tsc.h | 10 ++++++++++ 9 files changed, 75 insertions(+)
tools/perf/arch/x86/util/tsc.c +31 -0
@@ -46,3 +46,34 @@ u64 rdtsc(void)return low | ((u64 )high) <<32 ; } + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine) +{ +union perf_event event = { + .time_conv = { + .header = { + .type =PERF_RECORD_TIME_CONV , + .size =sizeof (struct time_conv_event ), + }, + }, + }; +struct perf_tsc_conversion tc; +int err; + + err =perf_read_tsc_conversion (pc, &tc); +if (err == -EOPNOTSUPP ) +return 0 ; +if (err) +return err; + +pr_debug2 ("Synthesizing TSC conversion information\n" ); + + event.time_conv.time_mult = tc.time_mult; + event.time_conv.time_shift = tc.time_shift; + event.time_conv.time_zero = tc.time_zero; + +return process (tool, &event,NULL , machine); +}
tools/perf/builtin-inject.c +1 -0
@@ -761,6 +761,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__repipe_op2_synth, .auxtrace = perf_event__repipe_auxtrace, .auxtrace_error = perf_event__repipe_op2_synth, + .time_conv = perf_event__repipe_op2_synth, .finished_round = perf_event__repipe_oe_synth, .build_id = perf_event__repipe_op2_synth, .id_index = perf_event__repipe_op2_synth,
tools/perf/builtin-record.c +15 -0
@@ -29,6 +29,7 @@#include "util/data.h" #include "util/perf_regs.h" #include "util/auxtrace.h" +#include "util/tsc.h" #include "util/parse-branch-options.h" #include "util/parse-regs-options.h" #include "util/llvm-utils.h"
@@ -512,6 +513,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused,static void snapshot_sig_handler (int sig); +int __weak +perf_event__synth_time_conv (const struct perf_event_mmap_page *pc__maybe_unused , +struct perf_tool *tool__maybe_unused , +perf_event__handler_t process__maybe_unused , +struct machine *machine__maybe_unused ) +{ +return 0 ; +} +static int record__synthesize (struct record *rec) {struct perf_session *session = rec->session;
@@ -549,6 +559,11 @@ static int record__synthesize(struct record *rec) } } + err =perf_event__synth_time_conv (rec->evlist->mmap[0 ].base, tool, + process_synthesized_event, machine); +if (err) + goto out; +if (rec->opts.full_auxtrace) { err =perf_event__synthesize_auxtrace_info (rec->itr, tool, session, process_synthesized_event);
tools/perf/util/event.c +1 -0
@@ -45,6 +45,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT] = "STAT", [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", + [PERF_RECORD_TIME_CONV] = "TIME_CONV", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +9 -0
@@ -232,6 +232,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_STAT =76 ,PERF_RECORD_STAT_ROUND =77 ,PERF_RECORD_EVENT_UPDATE =78 , +PERF_RECORD_TIME_CONV =79 , PERF_RECORD_HEADER_MAX };
@@ -468,6 +469,13 @@ struct stat_round_event {u64 time; }; +struct time_conv_event { +struct perf_event_header header; +u64 time_shift; +u64 time_mult; +u64 time_zero; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -496,6 +504,7 @@ union perf_event {struct stat_config_event stat_config;struct stat_event stat;struct stat_round_event stat_round; +struct time_conv_event time_conv; };void perf_event__print_totals (void );
tools/perf/util/session.c +6 -0
@@ -409,6 +409,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->stat = process_stat_stub;if (tool->stat_round ==NULL ) tool->stat_round = process_stat_round_stub; +if (tool->time_conv ==NULL ) + tool->time_conv = process_event_op2_stub; }static void swap_sample_id_all (union perf_event *event,void *data)
@@ -794,6 +796,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT] = perf_event__stat_swap, [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, + [PERF_RECORD_TIME_CONV] = perf_event__all64_swap, [PERF_RECORD_HEADER_MAX] = NULL, };
@@ -1342,6 +1345,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,return tool->stat (tool, event, session);case PERF_RECORD_STAT_ROUND :return tool->stat_round (tool, event, session); +case PERF_RECORD_TIME_CONV : + session->time_conv = event->time_conv; +return tool->time_conv (tool, event, session);default :return -EINVAL ; }
tools/perf/util/session.h +1 -0
@@ -26,6 +26,7 @@ struct perf_session {struct itrace_synth_opts *itrace_synth_opts;struct list_head auxtrace_index;struct trace_event tevent; +struct time_conv_event time_conv;bool repipe;bool one_mmap;void *one_mmap_addr;
tools/perf/util/tool.h +1 -0
@@ -57,6 +57,7 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, + time_conv, thread_map, cpu_map, stat_config,
tools/perf/util/tsc.h +10 -0
@@ -3,10 +3,20 @@#include <linux/types.h> +#include "event.h" #include "../arch/x86/util/tsc.h" u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);u64 rdtsc (void ); +struct perf_event_mmap_page ; +struct perf_tool ; +struct machine ; + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine); +#endif
Signature · 1 line
1.9.1
Adrian Hunter
reviewerRe: [PATCH V2 3/8] perf tools: Add time conversion event
Quoted 11 lines · Adrian Hunter
Intel PT uses the time members from the
perf_event_mmap_pageto convert between TSC and perf time.Due to a lack of foresight when Intel PT was implemented, those time members were recorded in the (implementation dependent)
AUXTRACE_INFOevent, the structure of which is generally inaccessible outside of the Intel PT decoder. However now the conversion between TSC and perf time is needed when processing a jitdump file when Intel PT has been used for tracing.
Quoted 6 lines
So add a user event to record the time members. 'perf record' will synthesize the event if the information is available. And session processing will put a copy of the event on the session so that tools like 'perf inject' can easily access it.
Signed-off-by Adrian Hunter <[email protected]>
This patch (patch 3) and the V2 versions of patches 6 and 7 i.e.
[PATCH V2 3/8] perf tools: Add time conversion event [PATCH V2 6/8] perf jit: Add support for using TSC as a timestamp [PATCH V2 7/8] perf intel-pt/bts: Define JITDUMP_USE_ARCH_TIMESTAMP
still apply. Do you have any comments?
Quoted 235 lines
---
Changes in V2:
Fixed "From" and "Signed-off-by" email addresses
tools/perf/arch/x86/util/tsc.c | 31 +++++++++++++++++++++++++++++++ tools/perf/builtin-inject.c | 1 + tools/perf/builtin-record.c | 15 +++++++++++++++ tools/perf/util/event.c | 1 + tools/perf/util/event.h | 9 +++++++++ tools/perf/util/session.c | 6 ++++++ tools/perf/util/session.h | 1 + tools/perf/util/tool.h | 1 + tools/perf/util/tsc.h | 10 ++++++++++ 9 files changed, 75 insertions(+)tools/perf/arch/x86/util/tsc.c +31
-0@@ -46,3 +46,34 @@ u64 rdtsc(void)return low | ((u64 )high) <<32 ; } + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine) +{ +union perf_event event = { + .time_conv = { + .header = { + .type =PERF_RECORD_TIME_CONV , + .size =sizeof (struct time_conv_event ), + }, + }, + }; +struct perf_tsc_conversion tc; +int err; + + err =perf_read_tsc_conversion (pc, &tc); +if (err == -EOPNOTSUPP ) +return 0 ; +if (err) +return err; + +pr_debug2 ("Synthesizing TSC conversion information\n" ); + + event.time_conv.time_mult = tc.time_mult; + event.time_conv.time_shift = tc.time_shift; + event.time_conv.time_zero = tc.time_zero; + +return process (tool, &event,NULL , machine); +}tools/perf/builtin-inject.c +1
-0@@ -761,6 +761,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__repipe_op2_synth, .auxtrace = perf_event__repipe_auxtrace, .auxtrace_error = perf_event__repipe_op2_synth, + .time_conv = perf_event__repipe_op2_synth, .finished_round = perf_event__repipe_oe_synth, .build_id = perf_event__repipe_op2_synth, .id_index = perf_event__repipe_op2_synth,tools/perf/builtin-record.c +15
-0@@ -29,6 +29,7 @@#include "util/data.h" #include "util/perf_regs.h" #include "util/auxtrace.h" +#include "util/tsc.h" #include "util/parse-branch-options.h" #include "util/parse-regs-options.h" #include "util/llvm-utils.h" @@ -512,6 +513,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused,static void snapshot_sig_handler (int sig); +int __weak +perf_event__synth_time_conv (const struct perf_event_mmap_page *pc__maybe_unused , +struct perf_tool *tool__maybe_unused , +perf_event__handler_t process__maybe_unused , +struct machine *machine__maybe_unused ) +{ +return 0 ; +} +static int record__synthesize (struct record *rec) {struct perf_session *session = rec->session;@@ -549,6 +559,11 @@ static int record__synthesize(struct record *rec) } } + err =perf_event__synth_time_conv (rec->evlist->mmap[0 ].base, tool, + process_synthesized_event, machine); +if (err) + goto out; +if (rec->opts.full_auxtrace) { err =perf_event__synthesize_auxtrace_info (rec->itr, tool, session, process_synthesized_event);tools/perf/util/event.c +1
-0@@ -45,6 +45,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT] = "STAT", [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", + [PERF_RECORD_TIME_CONV] = "TIME_CONV", };const char *perf_event__name (unsigned int id)tools/perf/util/event.h +9
-0@@ -232,6 +232,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_STAT =76 ,PERF_RECORD_STAT_ROUND =77 ,PERF_RECORD_EVENT_UPDATE =78 , +PERF_RECORD_TIME_CONV =79 , PERF_RECORD_HEADER_MAX };@@ -468,6 +469,13 @@ struct stat_round_event {u64 time; }; +struct time_conv_event { +struct perf_event_header header; +u64 time_shift; +u64 time_mult; +u64 time_zero; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;@@ -496,6 +504,7 @@ union perf_event {struct stat_config_event stat_config;struct stat_event stat;struct stat_round_event stat_round; +struct time_conv_event time_conv; };void perf_event__print_totals (void );tools/perf/util/session.c +6
-0@@ -409,6 +409,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->stat = process_stat_stub;if (tool->stat_round ==NULL ) tool->stat_round = process_stat_round_stub; +if (tool->time_conv ==NULL ) + tool->time_conv = process_event_op2_stub; }static void swap_sample_id_all (union perf_event *event,void *data)@@ -794,6 +796,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT] = perf_event__stat_swap, [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, + [PERF_RECORD_TIME_CONV] = perf_event__all64_swap, [PERF_RECORD_HEADER_MAX] = NULL, };@@ -1342,6 +1345,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,return tool->stat (tool, event, session);case PERF_RECORD_STAT_ROUND :return tool->stat_round (tool, event, session); +case PERF_RECORD_TIME_CONV : + session->time_conv = event->time_conv; +return tool->time_conv (tool, event, session);default :return -EINVAL ; }tools/perf/util/session.h +1
-0@@ -26,6 +26,7 @@ struct perf_session {struct itrace_synth_opts *itrace_synth_opts;struct list_head auxtrace_index;struct trace_event tevent; +struct time_conv_event time_conv;bool repipe;bool one_mmap;void *one_mmap_addr;tools/perf/util/tool.h +1
-0@@ -57,6 +57,7 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, + time_conv, thread_map, cpu_map, stat_config,tools/perf/util/tsc.h +10
-0@@ -3,10 +3,20 @@#include <linux/types.h> +#include "event.h" #include "../arch/x86/util/tsc.h" u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);u64 rdtsc (void ); +struct perf_event_mmap_page ; +struct perf_tool ; +struct machine ; + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine); +#endif
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V2 3/8] perf tools: Add time conversion event
Em Thu, Mar 31, 2016 at 09:33:04AM +0300, Adrian Hunter escreveu:
Quoted 19 lines · Adrian Hunter
Quoted 11 lines
Intel PT uses the time members from the
perf_event_mmap_pageto convert between TSC and perf time.Due to a lack of foresight when Intel PT was implemented, those time members were recorded in the (implementation dependent)
AUXTRACE_INFOevent, the structure of which is generally inaccessible outside of the Intel PT decoder. However now the conversion between TSC and perf time is needed when processing a jitdump file when Intel PT has been used for tracing.Quoted 6 lines
So add a user event to record the time members. 'perf record' will synthesize the event if the information is available. And session processing will put a copy of the event on the session so that tools like 'perf inject' can easily access it.
Signed-off-by Adrian Hunter <[email protected]>
Quoted 7 lines
This patch (patch 3) and the V2 versions of patches 6 and 7 i.e.
[PATCH V2 3/8] perf tools: Add time conversion event [PATCH V2 6/8] perf jit: Add support for using TSC as a timestamp [PATCH V2 7/8] perf intel-pt/bts: Define
JITDUMP_USE_ARCH_TIMESTAMPstill apply. Do you have any comments?
I was waiting for Stephane to say something, but judging from the fact that this is just making existing infrastructure to be available more widely, I am applying it.
- Arnaldo
Quoted 235 lines
Quoted 235 lines
---
Changes in V2:
Fixed "From" and "Signed-off-by" email addresses
tools/perf/arch/x86/util/tsc.c | 31 +++++++++++++++++++++++++++++++ tools/perf/builtin-inject.c | 1 + tools/perf/builtin-record.c | 15 +++++++++++++++ tools/perf/util/event.c | 1 + tools/perf/util/event.h | 9 +++++++++ tools/perf/util/session.c | 6 ++++++ tools/perf/util/session.h | 1 + tools/perf/util/tool.h | 1 + tools/perf/util/tsc.h | 10 ++++++++++ 9 files changed, 75 insertions(+)tools/perf/arch/x86/util/tsc.c +31
-0@@ -46,3 +46,34 @@ u64 rdtsc(void)return low | ((u64 )high) <<32 ; } + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine) +{ +union perf_event event = { + .time_conv = { + .header = { + .type =PERF_RECORD_TIME_CONV , + .size =sizeof (struct time_conv_event ), + }, + }, + }; +struct perf_tsc_conversion tc; +int err; + + err =perf_read_tsc_conversion (pc, &tc); +if (err == -EOPNOTSUPP ) +return 0 ; +if (err) +return err; + +pr_debug2 ("Synthesizing TSC conversion information\n" ); + + event.time_conv.time_mult = tc.time_mult; + event.time_conv.time_shift = tc.time_shift; + event.time_conv.time_zero = tc.time_zero; + +return process (tool, &event,NULL , machine); +}tools/perf/builtin-inject.c +1
-0@@ -761,6 +761,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__repipe_op2_synth, .auxtrace = perf_event__repipe_auxtrace, .auxtrace_error = perf_event__repipe_op2_synth, + .time_conv = perf_event__repipe_op2_synth, .finished_round = perf_event__repipe_oe_synth, .build_id = perf_event__repipe_op2_synth, .id_index = perf_event__repipe_op2_synth,tools/perf/builtin-record.c +15
-0@@ -29,6 +29,7 @@#include "util/data.h" #include "util/perf_regs.h" #include "util/auxtrace.h" +#include "util/tsc.h" #include "util/parse-branch-options.h" #include "util/parse-regs-options.h" #include "util/llvm-utils.h" @@ -512,6 +513,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused,static void snapshot_sig_handler (int sig); +int __weak +perf_event__synth_time_conv (const struct perf_event_mmap_page *pc__maybe_unused , +struct perf_tool *tool__maybe_unused , +perf_event__handler_t process__maybe_unused , +struct machine *machine__maybe_unused ) +{ +return 0 ; +} +static int record__synthesize (struct record *rec) {struct perf_session *session = rec->session;@@ -549,6 +559,11 @@ static int record__synthesize(struct record *rec) } } + err =perf_event__synth_time_conv (rec->evlist->mmap[0 ].base, tool, + process_synthesized_event, machine); +if (err) + goto out; +if (rec->opts.full_auxtrace) { err =perf_event__synthesize_auxtrace_info (rec->itr, tool, session, process_synthesized_event);tools/perf/util/event.c +1
-0@@ -45,6 +45,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT] = "STAT", [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", + [PERF_RECORD_TIME_CONV] = "TIME_CONV", };const char *perf_event__name (unsigned int id)tools/perf/util/event.h +9
-0@@ -232,6 +232,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_STAT =76 ,PERF_RECORD_STAT_ROUND =77 ,PERF_RECORD_EVENT_UPDATE =78 , +PERF_RECORD_TIME_CONV =79 , PERF_RECORD_HEADER_MAX };@@ -468,6 +469,13 @@ struct stat_round_event {u64 time; }; +struct time_conv_event { +struct perf_event_header header; +u64 time_shift; +u64 time_mult; +u64 time_zero; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;@@ -496,6 +504,7 @@ union perf_event {struct stat_config_event stat_config;struct stat_event stat;struct stat_round_event stat_round; +struct time_conv_event time_conv; };void perf_event__print_totals (void );tools/perf/util/session.c +6
-0@@ -409,6 +409,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->stat = process_stat_stub;if (tool->stat_round ==NULL ) tool->stat_round = process_stat_round_stub; +if (tool->time_conv ==NULL ) + tool->time_conv = process_event_op2_stub; }static void swap_sample_id_all (union perf_event *event,void *data)@@ -794,6 +796,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT] = perf_event__stat_swap, [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, + [PERF_RECORD_TIME_CONV] = perf_event__all64_swap, [PERF_RECORD_HEADER_MAX] = NULL, };@@ -1342,6 +1345,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,return tool->stat (tool, event, session);case PERF_RECORD_STAT_ROUND :return tool->stat_round (tool, event, session); +case PERF_RECORD_TIME_CONV : + session->time_conv = event->time_conv; +return tool->time_conv (tool, event, session);default :return -EINVAL ; }tools/perf/util/session.h +1
-0@@ -26,6 +26,7 @@ struct perf_session {struct itrace_synth_opts *itrace_synth_opts;struct list_head auxtrace_index;struct trace_event tevent; +struct time_conv_event time_conv;bool repipe;bool one_mmap;void *one_mmap_addr;tools/perf/util/tool.h +1
-0@@ -57,6 +57,7 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, + time_conv, thread_map, cpu_map, stat_config,tools/perf/util/tsc.h +10
-0@@ -3,10 +3,20 @@#include <linux/types.h> +#include "event.h" #include "../arch/x86/util/tsc.h" u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);u64 rdtsc (void ); +struct perf_event_mmap_page ; +struct perf_tool ; +struct machine ; + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine); +#endif
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf tools: Add time conversion event
In reply to Adrian Hunterperf tools: Add time conversion event
Commit-ID: 46bc29b970f0011a9099077f1db8f3540aa829fe Gitweb: http://git.kernel.org/tip/46bc29b970f0011a9099077f1db8f3540aa829fe Author: Adrian Hunter <[email protected]> AuthorDate: Tue, 8 Mar 2016 10:38:44 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 31 Mar 2016 10:52:24 -0300
perf tools: Add time conversion event
Intel PT uses the time members from the perf_event_mmap_page to convert between TSC and perf time.
Due to a lack of foresight when Intel PT was implemented, those time members were recorded in the (implementation dependent) AUXTRACE_INFO event, the structure of which is generally inaccessible outside of the Intel PT decoder. However now the conversion between TSC and perf time is needed when processing a jitdump file when Intel PT has been used for tracing.
So add a user event to record the time members. 'perf record' will synthesize the event if the information is available. And session processing will put a copy of the event on the session so that tools like 'perf inject' can easily access it.
--- tools/perf/arch/x86/util/tsc.c | 31 +++++++++++++++++++++++++++++++ tools/perf/builtin-inject.c | 1 + tools/perf/builtin-record.c | 15 +++++++++++++++ tools/perf/util/event.c | 1 + tools/perf/util/event.h | 9 +++++++++ tools/perf/util/session.c | 6 ++++++ tools/perf/util/session.h | 1 + tools/perf/util/tool.h | 1 + tools/perf/util/tsc.h | 10 ++++++++++ 9 files changed, 75 insertions(+)
tools/perf/arch/x86/util/tsc.c +31 -0
@@ -46,3 +46,34 @@ u64 rdtsc(void)return low | ((u64 )high) <<32 ; } + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine) +{ +union perf_event event = { + .time_conv = { + .header = { + .type =PERF_RECORD_TIME_CONV , + .size =sizeof (struct time_conv_event ), + }, + }, + }; +struct perf_tsc_conversion tc; +int err; + + err =perf_read_tsc_conversion (pc, &tc); +if (err == -EOPNOTSUPP ) +return 0 ; +if (err) +return err; + +pr_debug2 ("Synthesizing TSC conversion information\n" ); + + event.time_conv.time_mult = tc.time_mult; + event.time_conv.time_shift = tc.time_shift; + event.time_conv.time_zero = tc.time_zero; + +return process (tool, &event,NULL , machine); +}
tools/perf/builtin-inject.c +1 -0
@@ -748,6 +748,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .auxtrace_info = perf_event__repipe_op2_synth, .auxtrace = perf_event__repipe_auxtrace, .auxtrace_error = perf_event__repipe_op2_synth, + .time_conv = perf_event__repipe_op2_synth, .finished_round = perf_event__repipe_oe_synth, .build_id = perf_event__repipe_op2_synth, .id_index = perf_event__repipe_op2_synth,
tools/perf/builtin-record.c +15 -0
@@ -29,6 +29,7 @@#include "util/data.h" #include "util/perf_regs.h" #include "util/auxtrace.h" +#include "util/tsc.h" #include "util/parse-branch-options.h" #include "util/parse-regs-options.h" #include "util/llvm-utils.h"
@@ -512,6 +513,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused,static void snapshot_sig_handler (int sig); +int __weak +perf_event__synth_time_conv (const struct perf_event_mmap_page *pc__maybe_unused , +struct perf_tool *tool__maybe_unused , +perf_event__handler_t process__maybe_unused , +struct machine *machine__maybe_unused ) +{ +return 0 ; +} +static int record__synthesize (struct record *rec) {struct perf_session *session = rec->session;
@@ -549,6 +559,11 @@ static int record__synthesize(struct record *rec) } } + err =perf_event__synth_time_conv (rec->evlist->mmap[0 ].base, tool, + process_synthesized_event, machine); +if (err) + goto out; +if (rec->opts.full_auxtrace) { err =perf_event__synthesize_auxtrace_info (rec->itr, tool, session, process_synthesized_event);
tools/perf/util/event.c +1 -0
@@ -45,6 +45,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_STAT] = "STAT", [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", + [PERF_RECORD_TIME_CONV] = "TIME_CONV", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +9 -0
@@ -233,6 +233,7 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_STAT =76 ,PERF_RECORD_STAT_ROUND =77 ,PERF_RECORD_EVENT_UPDATE =78 , +PERF_RECORD_TIME_CONV =79 , PERF_RECORD_HEADER_MAX };
@@ -469,6 +470,13 @@ struct stat_round_event {u64 time; }; +struct time_conv_event { +struct perf_event_header header; +u64 time_shift; +u64 time_mult; +u64 time_zero; +}; +union perf_event {struct perf_event_header header;struct mmap_event mmap;
@@ -497,6 +505,7 @@ union perf_event {struct stat_config_event stat_config;struct stat_event stat;struct stat_round_event stat_round; +struct time_conv_event time_conv; };void perf_event__print_totals (void );
tools/perf/util/session.c +6 -0
@@ -409,6 +409,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->stat = process_stat_stub;if (tool->stat_round ==NULL ) tool->stat_round = process_stat_round_stub; +if (tool->time_conv ==NULL ) + tool->time_conv = process_event_op2_stub; }static void swap_sample_id_all (union perf_event *event,void *data)
@@ -794,6 +796,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT] = perf_event__stat_swap, [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, + [PERF_RECORD_TIME_CONV] = perf_event__all64_swap, [PERF_RECORD_HEADER_MAX] = NULL, };
@@ -1341,6 +1344,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,return tool->stat (tool, event, session);case PERF_RECORD_STAT_ROUND :return tool->stat_round (tool, event, session); +case PERF_RECORD_TIME_CONV : + session->time_conv = event->time_conv; +return tool->time_conv (tool, event, session);default :return -EINVAL ; }
tools/perf/util/session.h +1 -0
@@ -26,6 +26,7 @@ struct perf_session {struct itrace_synth_opts *itrace_synth_opts;struct list_head auxtrace_index;struct trace_event tevent; +struct time_conv_event time_conv;bool repipe;bool one_mmap;void *one_mmap_addr;
tools/perf/util/tool.h +1 -0
@@ -57,6 +57,7 @@ struct perf_tool { id_index, auxtrace_info, auxtrace_error, + time_conv, thread_map, cpu_map, stat_config,
tools/perf/util/tsc.h +10 -0
@@ -3,10 +3,20 @@#include <linux/types.h> +#include "event.h" #include "../arch/x86/util/tsc.h" u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);u64 rdtsc (void ); +struct perf_event_mmap_page ; +struct perf_tool ; +struct machine ; + +int perf_event__synth_time_conv (const struct perf_event_mmap_page *pc, +struct perf_tool *tool, +perf_event__handler_t process, +struct machine *machine); +#endif
Adrian Hunter
reviewerPATCH 4/8 perf jit: Let jit_process() return errors
In reply to Adrian HunterIn preparation for moving clockid validation into jit_process().
Previously a return value of zero meant the processing had been done and non-zero meant either the processing was not done (i.e. not the jitdump file mmap event) or an error occurred.
Change it so that zero means the processing was not done, one means the processing was done and successful, and negative values are an error.
--- tools/perf/builtin-inject.c | 16 ++++++++++++---- tools/perf/util/jitdump.c | 6 ++++-- 2 files changed, 16 insertions(+), 6 deletions(-)
tools/perf/builtin-inject.c +12 -4
@@ -253,12 +253,16 @@ static int perf_event__jit_repipe_mmap(struct perf_tool *tool, { struct perf_inject *inject = container_of(tool, struct perf_inject, tool);u64 n =0 ; +int ret;/* * if jit marker, then inject jit mmaps and generate ELF images */ -if (!jit_process (inject->session, &inject->output, machine, - event->mmap.filename, sample->pid, &n)) { + ret =jit_process (inject->session, &inject->output, machine, + event->mmap.filename, sample->pid, &n); +if (ret <0 ) +return ret; +if (ret) { inject->bytes_written += n;return 0 ; }
@@ -287,12 +291,16 @@ static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, { struct perf_inject *inject = container_of(tool, struct perf_inject, tool);u64 n =0 ; +int ret;/* * if jit marker, then inject jit mmaps and generate ELF images */ -if (!jit_process (inject->session, &inject->output, machine, - event->mmap2.filename, sample->pid, &n)) { + ret =jit_process (inject->session, &inject->output, machine, + event->mmap2.filename, sample->pid, &n); +if (ret <0 ) +return ret; +if (ret) { inject->bytes_written += n;return 0 ; }
tools/perf/util/jitdump.c +4 -2
@@ -647,7 +647,7 @@ jit_process(struct perf_session *session,* first, detect marker mmap (i.e., the jitdump mmap) */ if (jit_detect (filename, pid)) -return -1 ; +return 0 ;memset (&jd,0 ,sizeof (jd));
@@ -665,8 +665,10 @@ jit_process(struct perf_session *session, *nbytes =0 ; ret =jit_inject (&jd, filename); -if (!ret) +if (!ret) { *nbytes = jd.bytes_written; + ret =1 ; + }return ret; }
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf jit: Let jit_process() return errors
perf jit: Let jit_process() return errors
Commit-ID: 570735b33d122bcb259ef67c6aa63e5609af5752 Gitweb: http://git.kernel.org/tip/570735b33d122bcb259ef67c6aa63e5609af5752 Author: Adrian Hunter <[email protected]> AuthorDate: Mon, 7 Mar 2016 16:44:40 -0300 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 8 Mar 2016 10:11:17 +0100
perf jit: Let jit_process() return errors
In preparation for moving clockid validation into jit_process().
Previously a return value of zero meant the processing had been done and non-zero meant either the processing was not done (i.e. not the jitdump file mmap event) or an error occurred.
Change it so that zero means the processing was not done, one means the processing was done and successful, and negative values are an error.
--- tools/perf/builtin-inject.c | 16 ++++++++++++---- tools/perf/util/jitdump.c | 6 ++++-- 2 files changed, 16 insertions(+), 6 deletions(-)
tools/perf/builtin-inject.c +12 -4
@@ -253,12 +253,16 @@ static int perf_event__jit_repipe_mmap(struct perf_tool *tool, { struct perf_inject *inject = container_of(tool, struct perf_inject, tool);u64 n =0 ; +int ret;/* * if jit marker, then inject jit mmaps and generate ELF images */ -if (!jit_process (inject->session, &inject->output, machine, - event->mmap.filename, sample->pid, &n)) { + ret =jit_process (inject->session, &inject->output, machine, + event->mmap.filename, sample->pid, &n); +if (ret <0 ) +return ret; +if (ret) { inject->bytes_written += n;return 0 ; }
@@ -287,12 +291,16 @@ static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, { struct perf_inject *inject = container_of(tool, struct perf_inject, tool);u64 n =0 ; +int ret;/* * if jit marker, then inject jit mmaps and generate ELF images */ -if (!jit_process (inject->session, &inject->output, machine, - event->mmap2.filename, sample->pid, &n)) { + ret =jit_process (inject->session, &inject->output, machine, + event->mmap2.filename, sample->pid, &n); +if (ret <0 ) +return ret; +if (ret) { inject->bytes_written += n;return 0 ; }
tools/perf/util/jitdump.c +4 -2
@@ -647,7 +647,7 @@ jit_process(struct perf_session *session,* first, detect marker mmap (i.e., the jitdump mmap) */ if (jit_detect (filename, pid)) -return -1 ; +return 0 ;memset (&jd,0 ,sizeof (jd));
@@ -665,8 +665,10 @@ jit_process(struct perf_session *session, *nbytes =0 ; ret =jit_inject (&jd, filename); -if (!ret) +if (!ret) { *nbytes = jd.bytes_written; + ret =1 ; + }return ret; }
Adrian Hunter
reviewerPATCH 5/8 perf jit: Move clockid validation
In reply to Adrian HunterFrom: Adrian Hunter <[email protected]>
Move clockid validation into jit_process() so it can later be made conditional.
--- tools/perf/builtin-inject.c | 24 ------------------------ tools/perf/util/jitdump.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 24 deletions(-)
tools/perf/builtin-inject.c +0 -24
@@ -729,23 +729,6 @@ static int __cmd_inject(struct perf_inject *inject)return ret; } -#ifdef HAVE_LIBELF_SUPPORT -static int -jit_validate_events (struct perf_session *session) -{ -struct perf_evsel *evsel; - -/* -* check that all events use CLOCK_MONOTONIC -*/ -evlist__for_each (session->evlist, evsel) { -if (evsel->attr.use_clockid ==0 || evsel->attr.clockid !=CLOCK_MONOTONIC ) -return -1 ; - } -return 0 ; -} -#endif -int cmd_inject (int argc,const char **argv,const char *prefix__maybe_unused ) {struct perf_inject inject = {
@@ -853,13 +836,6 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) }#ifdef HAVE_LIBELF_SUPPORT if (inject.jit_mode) { -/* -* validate event is using the correct clockid -*/ -if (jit_validate_events (inject.session)) { -fprintf (stderr,"error, jitted code must be sampled with perf record -k 1\n" ); -return -1 ; - } inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap; inject.tool.ordered_events = true;
tools/perf/util/jitdump.c +23 -0
@@ -99,6 +99,21 @@ jit_close(struct jit_buf_desc *jd) }static int +jit_validate_events (struct perf_session *session) +{ +struct perf_evsel *evsel; + +/* +* check that all events use CLOCK_MONOTONIC +*/ +evlist__for_each (session->evlist, evsel) { +if (evsel->attr.use_clockid ==0 || evsel->attr.clockid !=CLOCK_MONOTONIC ) +return -1 ; + } +return 0 ; +} + +static int jit_open (struct jit_buf_desc *jd,const char *name) {struct jitheader header;
@@ -157,6 +172,14 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } +/* +* validate event is using the correct clockid +*/ +if (jit_validate_events (jd->session)) { +pr_err ("error, jitted code must be sampled with perf record -k 1\n" ); + goto error; + } + bs = header.total_size -sizeof (header);if (bs > bsz) {
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v2 5/8 perf jit: Move clockid validation
Move clockid validation into jit_process() so it can later be made conditional.
---
Changes in V2:
Fixed "From" and "Signed-off-by" email addresses
tools/perf/builtin-inject.c | 24 ------------------------ tools/perf/util/jitdump.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 24 deletions(-)
tools/perf/builtin-inject.c +0 -24
@@ -729,23 +729,6 @@ static int __cmd_inject(struct perf_inject *inject)return ret; } -#ifdef HAVE_LIBELF_SUPPORT -static int -jit_validate_events (struct perf_session *session) -{ -struct perf_evsel *evsel; - -/* -* check that all events use CLOCK_MONOTONIC -*/ -evlist__for_each (session->evlist, evsel) { -if (evsel->attr.use_clockid ==0 || evsel->attr.clockid !=CLOCK_MONOTONIC ) -return -1 ; - } -return 0 ; -} -#endif -int cmd_inject (int argc,const char **argv,const char *prefix__maybe_unused ) {struct perf_inject inject = {
@@ -853,13 +836,6 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) }#ifdef HAVE_LIBELF_SUPPORT if (inject.jit_mode) { -/* -* validate event is using the correct clockid -*/ -if (jit_validate_events (inject.session)) { -fprintf (stderr,"error, jitted code must be sampled with perf record -k 1\n" ); -return -1 ; - } inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap; inject.tool.ordered_events = true;
tools/perf/util/jitdump.c +23 -0
@@ -99,6 +99,21 @@ jit_close(struct jit_buf_desc *jd) }static int +jit_validate_events (struct perf_session *session) +{ +struct perf_evsel *evsel; + +/* +* check that all events use CLOCK_MONOTONIC +*/ +evlist__for_each (session->evlist, evsel) { +if (evsel->attr.use_clockid ==0 || evsel->attr.clockid !=CLOCK_MONOTONIC ) +return -1 ; + } +return 0 ; +} + +static int jit_open (struct jit_buf_desc *jd,const char *name) {struct jitheader header;
@@ -157,6 +172,14 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } +/* +* validate event is using the correct clockid +*/ +if (jit_validate_events (jd->session)) { +pr_err ("error, jitted code must be sampled with perf record -k 1\n" ); + goto error; + } + bs = header.total_size -sizeof (header);if (bs > bsz) {
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf jit: Move clockid validation
In reply to Adrian Hunterperf jit: Move clockid validation
Commit-ID: 4a018cc47932ef1e68a0600ce3ac100df70fab2a Gitweb: http://git.kernel.org/tip/4a018cc47932ef1e68a0600ce3ac100df70fab2a Author: Adrian Hunter <[email protected]> AuthorDate: Mon, 7 Mar 2016 16:44:41 -0300 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 8 Mar 2016 10:11:17 +0100
perf jit: Move clockid validation
Move clockid validation into jit_process() so it can later be made conditional.
--- tools/perf/builtin-inject.c | 24 ------------------------ tools/perf/util/jitdump.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 24 deletions(-)
tools/perf/builtin-inject.c +0 -24
@@ -729,23 +729,6 @@ static int __cmd_inject(struct perf_inject *inject)return ret; } -#ifdef HAVE_LIBELF_SUPPORT -static int -jit_validate_events (struct perf_session *session) -{ -struct perf_evsel *evsel; - -/* -* check that all events use CLOCK_MONOTONIC -*/ -evlist__for_each (session->evlist, evsel) { -if (evsel->attr.use_clockid ==0 || evsel->attr.clockid !=CLOCK_MONOTONIC ) -return -1 ; - } -return 0 ; -} -#endif -int cmd_inject (int argc,const char **argv,const char *prefix__maybe_unused ) {struct perf_inject inject = {
@@ -852,13 +835,6 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) }#ifdef HAVE_LIBELF_SUPPORT if (inject.jit_mode) { -/* -* validate event is using the correct clockid -*/ -if (jit_validate_events (inject.session)) { -fprintf (stderr,"error, jitted code must be sampled with perf record -k 1\n" ); -return -1 ; - } inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap; inject.tool.ordered_events = true;
tools/perf/util/jitdump.c +23 -0
@@ -99,6 +99,21 @@ jit_close(struct jit_buf_desc *jd) }static int +jit_validate_events (struct perf_session *session) +{ +struct perf_evsel *evsel; + +/* +* check that all events use CLOCK_MONOTONIC +*/ +evlist__for_each (session->evlist, evsel) { +if (evsel->attr.use_clockid ==0 || evsel->attr.clockid !=CLOCK_MONOTONIC ) +return -1 ; + } +return 0 ; +} + +static int jit_open (struct jit_buf_desc *jd,const char *name) {struct jitheader header;
@@ -157,6 +172,14 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } +/* +* validate event is using the correct clockid +*/ +if (jit_validate_events (jd->session)) { +pr_err ("error, jitted code must be sampled with perf record -k 1\n" ); + goto error; + } + bs = header.total_size -sizeof (header);if (bs > bsz) {
Adrian Hunter
reviewerPATCH 6/8 perf jit: Add support for using TSC as a timestamp
In reply to Adrian HunterFrom: Adrian Hunter <[email protected]>
Intel PT uses TSC as a timestamp, so add support for using TSC instead of the monotonic clock. Use of TSC is selected by an environment variable "JITDUMP_USE_ARCH_TIMESTAMP" and flagged in the jitdump file with flag JITDUMP_FLAGS_ARCH_TIMESTAMP.
--- tools/perf/jvmti/jvmti_agent.c | 43 ++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/jitdump.c | 37 +++++++++++++++++++++++++++++++----- tools/perf/util/jitdump.h | 3 +++ 3 files changed, 76 insertions(+), 7 deletions(-)
tools/perf/jvmti/jvmti_agent.c +41 -2
@@ -92,6 +92,22 @@ error:return ret; } +static int use_arch_timestamp; + +static inline uint64_t +get_arch_timestamp (void ) +{ +#if defined(__i386__) || defined(__x86_64__) +unsigned int low, high; + + asmvolatile ("rdtsc" :"=a" (low),"=d" (high)); + +return low | ((uint64_t )high) <<32 ; +#else +return 0 ; +#endif +} +#define NSEC_PER_SEC 1000000000static int perf_clk_id =CLOCK_MONOTONIC ;
@@ -107,6 +123,9 @@ perf_get_timestamp(void)struct timespec ts;int ret; +if (use_arch_timestamp) +return get_arch_timestamp (); + ret =clock_gettime (perf_clk_id, &ts);if (ret)return 0 ;
@@ -203,6 +222,17 @@ perf_close_marker_file(void)munmap (marker_addr, pgsz); } +static void +init_arch_timestamp (void ) +{ +char *str =getenv ("JITDUMP_USE_ARCH_TIMESTAMP" ); + +if (!str || !*str || !strcmp (str,"0" )) +return ; + + use_arch_timestamp =1 ; +} +void *jvmti_open (void ) {int pad_cnt;
@@ -211,11 +241,17 @@ void *jvmti_open(void)int fd;FILE *fp; +init_arch_timestamp (); +/* * check if clockid is supported */ -if (!perf_get_timestamp ()) -warnx ("jvmti: kernel does not support %d clock id" , perf_clk_id); +if (!perf_get_timestamp ()) { +if (use_arch_timestamp) +warnx ("jvmti: arch timestamp not supported" ); +else +warnx ("jvmti: kernel does not support %d clock id" , perf_clk_id); + }memset (&header,0 ,sizeof (header));
@@ -263,6 +299,9 @@ void *jvmti_open(void) header.timestamp =perf_get_timestamp (); +if (use_arch_timestamp) + header.flags |=JITDUMP_FLAGS_ARCH_TIMESTAMP ; +if (!fwrite (&header,sizeof (header),1 , fp)) {warn ("jvmti: cannot write dumpfile header" ); goto error;
tools/perf/util/jitdump.c +32 -5
@@ -17,6 +17,7 @@#include "strlist.h" #include <elf.h> +#include "tsc.h" #include "session.h" #include "jit.h" #include "jitdump.h"
@@ -33,6 +34,7 @@ struct jit_buf_desc {size_t bufsize;FILE *in;bool needs_bswap;/* handles cross-endianess */ +bool use_arch_timestamp;void *debug_data;size_t nr_debug_entries;uint32_t code_load_count;
@@ -158,13 +160,16 @@ jit_open(struct jit_buf_desc *jd, const char *name) header.flags =bswap_64 (header.flags); } + jd->use_arch_timestamp = header.flags &JITDUMP_FLAGS_ARCH_TIMESTAMP ; +if (verbose >2 ) -pr_debug ("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n" , +pr_debug ("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n" , header.version, header.total_size, (unsigned long long )header.timestamp, header.pid, - header.elf_mach); + header.elf_mach, + jd->use_arch_timestamp);if (header.flags &JITDUMP_FLAGS_RESERVED ) { pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
@@ -172,10 +177,15 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } +if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) { +pr_err ("jitdump file uses arch timestamps but there is no timestamp conversion\n" ); + goto error; + } +/* * validate event is using the correct clockid */ -if (jit_validate_events (jd->session)) { +if (!jd->use_arch_timestamp &&jit_validate_events (jd->session)) {pr_err ("error, jitted code must be sampled with perf record -k 1\n" ); goto error; }
@@ -329,6 +339,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)return 0 ; } +static uint64_t convert_timestamp (struct jit_buf_desc *jd,uint64_t timestamp) +{ +struct perf_tsc_conversion tc; + +if (!jd->use_arch_timestamp) +return timestamp; + + tc.time_shift = jd->session->time_conv.time_shift; + tc.time_mult = jd->session->time_conv.time_mult; + tc.time_zero = jd->session->time_conv.time_zero; + +if (!tc.time_mult) +return 0 ; + +return tsc_to_perf_time (timestamp, &tc); +} +static int jit_repipe_code_load (struct jit_buf_desc *jd,union jr_entry *jr) {struct perf_sample sample;
@@ -410,7 +437,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) id->tid = tid; }if (jd->sample_type &PERF_SAMPLE_TIME ) - id->time = jr->load.p.timestamp; + id->time =convert_timestamp (jd, jr->load.p.timestamp);/* * create pseudo sample to induce dso hit increment
@@ -498,7 +525,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) id->tid = tid; }if (jd->sample_type &PERF_SAMPLE_TIME ) - id->time = jr->load.p.timestamp; + id->time =convert_timestamp (jd, jr->load.p.timestamp);/* * create pseudo sample to induce dso hit increment
tools/perf/util/jitdump.h +3 -0
@@ -23,9 +23,12 @@#define JITHEADER_VERSION 1enum jitdump_flags_bits { +JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT ,JITDUMP_FLAGS_MAX_BIT , }; +#define JITDUMP_FLAGS_ARCH_TIMESTAMP (1ULL << JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT) +#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \ (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0)
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v2 6/8 perf jit: Add support for using TSC as a timestamp
Intel PT uses TSC as a timestamp, so add support for using TSC instead of the monotonic clock. Use of TSC is selected by an environment variable "JITDUMP_USE_ARCH_TIMESTAMP" and flagged in the jitdump file with flag JITDUMP_FLAGS_ARCH_TIMESTAMP.
---
Changes in V2:
Fixed "From" and "Signed-off-by" email addresses
tools/perf/jvmti/jvmti_agent.c | 43 ++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/jitdump.c | 37 +++++++++++++++++++++++++++++++----- tools/perf/util/jitdump.h | 3 +++ 3 files changed, 76 insertions(+), 7 deletions(-)
tools/perf/jvmti/jvmti_agent.c +41 -2
@@ -92,6 +92,22 @@ error:return ret; } +static int use_arch_timestamp; + +static inline uint64_t +get_arch_timestamp (void ) +{ +#if defined(__i386__) || defined(__x86_64__) +unsigned int low, high; + + asmvolatile ("rdtsc" :"=a" (low),"=d" (high)); + +return low | ((uint64_t )high) <<32 ; +#else +return 0 ; +#endif +} +#define NSEC_PER_SEC 1000000000static int perf_clk_id =CLOCK_MONOTONIC ;
@@ -107,6 +123,9 @@ perf_get_timestamp(void)struct timespec ts;int ret; +if (use_arch_timestamp) +return get_arch_timestamp (); + ret =clock_gettime (perf_clk_id, &ts);if (ret)return 0 ;
@@ -203,6 +222,17 @@ perf_close_marker_file(void)munmap (marker_addr, pgsz); } +static void +init_arch_timestamp (void ) +{ +char *str =getenv ("JITDUMP_USE_ARCH_TIMESTAMP" ); + +if (!str || !*str || !strcmp (str,"0" )) +return ; + + use_arch_timestamp =1 ; +} +void *jvmti_open (void ) {int pad_cnt;
@@ -211,11 +241,17 @@ void *jvmti_open(void)int fd;FILE *fp; +init_arch_timestamp (); +/* * check if clockid is supported */ -if (!perf_get_timestamp ()) -warnx ("jvmti: kernel does not support %d clock id" , perf_clk_id); +if (!perf_get_timestamp ()) { +if (use_arch_timestamp) +warnx ("jvmti: arch timestamp not supported" ); +else +warnx ("jvmti: kernel does not support %d clock id" , perf_clk_id); + }memset (&header,0 ,sizeof (header));
@@ -263,6 +299,9 @@ void *jvmti_open(void) header.timestamp =perf_get_timestamp (); +if (use_arch_timestamp) + header.flags |=JITDUMP_FLAGS_ARCH_TIMESTAMP ; +if (!fwrite (&header,sizeof (header),1 , fp)) {warn ("jvmti: cannot write dumpfile header" ); goto error;
tools/perf/util/jitdump.c +32 -5
@@ -17,6 +17,7 @@#include "strlist.h" #include <elf.h> +#include "tsc.h" #include "session.h" #include "jit.h" #include "jitdump.h"
@@ -33,6 +34,7 @@ struct jit_buf_desc {size_t bufsize;FILE *in;bool needs_bswap;/* handles cross-endianess */ +bool use_arch_timestamp;void *debug_data;size_t nr_debug_entries;uint32_t code_load_count;
@@ -158,13 +160,16 @@ jit_open(struct jit_buf_desc *jd, const char *name) header.flags =bswap_64 (header.flags); } + jd->use_arch_timestamp = header.flags &JITDUMP_FLAGS_ARCH_TIMESTAMP ; +if (verbose >2 ) -pr_debug ("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n" , +pr_debug ("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n" , header.version, header.total_size, (unsigned long long )header.timestamp, header.pid, - header.elf_mach); + header.elf_mach, + jd->use_arch_timestamp);if (header.flags &JITDUMP_FLAGS_RESERVED ) { pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
@@ -172,10 +177,15 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } +if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) { +pr_err ("jitdump file uses arch timestamps but there is no timestamp conversion\n" ); + goto error; + } +/* * validate event is using the correct clockid */ -if (jit_validate_events (jd->session)) { +if (!jd->use_arch_timestamp &&jit_validate_events (jd->session)) {pr_err ("error, jitted code must be sampled with perf record -k 1\n" ); goto error; }
@@ -329,6 +339,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)return 0 ; } +static uint64_t convert_timestamp (struct jit_buf_desc *jd,uint64_t timestamp) +{ +struct perf_tsc_conversion tc; + +if (!jd->use_arch_timestamp) +return timestamp; + + tc.time_shift = jd->session->time_conv.time_shift; + tc.time_mult = jd->session->time_conv.time_mult; + tc.time_zero = jd->session->time_conv.time_zero; + +if (!tc.time_mult) +return 0 ; + +return tsc_to_perf_time (timestamp, &tc); +} +static int jit_repipe_code_load (struct jit_buf_desc *jd,union jr_entry *jr) {struct perf_sample sample;
@@ -410,7 +437,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) id->tid = tid; }if (jd->sample_type &PERF_SAMPLE_TIME ) - id->time = jr->load.p.timestamp; + id->time =convert_timestamp (jd, jr->load.p.timestamp);/* * create pseudo sample to induce dso hit increment
@@ -498,7 +525,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) id->tid = tid; }if (jd->sample_type &PERF_SAMPLE_TIME ) - id->time = jr->load.p.timestamp; + id->time =convert_timestamp (jd, jr->load.p.timestamp);/* * create pseudo sample to induce dso hit increment
tools/perf/util/jitdump.h +3 -0
@@ -23,9 +23,12 @@#define JITHEADER_VERSION 1enum jitdump_flags_bits { +JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT ,JITDUMP_FLAGS_MAX_BIT , }; +#define JITDUMP_FLAGS_ARCH_TIMESTAMP (1ULL << JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT) +#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \ (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0)
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH 7/8 perf intel-pt/bts: Define JITDUMP_USE_ARCH_TIMESTAMP
In reply to Adrian HunterFrom: Adrian Hunter <[email protected]>
For Intel PT / BTS, define the environment variable that selects TSC timestamps in the jitdump file.
--- tools/perf/arch/x86/util/intel-bts.c | 5 +++++ tools/perf/arch/x86/util/intel-pt.c | 5 +++++ 2 files changed, 10 insertions(+)
tools/perf/arch/x86/util/intel-bts.c +5 -0
@@ -438,6 +438,11 @@ struct auxtrace_record *intel_bts_recording_init(int *err)if (!intel_bts_pmu)return NULL ; +if (setenv ("JITDUMP_USE_ARCH_TIMESTAMP" ,"1" ,1 )) { + *err = -errno; +return NULL ; + } + btsr =zalloc (sizeof (struct intel_bts_recording ));if (!btsr) { *err = -ENOMEM ;
tools/perf/arch/x86/util/intel-pt.c +5 -0
@@ -1027,6 +1027,11 @@ struct auxtrace_record *intel_pt_recording_init(int *err)if (!intel_pt_pmu)return NULL ; +if (setenv ("JITDUMP_USE_ARCH_TIMESTAMP" ,"1" ,1 )) { + *err = -errno; +return NULL ; + } + ptr =zalloc (sizeof (struct intel_pt_recording ));if (!ptr) { *err = -ENOMEM ;
Signature · 1 line
1.9.1
Adrian Hunter
reviewerPATCH v2 7/8 perf intel-pt/bts: Define JITDUMP_USE_ARCH_TIMESTAMP
For Intel PT / BTS, define the environment variable that selects TSC timestamps in the jitdump file.
---
Changes in V2:
Fixed "From" and "Signed-off-by" email addresses
tools/perf/arch/x86/util/intel-bts.c | 5 +++++ tools/perf/arch/x86/util/intel-pt.c | 5 +++++ 2 files changed, 10 insertions(+)
tools/perf/arch/x86/util/intel-bts.c +5 -0
@@ -438,6 +438,11 @@ struct auxtrace_record *intel_bts_recording_init(int *err)if (!intel_bts_pmu)return NULL ; +if (setenv ("JITDUMP_USE_ARCH_TIMESTAMP" ,"1" ,1 )) { + *err = -errno; +return NULL ; + } + btsr =zalloc (sizeof (struct intel_bts_recording ));if (!btsr) { *err = -ENOMEM ;
tools/perf/arch/x86/util/intel-pt.c +5 -0
@@ -1027,6 +1027,11 @@ struct auxtrace_record *intel_pt_recording_init(int *err)if (!intel_pt_pmu)return NULL ; +if (setenv ("JITDUMP_USE_ARCH_TIMESTAMP" ,"1" ,1 )) { + *err = -errno; +return NULL ; + } + ptr =zalloc (sizeof (struct intel_pt_recording ));if (!ptr) { *err = -ENOMEM ;
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt/bts: Define JITDUMP_USE_ARCH_TIMESTAMP
perf intel-pt/bts: Define JITDUMP_USE_ARCH_TIMESTAMP
Commit-ID: bd0c7a54219cc3745ce7f36970d8e5ffb3f8d80e Gitweb: http://git.kernel.org/tip/bd0c7a54219cc3745ce7f36970d8e5ffb3f8d80e Author: Adrian Hunter <[email protected]> AuthorDate: Tue, 8 Mar 2016 10:38:53 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 1 Apr 2016 18:46:24 -0300
perf intel-pt/bts: Define JITDUMP_USE_ARCH_TIMESTAMP
For Intel PT / BTS, define the environment variable that selects TSC timestamps in the jitdump file.
--- tools/perf/arch/x86/util/intel-bts.c | 5 +++++ tools/perf/arch/x86/util/intel-pt.c | 5 +++++ 2 files changed, 10 insertions(+)
tools/perf/arch/x86/util/intel-bts.c +5 -0
@@ -438,6 +438,11 @@ struct auxtrace_record *intel_bts_recording_init(int *err)if (!intel_bts_pmu)return NULL ; +if (setenv ("JITDUMP_USE_ARCH_TIMESTAMP" ,"1" ,1 )) { + *err = -errno; +return NULL ; + } + btsr =zalloc (sizeof (struct intel_bts_recording ));if (!btsr) { *err = -ENOMEM ;
tools/perf/arch/x86/util/intel-pt.c +5 -0
@@ -1027,6 +1027,11 @@ struct auxtrace_record *intel_pt_recording_init(int *err)if (!intel_pt_pmu)return NULL ; +if (setenv ("JITDUMP_USE_ARCH_TIMESTAMP" ,"1" ,1 )) { + *err = -errno; +return NULL ; + } + ptr =zalloc (sizeof (struct intel_pt_recording ));if (!ptr) { *err = -ENOMEM ;
Adrian Hunter
reviewerPATCH 8/8 perf tools: Use 64-bit shifts with (TSC) time conversion
In reply to Adrian HunterCommit b9511cd761fa ("perf/x86: Fix time_shift in perf_event_mmap_page") altered the time conversion algorithms documented in the perf_event.h header file, to use 64-bit shifts. That was done to make the code more future-proof (i.e. some time in the future a 32-bit shift could be allowed). Reflect those changes in perf tools.
--- tools/perf/arch/x86/tests/rdpmc.c | 2 +- tools/perf/util/tsc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
tools/perf/arch/x86/tests/rdpmc.c +1 -1
@@ -59,7 +59,7 @@ static u64 mmap_read_self(void *addr)u64 quot, rem; quot = (cyc >> time_shift); - rem = cyc & ((1 << time_shift) -1 ); + rem = cyc & (((u64 )1 << time_shift) -1 ); delta = time_offset + quot * time_mult + ((rem * time_mult) >> time_shift);
tools/perf/util/tsc.c +1 -1
@@ -19,7 +19,7 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)u64 quot, rem; quot = cyc >> tc->time_shift; - rem = cyc & ((1 << tc->time_shift) -1 ); + rem = cyc & (((u64 )1 << tc->time_shift) -1 );return tc->time_zero + quot * tc->time_mult + ((rem * tc->time_mult) >> tc->time_shift); }
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf tools: Use 64-bit shifts with (TSC) time conversion
perf tools: Use 64-bit shifts with (TSC) time conversion
Commit-ID: a23f96ee4d51ebd50b83ce0dbb5d04898fb8e3cb Gitweb: http://git.kernel.org/tip/a23f96ee4d51ebd50b83ce0dbb5d04898fb8e3cb Author: Adrian Hunter <[email protected]> AuthorDate: Mon, 7 Mar 2016 16:44:42 -0300 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 8 Mar 2016 10:11:18 +0100
perf tools: Use 64-bit shifts with (TSC) time conversion
Commit b9511cd761fa ("perf/x86: Fix time_shift in perf_event_mmap_page") altered the time conversion algorithms documented in the perf_event.h header file, to use 64-bit shifts. That was done to make the code more future-proof (i.e. some time in the future a 32-bit shift could be allowed). Reflect those changes in perf tools.
--- tools/perf/arch/x86/tests/rdpmc.c | 2 +- tools/perf/util/tsc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
tools/perf/arch/x86/tests/rdpmc.c +1 -1
@@ -59,7 +59,7 @@ static u64 mmap_read_self(void *addr)u64 quot, rem; quot = (cyc >> time_shift); - rem = cyc & ((1 << time_shift) -1 ); + rem = cyc & (((u64 )1 << time_shift) -1 ); delta = time_offset + quot * time_mult + ((rem * time_mult) >> time_shift);
tools/perf/util/tsc.c +1 -1
@@ -19,7 +19,7 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)u64 quot, rem; quot = cyc >> tc->time_shift; - rem = cyc & ((1 << tc->time_shift) -1 ); + rem = cyc & (((u64 )1 << tc->time_shift) -1 );return tc->time_zero + quot * tc->time_mult + ((rem * tc->time_mult) >> tc->time_shift); }
Adrian Hunter
reviewerHi
I have just sent V2 of patches 2, 3, 5, 6, 7 because the email address was wrong in the "From" and "Signed-off-by".
I realize you have already processed some of the patches. Very sorry for the inconvenience.
Regards
Adrian
PATCH 1/1 perf tools: Fix build errors on tsc functions for archs other than x86
Build errors on aarch64:
libperf.a(libperf-in.o): In function `convert_timestamp':
util/jitdump.c:356: undefined reference to `tsc_to_perf_time'
collect2: error: ld returned 1 exit status Makefile.perf:347: recipe for target 'perf' failed make[1]: *** [perf] Error 1
Makefile:68: recipe for target 'all' failed
make: *** [all] Error 2
Since tsc conversion functions were moved out from arch dir, move 'tsc.h' out from x86 dir to make it possible to compile for other archs.
--- tools/perf/arch/x86/util/tsc.c | 1 - tools/perf/arch/x86/util/tsc.h | 17 ----------------- tools/perf/util/Build | 3 +-- tools/perf/util/tsc.h | 11 ++++++++++- 4 files changed, 11 insertions(+), 21 deletions(-) delete mode 100644 tools/perf/arch/x86/util/tsc.h
tools/perf/arch/x86/util/tsc.c +0 -1
@@ -7,7 +7,6 @@#include <linux/types.h> #include "../../util/debug.h" #include "../../util/tsc.h" -#include "tsc.h" int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc,struct perf_tsc_conversion *tc)
tools/perf/arch/x86/util/tsc.h deleted +0 -17
@@ -1,17 +0,0 @@ -#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ -#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ - -#include <linux/types.h> - -struct perf_tsc_conversion { -u16 time_shift; -u32 time_mult; -u64 time_zero; -}; - -struct perf_event_mmap_page ; - -int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, -struct perf_tsc_conversion *tc); - -#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
tools/perf/util/Build +1 -2
@@ -69,8 +69,7 @@ libperf-y += stat-shadow.o libperf-y += record.o libperf-y += srcline.o libperf-y += data.o -libperf-$(CONFIG_X86) += tsc.o -libperf-$(CONFIG_AUXTRACE) += tsc.o +libperf-y += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o libperf-$(CONFIG_AUXTRACE) += auxtrace.o
tools/perf/util/tsc.h +10 -1
@@ -4,7 +4,16 @@#include <linux/types.h> #include "event.h" -#include "../arch/x86/util/tsc.h" + +struct perf_tsc_conversion { +u16 time_shift; +u32 time_mult; +u64 time_zero; +}; +struct perf_event_mmap_page ; + +int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, +struct perf_tsc_conversion *tc);u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);
Signature · 1 line
1.8.5.2
Re: [PATCH] perf tools: Fix build errors on tsc functions for archs other than x86
Quoted 9 lines · He Kuang
Build errors on aarch64:
libperf.a(libperf-in.o): In function `convert_timestamp':
util/jitdump.c:356: undefined reference to `tsc_to_perf_time'
collect2: error: ld returned 1 exit status Makefile.perf:347: recipe for target 'perf' failed make[1]: *** [perf] Error 1
Makefile:68: recipe for target 'all' failed
make: *** [all] Error 2
Sorry about that :-(
Quoted 3 lines
Since tsc conversion functions were moved out from arch dir, move '
tsc.h' out from x86 dir to make it possible to compile for other archs.
So this is the case where data can be collected on x86 and then processed on another arch.
Originally, it wasn't wanted to be compiled in:
http://marc.info/?l=linux-kernel&m=142445842131011
But that has been causing problems:
http://marc.info/?l=linux-kernel&m=144109627003194
So this seems better.
Quoted 2 lines
Signed-off-by He Kuang <[email protected]>
Quoted 80 lines
--- tools/perf/arch/x86/util/tsc.c | 1 - tools/perf/arch/x86/util/tsc.h | 17 ----------------- tools/perf/util/Build | 3 +-- tools/perf/util/tsc.h | 11 ++++++++++- 4 files changed, 11 insertions(+), 21 deletions(-) delete mode 100644 tools/perf/arch/x86/util/tsc.htools/perf/arch/x86/util/tsc.c +0
-1@@ -7,7 +7,6 @@#include <linux/types.h> #include "../../util/debug.h" #include "../../util/tsc.h" -#include "tsc.h" int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc,struct perf_tsc_conversion *tc)tools/perf/arch/x86/util/tsc.h deleted +0
-17@@ -1,17 +0,0 @@ -#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ -#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ - -#include <linux/types.h> - -struct perf_tsc_conversion { -u16 time_shift; -u32 time_mult; -u64 time_zero; -}; - -struct perf_event_mmap_page ; - -int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, -struct perf_tsc_conversion *tc); - -#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */ tools/perf/util/Build +1
-2@@ -69,8 +69,7 @@ libperf-y += stat-shadow.o libperf-y += record.o libperf-y += srcline.o libperf-y += data.o -libperf-$(CONFIG_X86) += tsc.o -libperf-$(CONFIG_AUXTRACE) += tsc.o +libperf-y += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o libperf-$(CONFIG_AUXTRACE) += auxtrace.otools/perf/util/tsc.h +10
-1@@ -4,7 +4,16 @@#include <linux/types.h> #include "event.h" -#include "../arch/x86/util/tsc.h" + +struct perf_tsc_conversion { +u16 time_shift; +u32 time_mult; +u64 time_zero; +}; +struct perf_event_mmap_page ; + +int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, +struct perf_tsc_conversion *tc);u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);
Arnaldo Carvalho de Melo
maintainerRe: [PATCH] perf tools: Fix build errors on tsc functions for archs other than x86
In reply to He KuangEm Fri, Apr 01, 2016 at 03:49:32AM +0000, He Kuang escreveu:
Quoted 9 lines
Build errors on aarch64:
libperf.a(libperf-in.o): In function `convert_timestamp':
util/jitdump.c:356: undefined reference to `tsc_to_perf_time'
collect2: error: ld returned 1 exit status Makefile.perf:347: recipe for target 'perf' failed make[1]: *** [perf] Error 1
Makefile:68: recipe for target 'all' failed
make: *** [all] Error 2
Got it, my cross-compile environment for aarch64 doesn't build jitdump.c because it needs a package I haven't found in ubuntu:
config/Makefile:416: No libcrypto.h found, disables jitted code injection, please install libssl-devel or libssl-dev
minimal-ubuntu-x-arm64: Ok
BTW, He, what environment do you use to build for arm64, is it a cross compile one? Yocto?
- Arnaldo
Quoted 85 lines
Since tsc conversion functions were moved out from arch dir, move '
tsc.h' out from x86 dir to make it possible to compile for other archs.Signed-off-by He Kuang <[email protected]>--- tools/perf/arch/x86/util/tsc.c | 1 - tools/perf/arch/x86/util/tsc.h | 17 ----------------- tools/perf/util/Build | 3 +-- tools/perf/util/tsc.h | 11 ++++++++++- 4 files changed, 11 insertions(+), 21 deletions(-) delete mode 100644 tools/perf/arch/x86/util/tsc.htools/perf/arch/x86/util/tsc.c +0
-1@@ -7,7 +7,6 @@#include <linux/types.h> #include "../../util/debug.h" #include "../../util/tsc.h" -#include "tsc.h" int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc,struct perf_tsc_conversion *tc)tools/perf/arch/x86/util/tsc.h deleted +0
-17@@ -1,17 +0,0 @@ -#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ -#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ - -#include <linux/types.h> - -struct perf_tsc_conversion { -u16 time_shift; -u32 time_mult; -u64 time_zero; -}; - -struct perf_event_mmap_page ; - -int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, -struct perf_tsc_conversion *tc); - -#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */ tools/perf/util/Build +1
-2@@ -69,8 +69,7 @@ libperf-y += stat-shadow.o libperf-y += record.o libperf-y += srcline.o libperf-y += data.o -libperf-$(CONFIG_X86) += tsc.o -libperf-$(CONFIG_AUXTRACE) += tsc.o +libperf-y += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o libperf-$(CONFIG_AUXTRACE) += auxtrace.otools/perf/util/tsc.h +10
-1@@ -4,7 +4,16 @@#include <linux/types.h> #include "event.h" -#include "../arch/x86/util/tsc.h" + +struct perf_tsc_conversion { +u16 time_shift; +u32 time_mult; +u64 time_zero; +}; +struct perf_event_mmap_page ; + +int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, +struct perf_tsc_conversion *tc);u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);Signature · 1 line
1.8.5.2
Re: [PATCH] perf tools: Fix build errors on tsc functions for archs other than x86
hi,
Quoted 10 lines · Arnaldo Carvalho de Melo
Em Fri, Apr 01, 2016 at 03:49:32AM +0000, He Kuang escreveu:
Quoted 9 lines
Build errors on aarch64:
libperf.a(libperf-in.o): In function `convert_timestamp':
util/jitdump.c:356: undefined reference to `tsc_to_perf_time'
collect2: error: ld returned 1 exit status Makefile.perf:347: recipe for target 'perf' failed make[1]: *** [perf] Error 1
Makefile:68: recipe for target 'all' failed
make: *** [all] Error 2
Quoted 8 lines
Got it, my cross-compile environment for aarch64 doesn't build
jitdump.cbecause it needs a package I haven't found in ubuntu:config/Makefile:416: No
libcrypto.hfound, disables jitted code injection, please install libssl-devel or libssl-dev
minimal-ubuntu-x-arm64: OkBTW, He, what environment do you use to build for arm64, is it a cross compile one? Yocto?
I use buildroot, though my colleague prefers yocto(oxygen).
In my environment, libcrypto is on.
... libcrypto: [ on ]
Quoted 90 lines
- Arnaldo
Quoted 85 lines
Since tsc conversion functions were moved out from arch dir, move '
tsc.h' out from x86 dir to make it possible to compile for other archs.Signed-off-by He Kuang <[email protected]>--- tools/perf/arch/x86/util/tsc.c | 1 - tools/perf/arch/x86/util/tsc.h | 17 ----------------- tools/perf/util/Build | 3 +-- tools/perf/util/tsc.h | 11 ++++++++++- 4 files changed, 11 insertions(+), 21 deletions(-)delete mode 100644
tools/perf/arch/x86/util/tsc.htools/perf/arch/x86/util/tsc.c +0
-1@@ -7,7 +7,6 @@#include <linux/types.h> #include "../../util/debug.h" #include "../../util/tsc.h" -#include "tsc.h" int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc,struct perf_tsc_conversion *tc)tools/perf/arch/x86/util/tsc.h deleted +0
-17@@ -1,17 +0,0 @@ -#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ -#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ - -#include <linux/types.h> - -struct perf_tsc_conversion { -u16 time_shift; -u32 time_mult; -u64 time_zero; -}; - -struct perf_event_mmap_page ; - -int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, -struct perf_tsc_conversion *tc); - -#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */ tools/perf/util/Build +1
-2@@ -69,8 +69,7 @@ libperf-y += stat-shadow.o libperf-y += record.o libperf-y += srcline.o libperf-y += data.o -libperf-$(CONFIG_X86) += tsc.o -libperf-$(CONFIG_AUXTRACE) += tsc.o +libperf-y += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o libperf-$(CONFIG_AUXTRACE) += auxtrace.otools/perf/util/tsc.h +10
-1@@ -4,7 +4,16 @@#include <linux/types.h> #include "event.h" -#include "../arch/x86/util/tsc.h" + +struct perf_tsc_conversion { +u16 time_shift; +u32 time_mult; +u64 time_zero; +}; +struct perf_event_mmap_page ; + +int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, +struct perf_tsc_conversion *tc);u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);Signature · 1 line
1.8.5.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH] perf tools: Fix build errors on tsc functions for archs other than x86
In reply to Arnaldo Carvalho de MeloEm Fri, Apr 01, 2016 at 10:13:12AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 11 lines
Em Fri, Apr 01, 2016 at 03:49:32AM +0000, He Kuang escreveu:
Quoted 9 lines
Build errors on aarch64:
libperf.a(libperf-in.o): In function `convert_timestamp':
util/jitdump.c:356: undefined reference to `tsc_to_perf_time'
collect2: error: ld returned 1 exit status Makefile.perf:347: recipe for target 'perf' failed make[1]: *** [perf] Error 1
Makefile:68: recipe for target 'all' failed
make: *** [all] Error 2
Quoted 8 lines
Got it, my cross-compile environment for aarch64 doesn't build
jitdump.cbecause it needs a package I haven't found in ubuntu:config/Makefile:416: No
libcrypto.hfound, disables jitted code injection, please install libssl-devel or libssl-dev
minimal-ubuntu-x-arm64: OkBTW, He, what environment do you use to build for arm64, is it a cross compile one? Yocto?
Adrian, BTW, Ok with this? I'm adding a:
And would appreciate your Acked-by.
Thanks,
- Arnaldo
Re: [PATCH] perf tools: Fix build errors on tsc functions for archs other than x86
Quoted 18 lines · Arnaldo Carvalho de Melo
Em Fri, Apr 01, 2016 at 10:13:12AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 17 lines
Em Fri, Apr 01, 2016 at 03:49:32AM +0000, He Kuang escreveu:
Quoted 9 lines
Build errors on aarch64:
libperf.a(libperf-in.o): In function `convert_timestamp':
util/jitdump.c:356: undefined reference to `tsc_to_perf_time'
collect2: error: ld returned 1 exit status Makefile.perf:347: recipe for target 'perf' failed make[1]: *** [perf] Error 1
Makefile:68: recipe for target 'all' failed
make: *** [all] Error 2Got it, my cross-compile environment for aarch64 doesn't build
jitdump.cbecause it needs a package I haven't found in ubuntu:config/Makefile:416: No
libcrypto.hfound, disables jitted code injection, please install libssl-devel or libssl-dev
minimal-ubuntu-x-arm64: Ok
Quoted 8 lines
Quoted 2 lines
BTW, He, what environment do you use to build for arm64, is it a cross compile one? Yocto?
Adrian, BTW, Ok with this? I'm adding a:
Fixes d3e58a3b8b3b ("perf jit: Add support for using TSC as a timestamp")And would appreciate your Acked-by.
Sure, already did in http://marc.info/?l=linux-kernel&m=145949505329251
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf jit: Add support for using TSC as a timestamp
In reply to He Kuangperf jit: Add support for using TSC as a timestamp
Commit-ID: 2a28e23049af99e1c810111ef5e56455cafeda45 Gitweb: http://git.kernel.org/tip/2a28e23049af99e1c810111ef5e56455cafeda45 Author: Adrian Hunter <[email protected]> AuthorDate: Tue, 8 Mar 2016 10:38:50 +0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 1 Apr 2016 18:42:55 -0300
perf jit: Add support for using TSC as a timestamp
Intel PT uses TSC as a timestamp, so add support for using TSC instead of the monotonic clock. Use of TSC is selected by an environment variable "JITDUMP_USE_ARCH_TIMESTAMP" and flagged in the jitdump file with flag JITDUMP_FLAGS_ARCH_TIMESTAMP.
--- tools/perf/arch/x86/util/tsc.c | 1 - tools/perf/arch/x86/util/tsc.h | 17 ----------------- tools/perf/jvmti/jvmti_agent.c | 43 ++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/Build | 3 +-- tools/perf/util/jitdump.c | 37 +++++++++++++++++++++++++++++++----- tools/perf/util/jitdump.h | 3 +++ tools/perf/util/tsc.h | 11 ++++++++++- 7 files changed, 87 insertions(+), 28 deletions(-)
tools/perf/arch/x86/util/tsc.c +0 -1
@@ -7,7 +7,6 @@#include <linux/types.h> #include "../../util/debug.h" #include "../../util/tsc.h" -#include "tsc.h" int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc,struct perf_tsc_conversion *tc)
tools/perf/arch/x86/util/tsc.h deleted +0 -17
@@ -1,17 +0,0 @@ -#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ -#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ - -#include <linux/types.h> - -struct perf_tsc_conversion { -u16 time_shift; -u32 time_mult; -u64 time_zero; -}; - -struct perf_event_mmap_page ; - -int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, -struct perf_tsc_conversion *tc); - -#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
tools/perf/jvmti/jvmti_agent.c +41 -2
76 lines not on this page · raw message
tools/perf/util/Build +1 -2
@@ -69,8 +69,7 @@ libperf-y += stat-shadow.o libperf-y += record.o libperf-y += srcline.o libperf-y += data.o -libperf-$(CONFIG_X86) += tsc.o -libperf-$(CONFIG_AUXTRACE) += tsc.o +libperf-y += tsc.o libperf-y += cloexec.o libperf-y += thread-stack.o libperf-$(CONFIG_AUXTRACE) += auxtrace.o
tools/perf/util/jitdump.c +32 -5
@@ -17,6 +17,7 @@#include "strlist.h" #include <elf.h> +#include "tsc.h" #include "session.h" #include "jit.h" #include "jitdump.h"
@@ -33,6 +34,7 @@ struct jit_buf_desc {size_t bufsize;FILE *in;bool needs_bswap;/* handles cross-endianess */ +bool use_arch_timestamp;void *debug_data;size_t nr_debug_entries;uint32_t code_load_count;
@@ -158,13 +160,16 @@ jit_open(struct jit_buf_desc *jd, const char *name) header.flags =bswap_64 (header.flags); } + jd->use_arch_timestamp = header.flags &JITDUMP_FLAGS_ARCH_TIMESTAMP ; +if (verbose >2 ) -pr_debug ("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n" , +pr_debug ("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n" , header.version, header.total_size, (unsigned long long )header.timestamp, header.pid, - header.elf_mach); + header.elf_mach, + jd->use_arch_timestamp);if (header.flags &JITDUMP_FLAGS_RESERVED ) { pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
@@ -172,10 +177,15 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } +if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) { +pr_err ("jitdump file uses arch timestamps but there is no timestamp conversion\n" ); + goto error; + } +/* * validate event is using the correct clockid */ -if (jit_validate_events (jd->session)) { +if (!jd->use_arch_timestamp &&jit_validate_events (jd->session)) {pr_err ("error, jitted code must be sampled with perf record -k 1\n" ); goto error; }
@@ -329,6 +339,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)return 0 ; } +static uint64_t convert_timestamp (struct jit_buf_desc *jd,uint64_t timestamp) +{ +struct perf_tsc_conversion tc; + +if (!jd->use_arch_timestamp) +return timestamp; + + tc.time_shift = jd->session->time_conv.time_shift; + tc.time_mult = jd->session->time_conv.time_mult; + tc.time_zero = jd->session->time_conv.time_zero; + +if (!tc.time_mult) +return 0 ; + +return tsc_to_perf_time (timestamp, &tc); +} +static int jit_repipe_code_load (struct jit_buf_desc *jd,union jr_entry *jr) {struct perf_sample sample;
@@ -410,7 +437,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) id->tid = tid; }if (jd->sample_type &PERF_SAMPLE_TIME ) - id->time = jr->load.p.timestamp; + id->time =convert_timestamp (jd, jr->load.p.timestamp);/* * create pseudo sample to induce dso hit increment
@@ -499,7 +526,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) id->tid = tid; }if (jd->sample_type &PERF_SAMPLE_TIME ) - id->time = jr->load.p.timestamp; + id->time =convert_timestamp (jd, jr->load.p.timestamp);/* * create pseudo sample to induce dso hit increment
tools/perf/util/jitdump.h +3 -0
@@ -23,9 +23,12 @@#define JITHEADER_VERSION 1enum jitdump_flags_bits { +JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT ,JITDUMP_FLAGS_MAX_BIT , }; +#define JITDUMP_FLAGS_ARCH_TIMESTAMP (1ULL << JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT) +#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \ (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0)
tools/perf/util/tsc.h +10 -1
@@ -4,7 +4,16 @@#include <linux/types.h> #include "event.h" -#include "../arch/x86/util/tsc.h" + +struct perf_tsc_conversion { +u16 time_shift; +u32 time_mult; +u64 time_zero; +}; +struct perf_event_mmap_page ; + +int perf_read_tsc_conversion (const struct perf_event_mmap_page *pc, +struct perf_tsc_conversion *tc);u64 perf_time_to_tsc (u64 ns,struct perf_tsc_conversion *tc);u64 tsc_to_perf_time (u64 cyc,struct perf_tsc_conversion *tc);