Re: [PATCH i-g-t v4] tools/xe-perf-recorder: Add mmio-trigger support
"Dixit, Ashutosh" <[email protected]>
| Newsgroups | org.freedesktop.lists.igt-dev |
|---|---|
| Message-ID | <[email protected]> |
On Mon, 20 Jul 2026 20:32:35 -0700, Shekhar Chauhan wrote: > > Add mmio-trigger support to xe-perf-recorder, to justify the > whitelisting of OA MMIO Trigger Registers in XeKMD. > > Signed-off-by: Shekhar Chauhan <[email protected]> > --- > tools/xe-perf/xe_perf_recorder.c | 118 ++++++++++++++++++++++++++++++- > 1 file changed, 116 insertions(+), 2 deletions(-) > > diff --git a/tools/xe-perf/xe_perf_recorder.c b/tools/xe-perf/xe_perf_recorder.c > index 61c3f6945..c69050b43 100644 > --- a/tools/xe-perf/xe_perf_recorder.c > +++ b/tools/xe-perf/xe_perf_recorder.c > @@ -26,19 +26,28 @@ > #include <unistd.h> > > #include "igt_core.h" > +#include "intel_batchbuffer.h" > #include "intel_chipset.h" > #include "ioctl_wrappers.h" > #include "linux_scaffold.h" > +#include "xe/xe_ioctl.h" > #include "xe/xe_oa.h" > #include "xe/xe_oa_data.h" > #include "xe/xe_query.h" > > #include "xe_perf_recorder_commands.h" > > -#define ALIGN(v, a) (((v) + (a)-1) & ~((a)-1)) > -#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0])) > #define MAX(a,b) ((a) > (b) ? (a) : (b)) > #define MIN(a,b) ((a) < (b) ? (a) : (b)) > +#define OAG_MMIOTRIGGER 0xdb1c > +#define OAMERT_MMIOTRIGGER 0x1453cc > +#define OAM_MMIOTRIGGER_OFFSET 0x1d0 > +#define MEDIA_GT_GSI_OFFSET 0x380000 > +#define XE_OAM_SAG_BASE_ADJ (MEDIA_GT_GSI_OFFSET + 0x13000) > +#define XE_OAM_SCMI_0_BASE_ADJ (MEDIA_GT_GSI_OFFSET + 0x14000) > +#define XE_OAM_SCMI_1_BASE_ADJ (MEDIA_GT_GSI_OFFSET + 0x14800) > +#define OAREPORT_REASON_MASK 0x3f > +#define OAREPORT_REASON_SHIFT 19 > > struct circular_buffer { > char *data; > @@ -354,8 +363,50 @@ struct recording_context { > int oa_unit_id; > struct drm_xe_oa_unit *oa_unit; > struct drm_xe_engine_class_instance *hwe; > + > + uint32_t vm; > + uint32_t exec_queue; > + struct intel_bb *ibb; > }; > > +static uint32_t oa_unit_mmio_trigger_reg(struct recording_context *ctx) > +{ > + const struct drm_xe_oa_unit *oau = ctx->oa_unit; > + > + switch (oau->oa_unit_type) { > + case DRM_XE_OA_UNIT_TYPE_OAM: { > + struct drm_xe_query_oa_units *qoa = xe_oa_units(ctx->drm_fd); > + uint8_t *poau = (uint8_t *)&qoa->oa_units[0]; > + int first_oam_id = -1; > + > + /* Find the first OAM unit, as in oa_unit_by_type() */ > + for (int i = 0; i < qoa->num_oa_units; i++) { > + struct drm_xe_oa_unit *u = (struct drm_xe_oa_unit *)poau; > + > + if (u->oa_unit_type == DRM_XE_OA_UNIT_TYPE_OAM) { > + first_oam_id = u->oa_unit_id; > + break; > + } > + poau += sizeof(*u) + u->num_engines * sizeof(u->eci[0]); > + } > + > + assert(first_oam_id != -1); > + > + if (oau->oa_unit_id == first_oam_id) > + return XE_OAM_SCMI_0_BASE_ADJ + OAM_MMIOTRIGGER_OFFSET; > + return XE_OAM_SCMI_1_BASE_ADJ + OAM_MMIOTRIGGER_OFFSET; > + } > + case DRM_XE_OA_UNIT_TYPE_OAM_SAG: > + return XE_OAM_SAG_BASE_ADJ + OAM_MMIOTRIGGER_OFFSET; > + case DRM_XE_OA_UNIT_TYPE_MERT: > + return OAMERT_MMIOTRIGGER; > + case DRM_XE_OA_UNIT_TYPE_OAG: > + return OAG_MMIOTRIGGER; > + default: > + assert(0); > + } > +} > + > static void set_fd_flags(int fd, int flags) > { > int old = fcntl(fd, F_GETFL, 0); > @@ -569,6 +620,28 @@ static bool write_stream_status(struct recording_context *ctx, FILE *output) > return true; > } > > +static uint32_t > +report_reason(const uint32_t *report) > +{ > + return (report[0] >> OAREPORT_REASON_SHIFT) & OAREPORT_REASON_MASK; > +} > + > +static void > +check_mmio_trigger_report(struct recording_context *ctx, const void *report) > +{ > + const struct xe_oa_format *fmt = &oa_formats[ctx->metric_set->perf_oa_format]; > + const uint32_t *report_32 = report; > + uint64_t value; > + > + if (report_reason(report_32)) > + return; > + > + value = (fmt->header == HDR_64_BIT) ? ((const uint64_t *)report)[2] : report_32[2]; > + > + if (value == 0xc0ffee01 || value == 0xc0ffee02) > + fprintf(stdout, "Received trigger report with value 0x%" PRIx64 "\n", value); > +} > + > static bool write_stream_data(struct recording_context *ctx, > char *data, ssize_t size, FILE *output) > { > @@ -582,6 +655,8 @@ static bool write_stream_data(struct recording_context *ctx, > .size = sizeof(header) + format_size, > }; > > + check_mmio_trigger_report(ctx, data); I have merged my bug fix patch, so this now looks correct! Rest lgtm now, so this is: Reviewed-by: Ashutosh Dixit <[email protected]> > + > if (fwrite(&header, sizeof(header), 1, output) != 1) > return false; > > @@ -699,6 +774,22 @@ write_correlation_timestamps(struct recording_context *ctx, FILE *output) > return write_saved_correlation_timestamps(output, &corr); > } > > +static void emit_mmio_triggered_report(struct intel_bb *ibb, uint32_t reg, uint32_t value) > +{ > + intel_bb_out(ibb, MI_LOAD_REGISTER_IMM(1)); > + intel_bb_out(ibb, reg); > + intel_bb_out(ibb, value); > +} > + > +static void emit_oa_trigger(struct recording_context *ctx, uint32_t value) > +{ > + emit_mmio_triggered_report(ctx->ibb, oa_unit_mmio_trigger_reg(ctx), value); > + > + intel_bb_flush_render(ctx->ibb); > + intel_bb_sync(ctx->ibb); > + intel_bb_reset(ctx->ibb, false); > +} > + > static void > read_command_file(struct recording_context *ctx) > { > @@ -714,6 +805,9 @@ read_command_file(struct recording_context *ctx) > uint8_t *dump = malloc(len); > FILE *file; > > + emit_oa_trigger(ctx, 0xc0ffee02); > + write_perf_data(ctx->output_stream, ctx); > + > while (offset < len && > ((ret = read(ctx->command_fifo_fd, > (void *) dump + offset, len - offset)) > 0 > @@ -837,6 +931,13 @@ usage(const char *name) > static void > teardown_recording_context(struct recording_context *ctx) > { > + if (ctx->ibb) > + intel_bb_destroy(ctx->ibb); > + if (ctx->exec_queue) > + xe_exec_queue_destroy(ctx->drm_fd, ctx->exec_queue); > + if (ctx->vm) > + xe_vm_destroy(ctx->drm_fd, ctx->vm); > + > if (ctx->topology) > free(ctx->topology); > > @@ -914,6 +1015,14 @@ static int assign_oa_unit(int fd, struct recording_context *ctx) > return -1; > } > > +static void init_mmio_trigger_ctx(struct recording_context *ctx) > +{ > + ctx->vm = xe_vm_create(ctx->drm_fd, 0, 0); > + ctx->exec_queue = xe_exec_queue_create(ctx->drm_fd, ctx->vm, ctx->hwe, 0); > + ctx->ibb = intel_bb_create_with_context(ctx->drm_fd, ctx->exec_queue, ctx->vm, > + NULL, BATCH_SZ); > +} > + > int > main(int argc, char *argv[]) > { > @@ -1182,6 +1291,9 @@ main(int argc, char *argv[]) > goto fail; > } > > + init_mmio_trigger_ctx(&ctx); > + emit_oa_trigger(&ctx, 0xc0ffee01); > + > corr_period_ns = corr_period * 1000000000ul; > poll_time_ns = corr_period_ns; > > @@ -1229,6 +1341,8 @@ main(int argc, char *argv[]) > } > } > > + /* Emit second OA trigger for the case where circular buffer is not used */ > + emit_oa_trigger(&ctx, 0xc0ffee02); > fprintf(stdout, "Exiting...\n"); > > if (!write_perf_data(ctx.output_stream, &ctx)) { > -- > 2.53.0 >