]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/perf/arch/x86/util/tsc.c
rt2x00: rt2800pci: use module_pci_driver macro
[karo-tx-linux.git] / tools / perf / arch / x86 / util / tsc.c
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 t, quot, rem;
14
15         t = ns - tc->time_zero;
16         quot = t / tc->time_mult;
17         rem  = t % 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 }