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