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__ */ | ||
