diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2013-06-28 09:22:19 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-07-23 06:17:59 -0400 |
commit | 3bd5a5fc8c6b9fe769777abf74b0ab5fbd7930b4 (patch) | |
tree | ac509b983fe147d6706449c3bc14031591807585 /tools/perf/arch | |
parent | c73deb6aecda2955716f31572516f09d930ef450 (diff) |
perf tools: Add test for converting perf time to/from TSC
The test uses the newly added cap_usr_time_zero and time_zero of
perf_event_mmap_page. TSC from rdtsc is compared with the time
from 2 perf events. The test passes if the calculated times are
all in the correct order.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1372425741-1676-4-git-send-email-adrian.hunter@intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/arch')
-rw-r--r-- | tools/perf/arch/x86/Makefile | 2 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/tsc.c | 59 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/tsc.h | 20 |
3 files changed, 81 insertions, 0 deletions
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 815841c04eb2..8801fe02f206 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile | |||
@@ -6,3 +6,5 @@ ifndef NO_LIBUNWIND | |||
6 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o | 6 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o |
7 | endif | 7 | endif |
8 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o | 8 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o |
9 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o | ||
10 | LIB_H += arch/$(ARCH)/util/tsc.h | ||
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c new file mode 100644 index 000000000000..f1117441cdcd --- /dev/null +++ b/tools/perf/arch/x86/util/tsc.c | |||
@@ -0,0 +1,59 @@ | |||
1 | #include <stdbool.h> | ||
2 | #include <errno.h> | ||
3 | |||
4 | #include <linux/perf_event.h> | ||
5 | |||
6 | #include "../../perf.h" | ||
7 | #include "../../util/types.h" | ||
8 | #include "../../util/debug.h" | ||
9 | #include "tsc.h" | ||
10 | |||
11 | u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc) | ||
12 | { | ||
13 | u64 time, quot, rem; | ||
14 | |||
15 | time = ns - tc->time_zero; | ||
16 | quot = time / tc->time_mult; | ||
17 | rem = time % tc->time_mult; | ||
18 | return (quot << tc->time_shift) + | ||
19 | (rem << tc->time_shift) / tc->time_mult; | ||
20 | } | ||
21 | |||
22 | u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc) | ||
23 | { | ||
24 | u64 quot, rem; | ||
25 | |||
26 | quot = cyc >> tc->time_shift; | ||
27 | rem = cyc & ((1 << tc->time_shift) - 1); | ||
28 | return tc->time_zero + quot * tc->time_mult + | ||
29 | ((rem * tc->time_mult) >> tc->time_shift); | ||
30 | } | ||
31 | |||
32 | int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, | ||
33 | struct perf_tsc_conversion *tc) | ||
34 | { | ||
35 | bool cap_usr_time_zero; | ||
36 | u32 seq; | ||
37 | int i = 0; | ||
38 | |||
39 | while (1) { | ||
40 | seq = pc->lock; | ||
41 | rmb(); | ||
42 | tc->time_mult = pc->time_mult; | ||
43 | tc->time_shift = pc->time_shift; | ||
44 | tc->time_zero = pc->time_zero; | ||
45 | cap_usr_time_zero = pc->cap_usr_time_zero; | ||
46 | rmb(); | ||
47 | if (pc->lock == seq && !(seq & 1)) | ||
48 | break; | ||
49 | if (++i > 10000) { | ||
50 | pr_debug("failed to get perf_event_mmap_page lock\n"); | ||
51 | return -EINVAL; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | if (!cap_usr_time_zero) | ||
56 | return -EOPNOTSUPP; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
diff --git a/tools/perf/arch/x86/util/tsc.h b/tools/perf/arch/x86/util/tsc.h new file mode 100644 index 000000000000..a24dec81c795 --- /dev/null +++ b/tools/perf/arch/x86/util/tsc.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ | ||
2 | #define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ | ||
3 | |||
4 | #include "../../util/types.h" | ||
5 | |||
6 | struct perf_tsc_conversion { | ||
7 | u16 time_shift; | ||
8 | u32 time_mult; | ||
9 | u64 time_zero; | ||
10 | }; | ||
11 | |||
12 | struct perf_event_mmap_page; | ||
13 | |||
14 | int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, | ||
15 | struct perf_tsc_conversion *tc); | ||
16 | |||
17 | u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); | ||
18 | u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); | ||
19 | |||
20 | #endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */ | ||