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 "../../util/tsc.h" 10 #include "tsc.h" 11 12 int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 13 struct perf_tsc_conversion *tc) 14 { 15 bool cap_user_time_zero; 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; 25 cap_user_time_zero = pc->cap_user_time_zero; 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 35 if (!cap_user_time_zero) 36 return -EOPNOTSUPP; 37 38 return 0; 39 } 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 } 49