Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <leo.yan@linaro.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Gustavo A. R. Silva <gustavoars@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: John Garry <john.garry@huawei.com>
Cc: Kemeng Shi <shikemeng@huawei.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nick Gasson <nick.gasson@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Remi Bernon <rbernon@codeweavers.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Steve Maclean <steve.maclean@microsoft.com>
Cc: Will Deacon <will@kernel.org>
Cc: Zou Wei <zou_wei@huawei.com>
Link: http://lore.kernel.org/lkml/20200914115311.2201-2-leo.yan@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Leo Yan and committed by
Arnaldo Carvalho de Melo
03fca3af 7cd5738d

+72 -80
+1 -72
tools/perf/arch/x86/util/tsc.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <stdbool.h> 3 - #include <errno.h> 4 - 5 - #include <linux/stddef.h> 6 - #include <linux/perf_event.h> 7 - 8 2 #include <linux/types.h> 9 - #include <asm/barrier.h> 10 - #include "../../../util/debug.h" 11 - #include "../../../util/event.h" 12 - #include "../../../util/synthetic-events.h" 3 + 13 4 #include "../../../util/tsc.h" 14 - 15 - int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 16 - struct perf_tsc_conversion *tc) 17 - { 18 - bool cap_user_time_zero; 19 - u32 seq; 20 - int i = 0; 21 - 22 - while (1) { 23 - seq = pc->lock; 24 - rmb(); 25 - tc->time_mult = pc->time_mult; 26 - tc->time_shift = pc->time_shift; 27 - tc->time_zero = pc->time_zero; 28 - cap_user_time_zero = pc->cap_user_time_zero; 29 - rmb(); 30 - if (pc->lock == seq && !(seq & 1)) 31 - break; 32 - if (++i > 10000) { 33 - pr_debug("failed to get perf_event_mmap_page lock\n"); 34 - return -EINVAL; 35 - } 36 - } 37 - 38 - if (!cap_user_time_zero) 39 - return -EOPNOTSUPP; 40 - 41 - return 0; 42 - } 43 5 44 6 u64 rdtsc(void) 45 7 { ··· 10 48 asm volatile("rdtsc" : "=a" (low), "=d" (high)); 11 49 12 50 return low | ((u64)high) << 32; 13 - } 14 - 15 - int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc, 16 - struct perf_tool *tool, 17 - perf_event__handler_t process, 18 - struct machine *machine) 19 - { 20 - union perf_event event = { 21 - .time_conv = { 22 - .header = { 23 - .type = PERF_RECORD_TIME_CONV, 24 - .size = sizeof(struct perf_record_time_conv), 25 - }, 26 - }, 27 - }; 28 - struct perf_tsc_conversion tc; 29 - int err; 30 - 31 - if (!pc) 32 - return 0; 33 - err = perf_read_tsc_conversion(pc, &tc); 34 - if (err == -EOPNOTSUPP) 35 - return 0; 36 - if (err) 37 - return err; 38 - 39 - pr_debug2("Synthesizing TSC conversion information\n"); 40 - 41 - event.time_conv.time_mult = tc.time_mult; 42 - event.time_conv.time_shift = tc.time_shift; 43 - event.time_conv.time_zero = tc.time_zero; 44 - 45 - return process(tool, &event, NULL, machine); 46 51 }
-8
tools/perf/util/synthetic-events.c
··· 2006 2006 return 0; 2007 2007 } 2008 2008 2009 - int __weak perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 2010 - struct perf_tool *tool __maybe_unused, 2011 - perf_event__handler_t process __maybe_unused, 2012 - struct machine *machine __maybe_unused) 2013 - { 2014 - return 0; 2015 - } 2016 - 2017 2009 extern const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE]; 2018 2010 2019 2011 int perf_event__synthesize_features(struct perf_tool *tool, struct perf_session *session,
+71
tools/perf/util/tsc.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 + #include <errno.h> 3 + 2 4 #include <linux/compiler.h> 5 + #include <linux/perf_event.h> 6 + #include <linux/stddef.h> 3 7 #include <linux/types.h> 4 8 9 + #include <asm/barrier.h> 10 + 11 + #include "event.h" 12 + #include "synthetic-events.h" 13 + #include "debug.h" 5 14 #include "tsc.h" 6 15 7 16 u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc) ··· 32 23 rem = cyc & (((u64)1 << tc->time_shift) - 1); 33 24 return tc->time_zero + quot * tc->time_mult + 34 25 ((rem * tc->time_mult) >> tc->time_shift); 26 + } 27 + 28 + int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 29 + struct perf_tsc_conversion *tc) 30 + { 31 + bool cap_user_time_zero; 32 + u32 seq; 33 + int i = 0; 34 + 35 + while (1) { 36 + seq = pc->lock; 37 + rmb(); 38 + tc->time_mult = pc->time_mult; 39 + tc->time_shift = pc->time_shift; 40 + tc->time_zero = pc->time_zero; 41 + cap_user_time_zero = pc->cap_user_time_zero; 42 + rmb(); 43 + if (pc->lock == seq && !(seq & 1)) 44 + break; 45 + if (++i > 10000) { 46 + pr_debug("failed to get perf_event_mmap_page lock\n"); 47 + return -EINVAL; 48 + } 49 + } 50 + 51 + if (!cap_user_time_zero) 52 + return -EOPNOTSUPP; 53 + 54 + return 0; 55 + } 56 + 57 + int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc, 58 + struct perf_tool *tool, 59 + perf_event__handler_t process, 60 + struct machine *machine) 61 + { 62 + union perf_event event = { 63 + .time_conv = { 64 + .header = { 65 + .type = PERF_RECORD_TIME_CONV, 66 + .size = sizeof(struct perf_record_time_conv), 67 + }, 68 + }, 69 + }; 70 + struct perf_tsc_conversion tc; 71 + int err; 72 + 73 + if (!pc) 74 + return 0; 75 + err = perf_read_tsc_conversion(pc, &tc); 76 + if (err == -EOPNOTSUPP) 77 + return 0; 78 + if (err) 79 + return err; 80 + 81 + pr_debug2("Synthesizing TSC conversion information\n"); 82 + 83 + event.time_conv.time_mult = tc.time_mult; 84 + event.time_conv.time_shift = tc.time_shift; 85 + event.time_conv.time_zero = tc.time_zero; 86 + 87 + return process(tool, &event, NULL, machine); 35 88 } 36 89 37 90 u64 __weak rdtsc(void)