x86/debug: Drop several unnecessary CFI annotations
[cascardo/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 <linux/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_user_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_user_time_zero = pc->cap_user_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_user_time_zero)
56                 return -EOPNOTSUPP;
57
58         return 0;
59 }