[PATCH i-g-t 3/6] tests/intel/xe_oa: Sanity check PEC report data for TestOa metric set

Ashutosh Dixit ashutosh.dixit at intel.com
Tue Apr 8 18:12:07 UTC 2025


Implement sanity checking for Xe2 PEC OA reports. Previously there was
sanity checking only for Xe1 OA reports, but no sanity checking for Xe2 PEC
OA reports.

Signed-off-by: Ashutosh Dixit <ashutosh.dixit at intel.com>
---
 tests/intel/xe_oa.c | 121 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 119 insertions(+), 2 deletions(-)

diff --git a/tests/intel/xe_oa.c b/tests/intel/xe_oa.c
index 2440101900..eaf97ae0df 100644
--- a/tests/intel/xe_oa.c
+++ b/tests/intel/xe_oa.c
@@ -966,6 +966,115 @@ accumulator_print(struct accumulator *accumulator, const char *title)
 		igt_debug("\tC%u = %"PRIu64"\n", i, deltas[idx++]);
 }
 
+
+/*
+ * pec_sanity_check_reports() uses the following properties of the TestOa
+ * metric set with the "576B_PEC64LL" or XE_OA_FORMAT_PEC64u64 format. See
+ * e.g. lib/xe/oa-configs/oa-lnl.xml.
+ *
+ * If pec[] is the array of pec qwords following the report header (Bspec
+ * 60942) then we have:
+ *
+ *	pec[2]  : test_event1_cycles
+ *	pec[3]  : test_event1_cycles_xecore0
+ *	pec[4]  : test_event1_cycles_xecore1
+ *	pec[5]  : test_event1_cycles_xecore2
+ *	pec[6]  : test_event1_cycles_xecore3
+ *	pec[21] : test_event1_cycles_xecore4
+ *	pec[22] : test_event1_cycles_xecore5
+ *	pec[23] : test_event1_cycles_xecore6
+ *	pec[24] : test_event1_cycles_xecore7
+ *
+ * test_event1_cycles_xecore* increment with every clock, so they increment
+ * the same as gpu_ticks in report headers in successive reports. And
+ * test_event1_cycles increment by 'gpu_ticks * num_xecores'.
+ *
+ * These equations are not exact due to fluctuations, but are precise when
+ * averaged over long periods.
+ */
+static void pec_sanity_check_one(const u32 *report)
+{
+	int xecore_idx[] = {3, 4, 5, 6, 21, 22, 23, 24};
+	u64 first, *pec = (u64 *)(report + 8);
+
+	igt_debug("\ttest_event1_cycles: %#lx\n", pec[2]);
+	for (int i = 0; i < ARRAY_SIZE(xecore_idx); i++)
+		igt_debug("\ttest_event1_cycles_xecore %d: %#lx\n", i, pec[xecore_idx[i]]);
+
+	/* Compare against the first non-zero test_event1_cycles_xecore* */
+	for (int i = 0; i < ARRAY_SIZE(xecore_idx); i++) {
+		first = pec[xecore_idx[i]];
+		if (first)
+			break;
+	}
+
+	/* test_event1_cycles_xecore* should be within an epsilon of each other */
+	for (int i = 0; i < ARRAY_SIZE(xecore_idx); i++) {
+		igt_debug("n %d: pec[n] %#lx, first %#lx\n",
+			  xecore_idx[i], pec[xecore_idx[i]], first);
+		/* 0 value for pec[xecore_idx[i]] indicates missing xecore */
+		if (pec[xecore_idx[i]])
+			assert_within_epsilon(pec[xecore_idx[i]], first, 0.1);
+	}
+
+	igt_debug("first * num_xecores: %#lx, pec[2] %#lx\n",
+		  first * intel_xe_perf->devinfo.n_eu_sub_slices, pec[2]);
+	/* test_event1_cycles should be close to (test_event1_cycles_xecore* * num_xecores) */
+	assert_within_epsilon(first * intel_xe_perf->devinfo.n_eu_sub_slices, pec[2], 0.1);
+}
+
+static void pec_sanity_check_two(const u32 *report0, const u32 *report1,
+				 struct intel_xe_perf_metric_set *set)
+{
+	u64 tick_delta = oa_tick_delta(report1, report0, set->perf_oa_format);
+	int xecore_idx[] = {3, 4, 5, 6, 21, 22, 23, 24};
+	u64 *pec0 = (u64 *)(report0 + 8);
+	u64 *pec1 = (u64 *)(report1 + 8);
+
+	igt_debug("tick delta = %#lx\n", tick_delta);
+
+	/* Difference in test_event1_cycles_xecore* values should be close to tick_delta */
+	for (int i = 0; i < ARRAY_SIZE(xecore_idx); i++) {
+		igt_debug("n %d: pec1[n] - pec0[n] %#lx, tick delta %#lx\n",
+			  xecore_idx[i], pec1[xecore_idx[i]] - pec0[xecore_idx[i]], tick_delta);
+		/* 0 value for pec[xecore_idx[i]] indicates missing xecore */
+		if (pec1[xecore_idx[i]] && pec0[xecore_idx[i]])
+			assert_within_epsilon(pec1[xecore_idx[i]] - pec0[xecore_idx[i]],
+					      tick_delta, 0.1);
+		/* Same test_event1_cycles_xecore* should be present in all reports */
+		if (pec1[xecore_idx[i]])
+			igt_assert(pec0[xecore_idx[i]]);
+	}
+
+	igt_debug("pec1[2] - pec0[2] %#lx, tick_delta * num_xecores: %#lx\n",
+		  pec1[2] - pec0[2], tick_delta * intel_xe_perf->devinfo.n_eu_sub_slices);
+	/* Difference in test_event1_cycles should be close to (tick_delta * num_xecores) */
+	assert_within_epsilon(pec1[2] - pec0[2],
+			      tick_delta * intel_xe_perf->devinfo.n_eu_sub_slices, 0.1);
+}
+
+/* Sanity check Xe2+ PEC reports. Note: report format must be @set->perf_oa_format */
+static void pec_sanity_check_reports(const u32 *report0, const u32 *report1,
+				     struct intel_xe_perf_metric_set *set)
+{
+	if (igt_run_in_simulation() || intel_graphics_ver(devid) < IP_VER(20, 0)) {
+		igt_debug("%s: Skip checking PEC reports in simulation or Xe1\n", __func__);
+		return;
+	}
+
+	if (strcmp(set->name, "TestOa")) {
+		igt_debug("%s: Can't check reports for metric set %s\n", __func__, set->name);
+		return;
+	}
+
+	dump_report(report0, set->perf_raw_size, "pec_report0");
+	dump_report(report1, set->perf_raw_size, "pec_report1");
+
+	pec_sanity_check_one(report0);
+	pec_sanity_check_one(report1);
+	pec_sanity_check_two(report0, report1, set);
+}
+
 /* The TestOa metric set is designed so */
 static void
 sanity_check_reports(const uint32_t *oa_report0, const uint32_t *oa_report1,
@@ -1589,6 +1698,9 @@ static void test_oa_formats(const struct drm_xe_engine_class_instance *hwe)
 
 		print_reports(oa_report0, oa_report1, i);
 		sanity_check_reports(oa_report0, oa_report1, i);
+
+		if (i == metric_set(hwe)->perf_oa_format)
+			pec_sanity_check_reports(oa_report0, oa_report1, metric_set(hwe));
 	}
 }
 
@@ -2527,8 +2639,10 @@ test_non_zero_reason(const struct drm_xe_engine_class_instance *hwe, size_t oa_b
 
 		igt_assert_neq(reason, 0);
 
-		if (last_report)
+		if (last_report) {
 			sanity_check_reports(last_report, report, fmt);
+			pec_sanity_check_reports(last_report, report, metric_set(hwe));
+		}
 
 		last_report = report;
 	}
@@ -4266,9 +4380,12 @@ static void mmap_check_reports(void *oa_vaddr, uint32_t oa_size,
 			continue;
 
 		timer_reports++;
-		if (timer_reports >= 3)
+		if (timer_reports >= 3) {
 			sanity_check_reports(reports - 2 * report_words,
 					     reports - report_words, fmt);
+			pec_sanity_check_reports(reports - 2 * report_words,
+						 reports - report_words, metric_set(hwe));
+		}
 	}
 
 	igt_assert(timer_reports >= 3);
-- 
2.48.1



More information about the igt-dev mailing list