• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2021 Collabora, Ltd.
3  * Author: Antonio Caggiano <antonio.caggiano@collabora.com>
4  *
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "intel_pps_perf.h"
9 
10 #include <math.h>
11 #include <sys/ioctl.h>
12 #include <util/ralloc.h>
13 #include <utility>
14 
15 #include <pps/pps.h>
16 #include <pps/pps_device.h>
17 
18 namespace pps
19 {
IntelPerf(const int drm_fd)20 IntelPerf::IntelPerf(const int drm_fd)
21    : drm_fd {drm_fd}
22    , ralloc_ctx {ralloc_context(nullptr)}
23    , ralloc_cfg {ralloc_context(nullptr)}
24    , cfg {intel_perf_new(ralloc_cfg)}
25 {
26    assert(drm_fd >= 0 && "DRM fd is not valid");
27 
28    if (!intel_get_device_info_from_fd(drm_fd, &devinfo, -1, -1)) {
29       PPS_LOG_FATAL("Failed to get devinfo");
30    }
31 
32    intel_perf_init_metrics(cfg,
33       &devinfo,
34       drm_fd,
35       false, // no pipeline statistics
36       false  // no register snapshots
37    );
38 }
39 
~IntelPerf()40 IntelPerf::~IntelPerf()
41 {
42    close();
43 
44    if (ralloc_ctx) {
45       ralloc_free(ralloc_ctx);
46    }
47 
48    if (ralloc_cfg) {
49       ralloc_free(ralloc_cfg);
50    }
51 }
52 
get_queries() const53 std::vector<struct intel_perf_query_info *> IntelPerf::get_queries() const
54 {
55    assert(cfg && "Intel perf config should be valid");
56    assert(cfg->n_queries && "Intel perf queries not initialized");
57 
58    std::vector<struct intel_perf_query_info *> queries = {};
59 
60    for (int i = 0; i < cfg->n_queries; ++i) {
61       struct intel_perf_query_info *query = &cfg->queries[i];
62       // Skip invalid queries
63       if (query && query->symbol_name) {
64          queries.push_back(query);
65       }
66    }
67 
68    return queries;
69 }
70 
71 // The period_exponent gives a sampling period as follows:
72 // sample_period = timestamp_period * 2^(period_exponent + 1)
73 // where timestamp_period is 80ns for Haswell+
get_oa_exponent(const intel_device_info * devinfo,const uint64_t sampling_period_ns)74 static uint32_t get_oa_exponent(const intel_device_info *devinfo, const uint64_t sampling_period_ns)
75 {
76    return static_cast<uint32_t>(log2(sampling_period_ns * devinfo->timestamp_frequency / 1000000000ull)) - 1;
77 }
78 
open(const uint64_t sampling_period_ns,struct intel_perf_query_info * query)79 bool IntelPerf::open(const uint64_t sampling_period_ns,
80                      struct intel_perf_query_info *query)
81 {
82    assert(!ctx && "Perf context should not be initialized at this point");
83 
84    ctx = intel_perf_new_context(ralloc_ctx);
85    intel_perf_init_context(ctx, cfg, nullptr, nullptr, nullptr, &devinfo, 0, drm_fd);
86 
87    auto oa_exponent = get_oa_exponent(&devinfo, sampling_period_ns);
88 
89    return intel_perf_open(ctx,
90       query->oa_metrics_set_id,
91       query->oa_format,
92       oa_exponent,
93       drm_fd,
94       INTEL_PERF_INVALID_CTX_ID,
95       true /* enable stream immediately */);
96 }
97 
close()98 void IntelPerf::close()
99 {
100    if (ctx) {
101       intel_perf_close(ctx, nullptr);
102       ctx = nullptr;
103    }
104 }
105 
oa_stream_ready() const106 bool IntelPerf::oa_stream_ready() const
107 {
108    assert(ctx && "Perf context was not open");
109    return intel_perf_oa_stream_ready(ctx);
110 }
111 
read_oa_stream(void * buf,size_t bytes) const112 ssize_t IntelPerf::read_oa_stream(void *buf, size_t bytes) const
113 {
114    assert(ctx && "Perf context was not open");
115    return intel_perf_read_oa_stream(ctx, buf, bytes);
116 }
117 
118 } // namespace pps
119