root/tools/perf/arch/x86/util/tsc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. perf_read_tsc_conversion
  2. rdtsc
  3. perf_event__synth_time_conv

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <stdbool.h>
   3 #include <errno.h>
   4 
   5 #include <linux/stddef.h>
   6 #include <linux/perf_event.h>
   7 
   8 #include <linux/types.h>
   9 #include <asm/barrier.h>
  10 #include "../../../util/debug.h"
  11 #include "../../../util/event.h"
  12 #include "../../../util/synthetic-events.h"
  13 #include "../../../util/tsc.h"
  14 
  15 int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
  16                              struct perf_tsc_conversion *tc)
  17 {
  18         bool cap_user_time_zero;
  19         u32 seq;
  20         int i = 0;
  21 
  22         while (1) {
  23                 seq = pc->lock;
  24                 rmb();
  25                 tc->time_mult = pc->time_mult;
  26                 tc->time_shift = pc->time_shift;
  27                 tc->time_zero = pc->time_zero;
  28                 cap_user_time_zero = pc->cap_user_time_zero;
  29                 rmb();
  30                 if (pc->lock == seq && !(seq & 1))
  31                         break;
  32                 if (++i > 10000) {
  33                         pr_debug("failed to get perf_event_mmap_page lock\n");
  34                         return -EINVAL;
  35                 }
  36         }
  37 
  38         if (!cap_user_time_zero)
  39                 return -EOPNOTSUPP;
  40 
  41         return 0;
  42 }
  43 
  44 u64 rdtsc(void)
  45 {
  46         unsigned int low, high;
  47 
  48         asm volatile("rdtsc" : "=a" (low), "=d" (high));
  49 
  50         return low | ((u64)high) << 32;
  51 }
  52 
  53 int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc,
  54                                 struct perf_tool *tool,
  55                                 perf_event__handler_t process,
  56                                 struct machine *machine)
  57 {
  58         union perf_event event = {
  59                 .time_conv = {
  60                         .header = {
  61                                 .type = PERF_RECORD_TIME_CONV,
  62                                 .size = sizeof(struct perf_record_time_conv),
  63                         },
  64                 },
  65         };
  66         struct perf_tsc_conversion tc;
  67         int err;
  68 
  69         if (!pc)
  70                 return 0;
  71         err = perf_read_tsc_conversion(pc, &tc);
  72         if (err == -EOPNOTSUPP)
  73                 return 0;
  74         if (err)
  75                 return err;
  76 
  77         pr_debug2("Synthesizing TSC conversion information\n");
  78 
  79         event.time_conv.time_mult  = tc.time_mult;
  80         event.time_conv.time_shift = tc.time_shift;
  81         event.time_conv.time_zero  = tc.time_zero;
  82 
  83         return process(tool, &event, NULL, machine);
  84 }

/* [<][>][^][v][top][bottom][index][help] */