From 03fca3af51703bd77ed14c88c3d5733840a69f3f Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Mon, 14 Sep 2020 19:53:06 +0800 Subject: perf tsc: Move out common functions from x86 Functions perf_read_tsc_conversion() and perf_event__synth_time_conv() should work as common functions rather than x86 specific, so move these two functions out from arch/x86 folder and place them into util/tsc.c. Since the function perf_event__synth_time_conv() will be linked in util/tsc.c, remove its weak version. Committer testing: Before/after: # perf test tsc 70: Convert perf time to TSC : Ok # # perf test -v tsc 70: Convert perf time to TSC : --- start --- test child forked, pid 8520 mmap size 528384B 1st event perf time 592110439891 tsc 2317172044331 rdtsc time 592110441915 tsc 2317172052010 2nd event perf time 592110442336 tsc 2317172053605 test child finished with 0 ---- end ---- Convert perf time to TSC: Ok # Signed-off-by: Leo Yan Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Gustavo A. R. Silva Cc: Ian Rogers Cc: Jiri Olsa Cc: John Garry Cc: Kemeng Shi Cc: linux-arm-kernel@lists.infradead.org Cc: Mark Rutland Cc: Mathieu Poirier Cc: Namhyung Kim Cc: Nick Gasson Cc: Peter Zijlstra Cc: Remi Bernon Cc: Stephane Eranian Cc: Steve Maclean Cc: Will Deacon Cc: Zou Wei Link: http://lore.kernel.org/lkml/20200914115311.2201-2-leo.yan@linaro.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/synthetic-events.c | 8 ----- tools/perf/util/tsc.c | 71 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 8 deletions(-) (limited to 'tools/perf/util') diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 89b390623b63..3ca5d9399680 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -2006,14 +2006,6 @@ int perf_event__synthesize_stat_events(struct perf_stat_config *config, struct p return 0; } -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; -} - extern const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE]; int perf_event__synthesize_features(struct perf_tool *tool, struct perf_session *session, diff --git a/tools/perf/util/tsc.c b/tools/perf/util/tsc.c index bfa782421cbd..9e3f04ddddf8 100644 --- a/tools/perf/util/tsc.c +++ b/tools/perf/util/tsc.c @@ -1,7 +1,16 @@ // SPDX-License-Identifier: GPL-2.0 +#include + #include +#include +#include #include +#include + +#include "event.h" +#include "synthetic-events.h" +#include "debug.h" #include "tsc.h" u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc) @@ -25,6 +34,68 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc) ((rem * tc->time_mult) >> tc->time_shift); } +int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, + struct perf_tsc_conversion *tc) +{ + bool cap_user_time_zero; + u32 seq; + int i = 0; + + while (1) { + seq = pc->lock; + rmb(); + tc->time_mult = pc->time_mult; + tc->time_shift = pc->time_shift; + tc->time_zero = pc->time_zero; + cap_user_time_zero = pc->cap_user_time_zero; + rmb(); + if (pc->lock == seq && !(seq & 1)) + break; + if (++i > 10000) { + pr_debug("failed to get perf_event_mmap_page lock\n"); + return -EINVAL; + } + } + + if (!cap_user_time_zero) + return -EOPNOTSUPP; + + return 0; +} + +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 perf_record_time_conv), + }, + }, + }; + struct perf_tsc_conversion tc; + int err; + + if (!pc) + return 0; + 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); +} + u64 __weak rdtsc(void) { return 0; -- cgit v1.2.3-59-g8ed1b