/* * Copyright © 2021 Collabora, Ltd. * Author: Antonio Caggiano * * SPDX-License-Identifier: MIT */ #include "intel_pps_perf.h" #include #include #include #include #include "drm-uapi/i915_drm.h" #include #include namespace pps { IntelPerf::IntelPerf(const int drm_fd) : drm_fd {drm_fd} , ralloc_ctx {ralloc_context(nullptr)} , ralloc_cfg {ralloc_context(nullptr)} , cfg {intel_perf_new(ralloc_cfg)} { assert(drm_fd >= 0 && "DRM fd is not valid"); if (!intel_get_device_info_from_fd(drm_fd, &devinfo)) { PPS_LOG_FATAL("Failed to get devinfo"); } intel_perf_init_metrics(cfg, &devinfo, drm_fd, false, // no pipeline statistics false // no register snapshots ); } IntelPerf::~IntelPerf() { close(); if (ralloc_ctx) { ralloc_free(ralloc_ctx); } if (ralloc_cfg) { ralloc_free(ralloc_cfg); } } std::vector IntelPerf::get_queries() const { assert(cfg && "Intel perf config should be valid"); assert(cfg->n_queries && "Intel perf queries not initialized"); std::vector queries = {}; for (int i = 0; i < cfg->n_queries; ++i) { struct intel_perf_query_info *query = &cfg->queries[i]; // Skip invalid queries if (query && query->symbol_name) { queries.push_back(query); } } return queries; } // The period_exponent gives a sampling period as follows: // sample_period = timestamp_period * 2^(period_exponent + 1) // where timestamp_period is 80ns for Haswell+ static uint32_t get_oa_exponent(const intel_device_info *devinfo, const uint64_t sampling_period_ns) { return static_cast(log2(sampling_period_ns * devinfo->timestamp_frequency / 1000000000ull)) - 1; } bool IntelPerf::open(const uint64_t sampling_period_ns, struct intel_perf_query_info *query) { assert(!ctx && "Perf context should not be initialized at this point"); ctx = intel_perf_new_context(ralloc_ctx); intel_perf_init_context(ctx, cfg, nullptr, nullptr, nullptr, &devinfo, 0, drm_fd); auto oa_exponent = get_oa_exponent(&devinfo, sampling_period_ns); return intel_perf_open(ctx, query->oa_metrics_set_id, query->oa_format, oa_exponent, drm_fd, INTEL_PERF_INVALID_CTX_ID, true /* enable stream immediately */); } void IntelPerf::close() { if (ctx) { intel_perf_close(ctx, nullptr); ctx = nullptr; } } bool IntelPerf::oa_stream_ready() const { assert(ctx && "Perf context was not open"); return intel_perf_oa_stream_ready(ctx); } ssize_t IntelPerf::read_oa_stream(void *buf, size_t bytes) const { assert(ctx && "Perf context was not open"); return intel_perf_read_oa_stream(ctx, buf, bytes); } } // namespace pps