1 // SPDX-License-Identifier: GPL-2.0
5 #include <linux/perf_event.h>
7 #include "../../perf.h"
8 #include <linux/types.h>
9 #include "../../util/debug.h"
10 #include "../../util/tsc.h"
12 int perf_read_tsc_conversion(const struct perf_event_mmap_page
*pc
,
13 struct perf_tsc_conversion
*tc
)
15 bool cap_user_time_zero
;
22 tc
->time_mult
= pc
->time_mult
;
23 tc
->time_shift
= pc
->time_shift
;
24 tc
->time_zero
= pc
->time_zero
;
25 cap_user_time_zero
= pc
->cap_user_time_zero
;
27 if (pc
->lock
== seq
&& !(seq
& 1))
30 pr_debug("failed to get perf_event_mmap_page lock\n");
35 if (!cap_user_time_zero
)
43 unsigned int low
, high
;
45 asm volatile("rdtsc" : "=a" (low
), "=d" (high
));
47 return low
| ((u64
)high
) << 32;
50 int perf_event__synth_time_conv(const struct perf_event_mmap_page
*pc
,
51 struct perf_tool
*tool
,
52 perf_event__handler_t process
,
53 struct machine
*machine
)
55 union perf_event event
= {
58 .type
= PERF_RECORD_TIME_CONV
,
59 .size
= sizeof(struct time_conv_event
),
63 struct perf_tsc_conversion tc
;
68 err
= perf_read_tsc_conversion(pc
, &tc
);
69 if (err
== -EOPNOTSUPP
)
74 pr_debug2("Synthesizing TSC conversion information\n");
76 event
.time_conv
.time_mult
= tc
.time_mult
;
77 event
.time_conv
.time_shift
= tc
.time_shift
;
78 event
.time_conv
.time_zero
= tc
.time_zero
;
80 return process(tool
, &event
, NULL
, machine
);