[PATCH i-g-t v4 2/3] tests/intel/xe_pmu: Add PMU test to validate engine activity stats

Riana Tauro riana.tauro at intel.com
Tue Feb 25 07:13:10 UTC 2025


Add a test to validate engine activity by reading PMU counters
(engine-active-ticks, engine-total-ticks) when running
workload on every engine

v2: rename busy to active
    add assert to format events (Umesh)
    add a helper macro

v3: initialize config (Umesh)

Signed-off-by: Riana Tauro <riana.tauro at intel.com>
Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa at intel.com>
---
 tests/intel/xe_pmu.c | 130 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 110 insertions(+), 20 deletions(-)

diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c
index d408d0f99..692cc986f 100644
--- a/tests/intel/xe_pmu.c
+++ b/tests/intel/xe_pmu.c
@@ -12,24 +12,23 @@
  * Test category: Functional tests
  */
 
-#include <fcntl.h>
-#include <limits.h>
-#include <time.h>
-#include <errno.h>
-#include <dirent.h>
-#include <string.h>
-#include <sys/time.h>
-
 #include "igt.h"
-#include "igt_device.h"
 #include "igt_perf.h"
 #include "igt_sysfs.h"
 
 #include "xe/xe_gt.h"
+#include "xe/xe_ioctl.h"
+#include "xe/xe_spin.h"
 
 #define SLEEP_DURATION 2 /* in seconds */
 const double tolerance = 0.1;
 
+#define test_each_engine(test, fd, hwe) \
+	igt_subtest_with_dynamic(test) \
+		xe_for_each_engine(fd, hwe) \
+			igt_dynamic_f("engine-%s%d", xe_engine_class_string(hwe->engine_class), \
+				      hwe->engine_instance)
+
 static int open_pmu(int xe, uint64_t config)
 {
 	int fd;
@@ -41,6 +40,17 @@ static int open_pmu(int xe, uint64_t config)
 	return fd;
 }
 
+static int open_group(int xe, uint64_t config, int group)
+{
+	int fd;
+
+	fd = igt_perf_open_group(xe_perf_type_id(xe), config, group);
+	igt_skip_on(fd < 0 && errno == ENODEV);
+	igt_assert(fd >= 0);
+
+	return fd;
+}
+
 static uint64_t __pmu_read_single(int fd, uint64_t *ts)
 {
 	uint64_t data[2];
@@ -52,6 +62,19 @@ static uint64_t __pmu_read_single(int fd, uint64_t *ts)
 	return data[0];
 }
 
+static uint64_t pmu_read_multi(int fd, unsigned int num, uint64_t *val)
+{
+	uint64_t buf[2 + num];
+	unsigned int i;
+
+	igt_assert_eq(read(fd, buf, sizeof(buf)), sizeof(buf));
+
+	for (i = 0; i < num; i++)
+		val[i] = buf[2 + i];
+
+	return buf[1];
+}
+
 static unsigned long read_idle_residency(int fd, int gt)
 {
 	unsigned long residency = 0;
@@ -65,23 +88,86 @@ static unsigned long read_idle_residency(int fd, int gt)
 	return residency;
 }
 
-static uint64_t get_event_config(int xe, unsigned int gt, char *event)
+static uint64_t add_format_config(const char *xe_device, const char *format, uint64_t val)
 {
 	int ret;
-	char xe_device[100];
-	uint64_t pmu_config;
 	uint32_t shift;
+	uint64_t config;
+
+	ret = perf_event_format(xe_device, format, &shift);
+	igt_assert(ret >= 0);
+	config = val << shift;
+
+	return config;
+}
+
+static uint64_t get_event_config(int xe, unsigned int gt, struct drm_xe_engine_class_instance *eci,
+				 const char *event)
+{
+	char xe_device[100];
+	uint64_t pmu_config = 0;
+	int ret;
 
 	xe_perf_device(xe, xe_device, sizeof(xe_device));
 	ret = perf_event_config(xe_device, event, &pmu_config);
 	igt_assert(ret >= 0);
-	ret = perf_event_format(xe_device, "gt", &shift);
-	igt_assert(ret >= 0);
-	pmu_config |= (uint64_t)gt << shift;
+	pmu_config |= add_format_config(xe_device, "gt", gt);
+
+	if (eci) {
+		pmu_config |= add_format_config(xe_device, "engine_class", eci->engine_class);
+		pmu_config |= add_format_config(xe_device, "engine_instance", eci->engine_instance);
+	}
 
 	return pmu_config;
 }
 
+/**
+ * SUBTEST: engine-activity-load
+ * Description: Test to validate engine activity stats by running a workload and
+ *              reading engine active ticks and engine total ticks PMU counters
+ */
+static void engine_activity(int fd, struct drm_xe_engine_class_instance *eci)
+{
+	uint64_t config, engine_active_ticks, engine_total_ticks, before[2], after[2];
+	struct xe_cork *cork = NULL;
+	uint32_t vm;
+	int pmu_fd[2];
+
+	config = get_event_config(fd, eci->gt_id, eci, "engine-active-ticks");
+	pmu_fd[0] = open_group(fd, config, -1);
+
+	config = get_event_config(fd, eci->gt_id, eci, "engine-total-ticks");
+	pmu_fd[1] = open_group(fd, config, pmu_fd[0]);
+
+	vm = xe_vm_create(fd, 0, 0);
+	cork = xe_cork_create_opts(fd, eci, vm, 1, 1);
+	xe_cork_sync_start(fd, cork);
+
+	pmu_read_multi(pmu_fd[0], 2, before);
+	usleep(SLEEP_DURATION * USEC_PER_SEC);
+	pmu_read_multi(pmu_fd[0], 2, after);
+
+	xe_cork_sync_end(fd, cork);
+
+	engine_active_ticks = after[0] - before[0];
+	engine_total_ticks = after[1] - before[1];
+
+	igt_debug("Engine active ticks:  after %ld, before %ld delta %ld\n", after[0], before[0],
+		  engine_active_ticks);
+	igt_debug("Engine total ticks: after %ld, before %ld delta %ld\n", after[1], before[1],
+		  engine_total_ticks);
+
+	if (cork)
+		xe_cork_destroy(fd, cork);
+
+	xe_vm_destroy(fd, vm);
+
+	close(pmu_fd[0]);
+	close(pmu_fd[1]);
+
+	assert_within_epsilon(engine_active_ticks, engine_total_ticks, tolerance);
+}
+
 /**
  * SUBTEST: gt-c6-idle
  * Description: Basic residency test to validate idle residency
@@ -91,14 +177,12 @@ static void test_gt_c6_idle(int xe, unsigned int gt)
 {
 	int pmu_fd;
 	uint64_t pmu_config;
-	char event[100];
 	uint64_t ts[2];
 	unsigned long slept, start, end;
 	uint64_t val;
 
 	/* Get the PMU config for the gt-c6 event */
-	sprintf(event, "gt-c6-residency");
-	pmu_config = get_event_config(xe, gt, event);
+	pmu_config = get_event_config(xe, gt, NULL, "gt-c6-residency");
 
 	pmu_fd = open_pmu(xe, pmu_config);
 
@@ -125,16 +209,22 @@ static void test_gt_c6_idle(int xe, unsigned int gt)
 igt_main
 {
 	int fd, gt;
+	struct drm_xe_engine_class_instance *eci;
 
 	igt_fixture {
 		fd = drm_open_driver(DRIVER_XE);
-		igt_require(!IS_PONTEVECCHIO(xe_dev_id(fd)));
 	}
 
 	igt_describe("Validate PMU gt-c6 residency counters when idle");
-	igt_subtest("gt-c6-idle")
+	igt_subtest("gt-c6-idle") {
+		igt_require(!IS_PONTEVECCHIO(xe_dev_id(fd)));
 		xe_for_each_gt(fd, gt)
 			test_gt_c6_idle(fd, gt);
+	}
+
+	igt_describe("Validate engine activity with workload");
+	test_each_engine("engine-activity-load", fd, eci)
+		engine_activity(fd, eci);
 
 	igt_fixture {
 		close(fd);
-- 
2.47.1



More information about the igt-dev mailing list