diff options
Diffstat (limited to 'tools/perf/arch/x86')
-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__ */ | ||