Path: blob/21.2-virgl/src/intel/ds/intel_pps_perf.cc
4547 views
/*1* Copyright © 2021 Collabora, Ltd.2* Author: Antonio Caggiano <[email protected]>3*4* SPDX-License-Identifier: MIT5*/67#include "intel_pps_perf.h"89#include <i915_drm.h>10#include <math.h>11#include <sys/ioctl.h>12#include <util/ralloc.h>13#include <utility>1415#include <pps/pps.h>16#include <pps/pps_device.h>1718namespace pps19{20int perf_ioctl(int fd, unsigned long request, void *arg)21{22int ret;2324do {25ret = ioctl(fd, request, arg);26} while (ret == -1 && (errno == EINTR || errno == EAGAIN));2728return ret;29}3031IntelPerf::IntelPerf(const int drm_fd)32: drm_fd {drm_fd}33, ralloc_ctx {ralloc_context(nullptr)}34, ralloc_cfg {ralloc_context(nullptr)}35, cfg {intel_perf_new(ralloc_cfg)}36{37assert(drm_fd >= 0 && "DRM fd is not valid");3839if (!intel_get_device_info_from_fd(drm_fd, &devinfo)) {40PPS_LOG_FATAL("Failed to get devinfo");41}4243intel_perf_init_metrics(cfg,44&devinfo,45drm_fd,46false, // no pipeline statistics47false // no register snapshots48);4950// Enable RenderBasic counters51auto query_name = "RenderBasic";52query = find_query_by_name(query_name);53if (!query) {54PPS_LOG_FATAL("Failed to find %s query", query_name);55}56}5758IntelPerf::IntelPerf(IntelPerf &&o)59: drm_fd {o.drm_fd}60, ralloc_ctx {o.ralloc_ctx}61, ralloc_cfg {o.ralloc_cfg}62, ctx {o.ctx}63, cfg {o.cfg}64, devinfo {std::move(o.devinfo)}65, query {std::move(o.query)}66{67o.drm_fd = -1;68o.ralloc_ctx = nullptr;69o.ralloc_cfg = nullptr;70o.ctx = nullptr;71o.cfg = nullptr;72}7374IntelPerf &IntelPerf::operator=(IntelPerf &&o) noexcept75{76std::swap(drm_fd, o.drm_fd);77std::swap(ralloc_ctx, o.ralloc_ctx);78std::swap(ralloc_cfg, o.ralloc_cfg);79std::swap(ctx, o.ctx);80std::swap(cfg, o.cfg);81std::swap(devinfo, o.devinfo);82std::swap(query, o.query);83return *this;84}8586IntelPerf::~IntelPerf()87{88close();8990if (ralloc_ctx) {91ralloc_free(ralloc_ctx);92}9394if (ralloc_cfg) {95ralloc_free(ralloc_cfg);96}97}9899/// @return A query info, which is something like a group of counters100std::optional<struct intel_perf_query_info> IntelPerf::find_query_by_name(101const std::string &name) const102{103for (int i = 0; i < cfg->n_queries; ++i) {104struct intel_perf_query_info query = cfg->queries[i];105if (name == query.symbol_name) {106return query;107}108}109110return std::nullopt;111}112113std::vector<struct intel_perf_query_info *> IntelPerf::get_queries() const114{115assert(cfg && "Intel perf config should be valid");116assert(cfg->n_queries && "Intel perf queries not initialized");117118std::vector<struct intel_perf_query_info *> queries = {};119120for (int i = 0; i < cfg->n_queries; ++i) {121struct intel_perf_query_info *query = &cfg->queries[i];122// Skip invalid queries123if (query && query->symbol_name) {124queries.push_back(query);125}126}127128return queries;129}130131static uint64_t query_timestamp_frequency(const int drm_fd)132{133int timestamp_frequency;134135drm_i915_getparam_t gp = {};136gp.param = I915_PARAM_CS_TIMESTAMP_FREQUENCY;137gp.value = ×tamp_frequency;138if (perf_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp) == 0) {139return timestamp_frequency;140}141142PPS_LOG_ERROR("Unable to query timestamp frequency from i915, guessing values...");143return 12000000;144}145146// The period_exponent gives a sampling period as follows:147// sample_period = timestamp_period * 2^(period_exponent + 1)148// where timestamp_period is 80ns for Haswell+149static uint32_t get_oa_exponent(const int drm_fd, const uint64_t sampling_period_ns)150{151uint64_t timestamp_frequency = query_timestamp_frequency(drm_fd);152return static_cast<uint32_t>(log2(sampling_period_ns * timestamp_frequency / 1000000000ull)) - 1;153}154155bool IntelPerf::open(const uint64_t sampling_period_ns)156{157assert(!ctx && "Perf context should not be initialized at this point");158159ctx = intel_perf_new_context(ralloc_ctx);160intel_perf_init_context(ctx, cfg, nullptr, nullptr, nullptr, &devinfo, 0, drm_fd);161162auto oa_exponent = get_oa_exponent(drm_fd, sampling_period_ns);163164return intel_perf_open(ctx,165query->oa_metrics_set_id,166query->oa_format,167oa_exponent,168drm_fd,169INTEL_PERF_INVALID_CTX_ID,170true /* enable stream immediately */);171}172173void IntelPerf::close()174{175if (ctx) {176intel_perf_close(ctx, nullptr);177ctx = nullptr;178}179}180181bool IntelPerf::oa_stream_ready() const182{183assert(ctx && "Perf context was not open");184return intel_perf_oa_stream_ready(ctx);185}186187ssize_t IntelPerf::read_oa_stream(void *buf, size_t bytes) const188{189assert(ctx && "Perf context was not open");190return intel_perf_read_oa_stream(ctx, buf, bytes);191}192193} // namespace pps194195196