Commit | Line | Data |
---|---|---|
3bd5a5fc AH |
1 | #include <stdbool.h> |
2 | #include <errno.h> | |
3 | ||
4 | #include <linux/perf_event.h> | |
5 | ||
6 | #include "../../perf.h" | |
d944c4ee | 7 | #include <linux/types.h> |
3bd5a5fc | 8 | #include "../../util/debug.h" |
0b437860 | 9 | #include "../../util/tsc.h" |
3bd5a5fc AH |
10 | #include "tsc.h" |
11 | ||
3bd5a5fc AH |
12 | int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, |
13 | struct perf_tsc_conversion *tc) | |
14 | { | |
fa731587 | 15 | bool cap_user_time_zero; |
3bd5a5fc AH |
16 | u32 seq; |
17 | int i = 0; | |
18 | ||
19 | while (1) { | |
20 | seq = pc->lock; | |
21 | rmb(); | |
22 | tc->time_mult = pc->time_mult; | |
23 | tc->time_shift = pc->time_shift; | |
24 | tc->time_zero = pc->time_zero; | |
fa731587 | 25 | cap_user_time_zero = pc->cap_user_time_zero; |
3bd5a5fc AH |
26 | rmb(); |
27 | if (pc->lock == seq && !(seq & 1)) | |
28 | break; | |
29 | if (++i > 10000) { | |
30 | pr_debug("failed to get perf_event_mmap_page lock\n"); | |
31 | return -EINVAL; | |
32 | } | |
33 | } | |
34 | ||
fa731587 | 35 | if (!cap_user_time_zero) |
3bd5a5fc AH |
36 | return -EOPNOTSUPP; |
37 | ||
38 | return 0; | |
39 | } | |
a6a69db4 AH |
40 | |
41 | u64 rdtsc(void) | |
42 | { | |
43 | unsigned int low, high; | |
44 | ||
45 | asm volatile("rdtsc" : "=a" (low), "=d" (high)); | |
46 | ||
47 | return low | ((u64)high) << 32; | |
48 | } |