
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29312>
181 lines
5.4 KiB
C
181 lines
5.4 KiB
C
/*
|
|
* Copyright 2024 Intel Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "perf/xe/intel_perf.h"
|
|
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "perf/intel_perf.h"
|
|
#include "intel_perf_common.h"
|
|
#include "intel/common/i915/intel_gem.h"
|
|
|
|
#include "drm-uapi/xe_drm.h"
|
|
|
|
#define FIELD_PREP_ULL(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask))
|
|
|
|
uint64_t xe_perf_get_oa_format(struct intel_perf_config *perf)
|
|
{
|
|
uint64_t fmt = FIELD_PREP_ULL(DRM_XE_OA_FORMAT_MASK_FMT_TYPE, DRM_XE_OA_FMT_TYPE_OAG);
|
|
|
|
/* same as I915_OA_FORMAT_A24u40_A14u32_B8_C8 and
|
|
* I915_OA_FORMAT_A32u40_A4u32_B8_C8 returned for gfx 125+ and gfx 120
|
|
* respectively.
|
|
*/
|
|
fmt |= FIELD_PREP_ULL(DRM_XE_OA_FORMAT_MASK_COUNTER_SEL, 5);
|
|
fmt |= FIELD_PREP_ULL(DRM_XE_OA_FORMAT_MASK_COUNTER_SIZE, 0);
|
|
fmt |= FIELD_PREP_ULL(DRM_XE_OA_FORMAT_MASK_BC_REPORT, 0);
|
|
|
|
return fmt;
|
|
}
|
|
|
|
bool
|
|
xe_oa_metrics_available(struct intel_perf_config *perf, int fd, bool use_register_snapshots)
|
|
{
|
|
bool perf_oa_available = false;
|
|
struct stat sb;
|
|
|
|
/* The existence of this file implies that this Xe KMD version supports
|
|
* perf interface.
|
|
*/
|
|
if (stat("/proc/sys/dev/xe/perf_stream_paranoid", &sb) == 0) {
|
|
uint64_t paranoid = 1;
|
|
|
|
/* Now we need to check if application has privileges to access perf
|
|
* interface.
|
|
*
|
|
* TODO: this approach does not takes into account applications running
|
|
* with CAP_PERFMON privileges.
|
|
*/
|
|
read_file_uint64("/proc/sys/dev/xe/perf_stream_paranoid", ¶noid);
|
|
if (paranoid == 0 || geteuid() == 0)
|
|
perf_oa_available = true;
|
|
}
|
|
|
|
if (!perf_oa_available)
|
|
return perf_oa_available;
|
|
|
|
perf->features_supported |= INTEL_PERF_FEATURE_HOLD_PREEMPTION;
|
|
|
|
return perf_oa_available;
|
|
}
|
|
|
|
uint64_t
|
|
xe_add_config(struct intel_perf_config *perf, int fd,
|
|
const struct intel_perf_registers *config,
|
|
const char *guid)
|
|
{
|
|
struct drm_xe_oa_config xe_config = {};
|
|
struct drm_xe_perf_param perf_param = {
|
|
.perf_type = DRM_XE_PERF_TYPE_OA,
|
|
.perf_op = DRM_XE_PERF_OP_ADD_CONFIG,
|
|
.param = (uintptr_t)&xe_config,
|
|
};
|
|
uint32_t *regs;
|
|
int ret;
|
|
|
|
memcpy(xe_config.uuid, guid, sizeof(xe_config.uuid));
|
|
|
|
xe_config.n_regs = config->n_mux_regs + config->n_b_counter_regs + config->n_flex_regs;
|
|
assert(xe_config.n_regs > 0);
|
|
|
|
regs = malloc(sizeof(uint64_t) * xe_config.n_regs);
|
|
xe_config.regs_ptr = (uintptr_t)regs;
|
|
|
|
memcpy(regs, config->mux_regs, config->n_mux_regs * sizeof(uint64_t));
|
|
regs += 2 * config->n_mux_regs;
|
|
memcpy(regs, config->b_counter_regs, config->n_b_counter_regs * sizeof(uint64_t));
|
|
regs += 2 * config->n_b_counter_regs;
|
|
memcpy(regs, config->flex_regs, config->n_flex_regs * sizeof(uint64_t));
|
|
|
|
ret = intel_ioctl(fd, DRM_IOCTL_XE_PERF, &perf_param);
|
|
free(regs);
|
|
return ret > 0 ? ret : 0;
|
|
}
|
|
|
|
void
|
|
xe_remove_config(struct intel_perf_config *perf, int fd, uint64_t config_id)
|
|
{
|
|
struct drm_xe_perf_param perf_param = {
|
|
.perf_type = DRM_XE_PERF_TYPE_OA,
|
|
.perf_op = DRM_XE_PERF_OP_REMOVE_CONFIG,
|
|
.param = (uintptr_t)&config_id,
|
|
};
|
|
|
|
intel_ioctl(fd, DRM_IOCTL_XE_PERF, &perf_param);
|
|
}
|
|
|
|
static void
|
|
perf_prop_set(struct drm_xe_ext_set_property *props, uint32_t *index,
|
|
enum drm_xe_oa_property_id prop_id, uint64_t value)
|
|
{
|
|
if (*index > 0)
|
|
props[*index - 1].base.next_extension = (uintptr_t)&props[*index];
|
|
|
|
props[*index].base.name = DRM_XE_OA_EXTENSION_SET_PROPERTY;
|
|
props[*index].property = prop_id;
|
|
props[*index].value = value;
|
|
*index = *index + 1;
|
|
}
|
|
|
|
int
|
|
xe_perf_stream_open(struct intel_perf_config *perf_config, int drm_fd,
|
|
uint32_t exec_id, uint64_t metrics_set_id,
|
|
uint64_t report_format, uint64_t period_exponent,
|
|
bool hold_preemption, bool enable)
|
|
{
|
|
struct drm_xe_ext_set_property props[DRM_XE_OA_PROPERTY_NO_PREEMPT + 1] = {};
|
|
struct drm_xe_perf_param perf_param = {
|
|
.perf_type = DRM_XE_PERF_TYPE_OA,
|
|
.perf_op = DRM_XE_PERF_OP_STREAM_OPEN,
|
|
.param = (uintptr_t)&props,
|
|
};
|
|
uint32_t i = 0;
|
|
int fd, flags;
|
|
|
|
if (exec_id)
|
|
perf_prop_set(props, &i, DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID, exec_id);
|
|
perf_prop_set(props, &i, DRM_XE_OA_PROPERTY_OA_DISABLED, !enable);
|
|
perf_prop_set(props, &i, DRM_XE_OA_PROPERTY_SAMPLE_OA, true);
|
|
perf_prop_set(props, &i, DRM_XE_OA_PROPERTY_OA_METRIC_SET, metrics_set_id);
|
|
perf_prop_set(props, &i, DRM_XE_OA_PROPERTY_OA_FORMAT, report_format);
|
|
perf_prop_set(props, &i, DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT, period_exponent);
|
|
if (hold_preemption)
|
|
perf_prop_set(props, &i, DRM_XE_OA_PROPERTY_NO_PREEMPT, hold_preemption);
|
|
|
|
fd = intel_ioctl(drm_fd, DRM_IOCTL_XE_PERF, &perf_param);
|
|
if (fd < 0)
|
|
return fd;
|
|
|
|
flags = fcntl(fd, F_GETFL, 0);
|
|
flags |= O_CLOEXEC | O_NONBLOCK;
|
|
if (fcntl(fd, F_SETFL, flags)) {
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
int
|
|
xe_perf_stream_set_state(int perf_stream_fd, bool enable)
|
|
{
|
|
unsigned long uapi = enable ? DRM_XE_PERF_IOCTL_ENABLE : DRM_XE_PERF_IOCTL_DISABLE;
|
|
|
|
return intel_ioctl(perf_stream_fd, uapi, 0);
|
|
}
|
|
|
|
int
|
|
xe_perf_stream_set_metrics_id(int perf_stream_fd, uint64_t metrics_set_id)
|
|
{
|
|
struct drm_xe_ext_set_property prop = {};
|
|
uint32_t index = 0;
|
|
|
|
perf_prop_set(&prop, &index, DRM_XE_OA_PROPERTY_OA_METRIC_SET,
|
|
metrics_set_id);
|
|
return intel_ioctl(perf_stream_fd, DRM_XE_PERF_IOCTL_CONFIG,
|
|
(void *)(uintptr_t)&prop);
|
|
}
|