1 /*
2 * Copyright © 2021 Collabora, Ltd.
3 * Author: Antonio Caggiano <[email protected]>
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 , cfg {intel_perf_new(NULL)}
23 {
24 assert(drm_fd >= 0 && "DRM fd is not valid");
25
26 if (!intel_get_device_info_from_fd(drm_fd, &devinfo, -1, -1)) {
27 PPS_LOG_FATAL("Failed to get devinfo");
28 }
29
30 intel_perf_init_metrics(cfg,
31 &devinfo,
32 drm_fd,
33 false, // no pipeline statistics
34 false // no register snapshots
35 );
36 }
37
~IntelPerf()38 IntelPerf::~IntelPerf()
39 {
40 close();
41
42 intel_perf_free(cfg);
43 }
44
get_queries() const45 std::vector<struct intel_perf_query_info *> IntelPerf::get_queries() const
46 {
47 assert(cfg && "Intel perf config should be valid");
48 assert(cfg->n_queries && "Intel perf queries not initialized");
49
50 std::vector<struct intel_perf_query_info *> queries = {};
51
52 for (int i = 0; i < cfg->n_queries; ++i) {
53 struct intel_perf_query_info *query = &cfg->queries[i];
54 // Skip invalid queries
55 if (query && query->symbol_name) {
56 queries.push_back(query);
57 }
58 }
59
60 return queries;
61 }
62
63 // The period_exponent gives a sampling period as follows:
64 // sample_period = timestamp_period * 2^(period_exponent + 1)
65 // where timestamp_period is 80ns for Haswell+
get_oa_exponent(const intel_device_info * devinfo,const uint64_t sampling_period_ns)66 static uint32_t get_oa_exponent(const intel_device_info *devinfo, const uint64_t sampling_period_ns)
67 {
68 return static_cast<uint32_t>(log2(sampling_period_ns * devinfo->timestamp_frequency / 1000000000ull)) - 1;
69 }
70
open(const uint64_t sampling_period_ns,struct intel_perf_query_info * query)71 bool IntelPerf::open(const uint64_t sampling_period_ns,
72 struct intel_perf_query_info *query)
73 {
74 assert(!ctx && "Perf context should not be initialized at this point");
75
76 ctx = intel_perf_new_context(NULL);
77 intel_perf_init_context(ctx, cfg, nullptr, nullptr, nullptr, &devinfo, 0, drm_fd);
78
79 auto oa_exponent = get_oa_exponent(&devinfo, sampling_period_ns);
80
81 return intel_perf_open(ctx,
82 query->oa_metrics_set_id,
83 query->oa_format,
84 oa_exponent,
85 drm_fd,
86 INTEL_PERF_INVALID_CTX_ID,
87 true /* enable stream immediately */);
88 }
89
close()90 void IntelPerf::close()
91 {
92 if (ctx) {
93 intel_perf_close(ctx, nullptr);
94 intel_perf_free_context(ctx);
95 ctx = nullptr;
96 }
97 }
98
oa_stream_ready() const99 bool IntelPerf::oa_stream_ready() const
100 {
101 assert(ctx && "Perf context was not open");
102 return intel_perf_oa_stream_ready(ctx);
103 }
104
read_oa_stream(void * buf,size_t bytes) const105 ssize_t IntelPerf::read_oa_stream(void *buf, size_t bytes) const
106 {
107 assert(ctx && "Perf context was not open");
108 return intel_perf_read_oa_stream(ctx, buf, bytes);
109 }
110
111 } // namespace pps
112