blob: fd2868490d00ea895b380e5cd408482c2f990a35 [file] [log] [blame]
Adrian Hunter3bd5a5f2013-06-28 16:22:19 +03001#include <stdbool.h>
2#include <errno.h>
3
4#include <linux/perf_event.h>
5
6#include "../../perf.h"
Borislav Petkovd944c4e2014-04-25 21:31:02 +02007#include <linux/types.h>
Adrian Hunter3bd5a5f2013-06-28 16:22:19 +03008#include "../../util/debug.h"
Adrian Hunter0b437862014-07-14 13:03:03 +03009#include "../../util/tsc.h"
Adrian Hunter3bd5a5f2013-06-28 16:22:19 +030010#include "tsc.h"
11
Adrian Hunter3bd5a5f2013-06-28 16:22:19 +030012int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
13 struct perf_tsc_conversion *tc)
14{
Peter Zijlstrafa731582013-09-19 10:16:42 +020015 bool cap_user_time_zero;
Adrian Hunter3bd5a5f2013-06-28 16:22:19 +030016 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;
Peter Zijlstrafa731582013-09-19 10:16:42 +020025 cap_user_time_zero = pc->cap_user_time_zero;
Adrian Hunter3bd5a5f2013-06-28 16:22:19 +030026 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
Peter Zijlstrafa731582013-09-19 10:16:42 +020035 if (!cap_user_time_zero)
Adrian Hunter3bd5a5f2013-06-28 16:22:19 +030036 return -EOPNOTSUPP;
37
38 return 0;
39}
Adrian Huntera6a69db2014-07-22 16:17:32 +030040
41u64 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}