All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports
@ 2021-08-30 19:33 Umesh Nerlige Ramappa
  2021-08-30 19:33 ` [igt-dev] [PATCH 2/5] i915/perf: Add tests for mapped OA buffer Umesh Nerlige Ramappa
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Umesh Nerlige Ramappa @ 2021-08-30 19:33 UTC (permalink / raw)
  To: igt-dev, Ashutosh Dixit; +Cc: Lionel G Landwerlin

From: Lionel G Landwerlin <lionel.g.landwerlin@intel.com>

By whitelisting a couple of registers we can allow an application
batch to trigger OA reports in the OA buffer by switching back & forth
an inverter on the condition logic.

v2: Wait before sampling the timestamp used to end the OA buffer search
v3:
- Ensure OA regs are whitelisted and reports are triggered only when
  perf_stream_paranoid is set to 0.
- Drop root to trigger reports.
v4:
- wait for children after igt_assert
- use new api for intel batch buffer
- clean up test code

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 tests/i915/perf.c | 421 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 404 insertions(+), 17 deletions(-)

diff --git a/tests/i915/perf.c b/tests/i915/perf.c
index e641d5d2..fa3840eb 100644
--- a/tests/i915/perf.c
+++ b/tests/i915/perf.c
@@ -53,6 +53,8 @@ IGT_TEST_DESCRIPTION("Test the i915 perf metrics streaming interface");
 #define OAREPORT_REASON_SHIFT          19
 #define OAREPORT_REASON_TIMER          (1<<0)
 #define OAREPORT_REASON_INTERNAL       (3<<1)
+#define OAREPORT_REASON_TRIGGER1       (1<<1)
+#define OAREPORT_REASON_TRIGGER2       (1<<2)
 #define OAREPORT_REASON_CTX_SWITCH     (1<<3)
 #define OAREPORT_REASON_GO             (1<<4)
 #define OAREPORT_REASON_CLK_RATIO      (1<<5)
@@ -204,6 +206,7 @@ static struct intel_perf *intel_perf = NULL;
 static struct intel_perf_metric_set *test_set = NULL;
 static bool *undefined_a_counters;
 static uint64_t oa_exp_1_millisec;
+struct intel_mmio_data mmio_data;
 
 static igt_render_copyfunc_t render_copy = NULL;
 static uint32_t (*read_report_ticks)(const uint32_t *report,
@@ -294,6 +297,23 @@ __perf_open(int fd, struct drm_i915_perf_open_param *param, bool prevent_pm)
 	return ret;
 }
 
+static int i915_perf_revision(int fd)
+{
+	drm_i915_getparam_t gp;
+	int value = 1, ret;
+
+	gp.param = I915_PARAM_PERF_REVISION;
+	gp.value = &value;
+	ret = igt_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	if (ret == -1) {
+		/* If the param is missing, consider version 1. */
+		igt_assert_eq(errno, EINVAL);
+		return 1;
+	}
+
+	return value;
+}
+
 static int
 lookup_format(int i915_perf_fmt_id)
 {
@@ -3151,6 +3171,283 @@ emit_stall_timestamp_and_rpc(struct intel_bb *ibb,
 	emit_report_perf_count(ibb, dst, report_dst_offset, report_id);
 }
 
+/* The following register all have the same layout. */
+#define OAREPORTTRIG2 (0x2744)
+#define   OAREPORTTRIG2_INVERT_A_0  (1 << 0)
+#define   OAREPORTTRIG2_INVERT_A_1  (1 << 1)
+#define   OAREPORTTRIG2_INVERT_A_2  (1 << 2)
+#define   OAREPORTTRIG2_INVERT_A_3  (1 << 3)
+#define   OAREPORTTRIG2_INVERT_A_4  (1 << 4)
+#define   OAREPORTTRIG2_INVERT_A_5  (1 << 5)
+#define   OAREPORTTRIG2_INVERT_A_6  (1 << 6)
+#define   OAREPORTTRIG2_INVERT_A_7  (1 << 7)
+#define   OAREPORTTRIG2_INVERT_A_8  (1 << 8)
+#define   OAREPORTTRIG2_INVERT_A_9  (1 << 9)
+#define   OAREPORTTRIG2_INVERT_A_10 (1 << 10)
+#define   OAREPORTTRIG2_INVERT_A_11 (1 << 11)
+#define   OAREPORTTRIG2_INVERT_A_12 (1 << 12)
+#define   OAREPORTTRIG2_INVERT_A_13 (1 << 13)
+#define   OAREPORTTRIG2_INVERT_A_14 (1 << 14)
+#define   OAREPORTTRIG2_INVERT_A_15 (1 << 15)
+#define   OAREPORTTRIG2_INVERT_B_0  (1 << 16)
+#define   OAREPORTTRIG2_INVERT_B_1  (1 << 17)
+#define   OAREPORTTRIG2_INVERT_B_2  (1 << 18)
+#define   OAREPORTTRIG2_INVERT_B_3  (1 << 19)
+#define   OAREPORTTRIG2_INVERT_C_0  (1 << 20)
+#define   OAREPORTTRIG2_INVERT_C_1  (1 << 21)
+#define   OAREPORTTRIG2_INVERT_D_0  (1 << 22)
+#define   OAREPORTTRIG2_THRESHOLD_ENABLE      (1 << 23)
+#define   OAREPORTTRIG2_REPORT_TRIGGER_ENABLE (1 << 31)
+#define OAREPORTTRIG6 (0x2754)
+#define OA_PERF_COUNTER_A(idx) (0x2800 + 8 * (idx))
+#define GEN8_OASTATUS (0x2b08)
+
+#define GEN12_OAREPORTTRIG2 (0xd924)
+#define GEN12_OAREPORTTRIG6 (0xd934)
+#define GEN12_OAG_PERF_COUNTER_A(idx) (0xD980 + 8 * (idx))
+#define GEN12_OAG_OASTATUS (0xdafc)
+
+#define RING_FORCE_TO_NONPRIV_ADDRESS_MASK 0x03fffffc
+
+/*
+ * We have 2 trigger registers that each generate a different
+ * report reason.
+ */
+static const uint32_t gen9_oa_wl[] = {
+	OAREPORTTRIG2,
+	OAREPORTTRIG6,
+	OA_PERF_COUNTER_A(18),
+	GEN8_OASTATUS,
+};
+static const uint32_t gen12_oa_wl[] = {
+	GEN12_OAREPORTTRIG2,
+	GEN12_OAREPORTTRIG6,
+	GEN12_OAG_PERF_COUNTER_A(18),
+	GEN12_OAG_OASTATUS,
+};
+
+static const uint32_t nonpriv_slots[] = {
+	0x24d0, 0x24d4, 0x24d8, 0x24dc, 0x24e0, 0x24e4, 0x24e8, 0x24ec,
+	0x24f0, 0x24f4, 0x24f8, 0x24fc, 0x2010, 0x2014, 0x2018, 0x201c,
+	0x21e0, 0x21e4, 0x21e8, 0x21ec,
+};
+
+struct test_perf {
+	const uint32_t *slots;
+	uint32_t num_slots;
+	const uint32_t *wl;
+	uint32_t num_wl;
+} perf;
+
+static void perf_init_whitelist(void)
+{
+	perf.slots = nonpriv_slots;
+
+	if (intel_gen(devid) >= 12) {
+		perf.num_slots = 20;
+		perf.wl = gen12_oa_wl;
+		perf.num_wl = i915_perf_revision(drm_fd) < 7 ? 2 :
+			       ARRAY_SIZE(gen12_oa_wl);
+	} else {
+		perf.num_slots = 12;
+		perf.wl = gen9_oa_wl;
+		perf.num_wl = i915_perf_revision(drm_fd) < 7 ? 2 :
+			       ARRAY_SIZE(gen9_oa_wl);
+	}
+}
+
+static void
+emit_triggered_oa_report(struct intel_bb *ibb, uint32_t trigger)
+{
+	const uint32_t *triggers = perf.wl;
+
+	assert(trigger <= 1);
+
+	intel_bb_out(ibb, MI_LOAD_REGISTER_IMM);
+	intel_bb_out(ibb, triggers[trigger]);
+	intel_bb_out(ibb, OAREPORTTRIG2_INVERT_C_1 |
+			  OAREPORTTRIG2_REPORT_TRIGGER_ENABLE);
+	intel_bb_out(ibb, MI_LOAD_REGISTER_IMM);
+	intel_bb_out(ibb, triggers[trigger]);
+	intel_bb_out(ibb, OAREPORTTRIG2_INVERT_C_1 |
+			  OAREPORTTRIG2_INVERT_D_0 |
+			  OAREPORTTRIG2_REPORT_TRIGGER_ENABLE);
+}
+
+static uint64_t
+rcs_timestmap_reg_read(int fd)
+{
+	struct drm_i915_reg_read rr = {
+		.offset = 0x2358 | I915_REG_READ_8B_WA, /* render ring timestamp */
+	};
+
+	do_ioctl(fd, DRM_IOCTL_I915_REG_READ, &rr);
+
+	return rr.val;
+}
+
+/*
+ * Verify that we can trigger OA reports into the OA buffer using
+ * MI_LRI.
+ */
+static void
+test_triggered_oa_reports(int paranoid)
+{
+	int oa_exponent = max_oa_exponent_for_period_lte(1000000);
+	uint64_t properties[] = {
+		DRM_I915_PERF_PROP_CTX_HANDLE, UINT64_MAX, /* updated below */
+
+		/* Note: we have to specify at least one sample property even
+		 * though we aren't interested in samples in this case
+		 */
+		DRM_I915_PERF_PROP_SAMPLE_OA, true,
+
+		/* OA unit configuration */
+		DRM_I915_PERF_PROP_OA_METRICS_SET, test_set->perf_oa_metrics_set,
+		DRM_I915_PERF_PROP_OA_FORMAT, test_set->perf_oa_format,
+		DRM_I915_PERF_PROP_OA_EXPONENT, oa_exponent,
+
+		/* Note: no OA exponent specified in this case */
+	};
+	struct drm_i915_perf_open_param param = {
+		.flags = I915_PERF_FLAG_FD_CLOEXEC,
+		.num_properties = ARRAY_SIZE(properties) / 2,
+		.properties_ptr = to_user_pointer(properties),
+	};
+	struct drm_i915_perf_record_header *header;
+	struct buf_ops *bops;
+	uint32_t context;
+	struct igt_helper_process child = {};
+	struct intel_bb *ibb;
+	struct intel_buf src[2], dst[2];
+	uint64_t timestamp32_mask = (1ull << 32) - 1;
+	uint64_t timestamps[2];
+	uint32_t buf_size = 16 * 1024 * 1024;
+	uint8_t *buf = malloc(buf_size);
+	int width = 800;
+	int height = 600;
+	uint32_t trigger_counts[2] = { 0, };
+	int ret;
+
+	write_u64_file("/proc/sys/dev/i915/perf_stream_paranoid", paranoid);
+
+	do {
+		igt_fork_helper(&child) {
+			if (!paranoid)
+				igt_drop_root();
+
+			bops = buf_ops_create(drm_fd);
+
+			scratch_buf_init(bops, &src[0], width, height, 0xff0000ff);
+			scratch_buf_init(bops, &dst[0], width, height, 0x00ff00ff);
+			scratch_buf_init(bops, &src[1], 2 * width, height, 0xff0000ff);
+			scratch_buf_init(bops, &dst[1], 2 * width, height, 0x00ff00ff);
+
+			context = gem_context_create(drm_fd);
+			igt_assert(context);
+			ibb = intel_bb_create_with_context(drm_fd, context, BATCH_SZ);
+			properties[1] = context;
+
+			timestamps[0] = rcs_timestmap_reg_read(drm_fd);
+
+			stream_fd = __perf_open(drm_fd, &param, false);
+
+			emit_triggered_oa_report(ibb, 0);
+
+			render_copy(ibb,
+				    &src[0], 0, 0, width, height,
+				    &dst[0], 0, 0);
+
+			emit_triggered_oa_report(ibb, 0);
+
+			emit_triggered_oa_report(ibb, 1);
+
+			render_copy(ibb,
+				    &src[1], 0, 0, 2 * width, height,
+				    &dst[1], 0, 0);
+
+			emit_triggered_oa_report(ibb, 1);
+
+			intel_bb_flush_render(ibb);
+			intel_bb_sync(ibb);
+
+			timestamps[1] = rcs_timestmap_reg_read(drm_fd);
+
+			if (timestamps[1] < timestamps[0] ||
+			    (timestamps[1] & timestamp32_mask) < (timestamps[1] & timestamp32_mask)) {
+				igt_debug("Timestamp rollover, trying again\n");
+				exit(EAGAIN);
+			}
+
+			ret = i915_read_reports_until_timestamp(test_set->perf_oa_format,
+								buf, buf_size,
+								timestamps[0] & timestamp32_mask,
+								timestamps[1] & timestamp32_mask);
+
+			for (size_t offset = 0; offset < ret; offset += header->size) {
+				uint32_t *report;
+
+				header = (void *)(buf + offset);
+
+				igt_assert_eq(header->pad, 0); /* Reserved */
+
+				igt_assert_neq(header->type, DRM_I915_PERF_RECORD_OA_BUFFER_LOST);
+
+				if (header->type == DRM_I915_PERF_RECORD_OA_REPORT_LOST)
+					continue;
+
+				/* Currently the only other record type expected is a
+				 * _SAMPLE. Notably this test will need updating if
+				 * i915-perf is extended in the future with additional
+				 * record types.
+				 */
+				igt_assert_eq(header->type, DRM_I915_PERF_RECORD_SAMPLE);
+
+				report = (void *)(header + 1);
+
+				igt_debug("report ts=0x%08x hw_id=0x%08x reason=%s\n",
+					  report[1], report[2],
+					  gen8_read_report_reason(report));
+
+				if (gen8_report_reason(report) & OAREPORT_REASON_TRIGGER1) {
+					igt_assert_eq(trigger_counts[1], 0);
+					trigger_counts[0]++;
+				}
+				if (gen8_report_reason(report) & OAREPORT_REASON_TRIGGER2) {
+					igt_assert_eq(trigger_counts[0], 2);
+					trigger_counts[1]++;
+				}
+			}
+
+			if (paranoid) {
+				igt_assert_eq(trigger_counts[0], 0);
+				igt_assert_eq(trigger_counts[1], 0);
+			} else {
+				igt_assert_eq(trigger_counts[0], 2);
+				igt_assert_eq(trigger_counts[1], 2);
+			}
+
+			for (int i = 0; i < ARRAY_SIZE(src); i++) {
+				intel_buf_close(bops, &src[i]);
+				intel_buf_close(bops, &dst[i]);
+			}
+
+			intel_bb_destroy(ibb);
+			gem_context_destroy(drm_fd, context);
+			buf_ops_destroy(bops);
+			__perf_close(stream_fd);
+		}
+
+		ret = igt_wait_helper(&child);
+
+		igt_assert(WEXITSTATUS(ret) == EAGAIN ||
+			   WEXITSTATUS(ret) == 0);
+
+	} while (WEXITSTATUS(ret) == EAGAIN);
+
+	free(buf);
+}
+
 /* Tests the INTEL_performance_query use case where an unprivileged process
  * should be able to configure the OA unit for per-context metrics (for a
  * context associated with that process' drm file descriptor) and the counters
@@ -4777,6 +5074,88 @@ test_whitelisted_registers_userspace_config(void)
 	i915_perf_remove_config(drm_fd, config_id);
 }
 
+static void dump_whitelist(const char *msg)
+{
+	int i;
+
+	igt_debug("%s\n", msg);
+
+	for (i = 0; i < perf.num_slots; i++)
+		igt_debug("FORCE_TO_NON_PRIV_%02d = %08x\n",
+			  i, intel_register_read(&mmio_data, perf.slots[i]));
+}
+
+static bool in_whitelist(uint32_t reg)
+{
+	int i;
+
+	for (i = 0; i < perf.num_slots; i++) {
+		uint32_t fpriv = intel_register_read(&mmio_data, perf.slots[i]);
+
+		if ((fpriv & RING_FORCE_TO_NONPRIV_ADDRESS_MASK) == reg)
+			return true;
+	}
+
+	return false;
+}
+
+static void oa_regs_in_whitelist(bool are_present)
+{
+	int i;
+
+	if (are_present) {
+		for (i = 0; i < perf.num_wl; i++)
+			igt_assert(in_whitelist(perf.wl[i]));
+	} else {
+		for (i = 0; i < perf.num_wl; i++)
+			igt_assert(!in_whitelist(perf.wl[i]));
+	}
+}
+
+static void test_oa_regs_whitelist(int paranoid)
+{
+	uint64_t properties[] = {
+		DRM_I915_PERF_PROP_SAMPLE_OA, true,
+		DRM_I915_PERF_PROP_OA_METRICS_SET, test_set->perf_oa_metrics_set,
+		DRM_I915_PERF_PROP_OA_FORMAT, test_set->perf_oa_format,
+		DRM_I915_PERF_PROP_OA_EXPONENT, oa_exp_1_millisec,
+
+	};
+	struct drm_i915_perf_open_param param = {
+		.flags = I915_PERF_FLAG_FD_CLOEXEC,
+		.num_properties = sizeof(properties) / 16,
+		.properties_ptr = to_user_pointer(properties),
+	};
+	write_u64_file("/proc/sys/dev/i915/perf_stream_paranoid", paranoid);
+	intel_register_access_init(&mmio_data, intel_get_pci_device(),
+				   0, drm_fd);
+	stream_fd = __perf_open(drm_fd, &param, false);
+
+	dump_whitelist("oa whitelisted");
+
+	/*
+	 * oa registers are whitelisted only if paranoid = 0. if so, make sure
+	 * that the registers are in the nonpriv slots. if not, make sure the
+	 * registers are NOT present in the nonpriv slots.
+	 */
+	if (paranoid)
+		oa_regs_in_whitelist(false);
+	else
+		oa_regs_in_whitelist(true);
+
+	__perf_close(stream_fd);
+
+	dump_whitelist("oa remove whitelist");
+
+	/*
+	 * after perf close, check that registers are removed from the nonpriv
+	 * slots
+	 */
+	oa_regs_in_whitelist(false);
+
+	intel_register_access_fini(&mmio_data);
+}
+
 static unsigned
 read_i915_module_ref(void)
 {
@@ -4889,23 +5268,6 @@ test_sysctl_defaults(void)
 	igt_assert_eq(max_freq, 100000);
 }
 
-static int i915_perf_revision(int fd)
-{
-	drm_i915_getparam_t gp;
-	int value = 1, ret;
-
-	gp.param = I915_PARAM_PERF_REVISION;
-	gp.value = &value;
-	ret = igt_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
-	if (ret == -1) {
-		/* If the param is missing, consider version 1. */
-		igt_assert_eq(errno, EINVAL);
-		return 1;
-	}
-
-	return value;
-}
-
 igt_main
 {
 	igt_fixture {
@@ -5119,6 +5481,31 @@ igt_main
 	igt_subtest("whitelisted-registers-userspace-config")
 		test_whitelisted_registers_userspace_config();
 
+
+	igt_subtest_group {
+		igt_fixture {
+			igt_require(intel_gen(devid) > 8);
+			igt_require(i915_perf_revision(drm_fd) >= 6);
+			perf_init_whitelist();
+		}
+
+		igt_describe("Verify that OA registers are whitelisted for paranoid 0");
+		igt_subtest("oa-regs-whitelisted")
+			test_oa_regs_whitelist(0);
+
+		igt_describe("Verify that OA registers are not whitelisted for paranoid 1");
+		igt_subtest("oa-regs-not-whitelisted")
+			test_oa_regs_whitelist(1);
+
+		igt_describe("Verify reports triggered when perf_stream_paranoid is 0");
+		igt_subtest("triggered-oa-reports-paranoid-0")
+			test_triggered_oa_reports(0);
+
+		igt_describe("Verify reports not triggered when perf_stream_paranoid is 1");
+		igt_subtest("triggered-oa-reports-paranoid-1")
+			test_triggered_oa_reports(1);
+	}
+
 	igt_fixture {
 		/* leave sysctl options in their default state... */
 		write_u64_file("/proc/sys/dev/i915/oa_max_sample_rate", 100000);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] [PATCH 2/5] i915/perf: Add tests for mapped OA buffer
  2021-08-30 19:33 [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports Umesh Nerlige Ramappa
@ 2021-08-30 19:33 ` Umesh Nerlige Ramappa
  2021-08-30 19:33 ` [igt-dev] [PATCH 3/5] lib/i915/perf: Add new record for mmaped " Umesh Nerlige Ramappa
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Umesh Nerlige Ramappa @ 2021-08-30 19:33 UTC (permalink / raw)
  To: igt-dev, Ashutosh Dixit; +Cc: Lionel G Landwerlin

For applications that need a faster way to access reports in the OA
buffer, i915 now provides a way to map the OA buffer to privileged user
space. Validate the mapped OA buffer.

v2: Fail on forked-privileged access to mapped oa buffer (Chris)
v3: (Ashutosh)
- Use sys/mman.h and drop MAP_FAILED define
- Update assert, vaddr access, uapi comment

Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
---
 include/drm-uapi/i915_drm.h |  33 +++++
 tests/i915/perf.c           | 287 ++++++++++++++++++++++++++++++++++++
 2 files changed, 320 insertions(+)

diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
index a1c0030c..4cdc8b17 100644
--- a/include/drm-uapi/i915_drm.h
+++ b/include/drm-uapi/i915_drm.h
@@ -2151,6 +2151,39 @@ struct drm_i915_perf_open_param {
  */
 #define I915_PERF_IOCTL_CONFIG	_IO('i', 0x2)
 
+/*
+ * Returns OA buffer properties to be used with mmap.
+ *
+ * This ioctl is available in perf revision 8.
+ */
+#define I915_PERF_IOCTL_GET_OA_BUFFER_INFO _IOWR('i', 0x3, struct drm_i915_perf_oa_buffer_info)
+
+/**
+ * OA buffer size and offset.
+ *
+ * OA output buffer
+ *   type: 0
+ *   flags: mbz
+ *
+ *   After querying the info, pass (size,offset) to mmap(),
+ *
+ *   mmap(0, info.size, PROT_READ, MAP_PRIVATE, perf_fd, info.offset).
+ *
+ *   Note that only a private (not shared between processes, or across fork())
+ *   read-only mmapping is allowed.
+ *
+ *   HW is continually writing data to the mapped  OA buffer and it conforms to
+ *   the OA format as specified by user config. The buffer provides reports that
+ *   have OA counters - A, B and C.
+ */
+struct drm_i915_perf_oa_buffer_info {
+	__u32 type;   /* in */
+	__u32 flags;  /* in */
+	__u64 size;   /* out */
+	__u64 offset; /* out */
+	__u64 rsvd;   /* mbz */
+};
+
 /*
  * Common to all i915 perf records
  */
diff --git a/tests/i915/perf.c b/tests/i915/perf.c
index fa3840eb..ceb93392 100644
--- a/tests/i915/perf.c
+++ b/tests/i915/perf.c
@@ -29,6 +29,7 @@
 #include <inttypes.h>
 #include <errno.h>
 #include <signal.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/times.h>
@@ -5156,6 +5157,262 @@ static void test_oa_regs_whitelist(int paranoid)
 	intel_register_access_fini(&mmio_data);
 }
 
+#define OA_BUFFER_DATA(tail, head, oa_buffer_size) \
+	(((tail) - (head)) & ((oa_buffer_size) - 1))
+
+static uint32_t oa_status_reg(void)
+{
+	uint32_t status;
+
+	intel_register_access_init(&mmio_data, intel_get_pci_device(),
+				   0, drm_fd);
+	if (IS_HASWELL(devid))
+		status = intel_register_read(&mmio_data, 0x2346) & 0x7;
+	else if (IS_GEN12(devid))
+		status = intel_register_read(&mmio_data, 0xdafc) & 0x7;
+	else
+		status = intel_register_read(&mmio_data, 0x2b08) & 0xf;
+
+	intel_register_access_fini(&mmio_data);
+
+	return status;
+}
+
+static jmp_buf jmp;
+static void __attribute__((noreturn)) sigtrap(int sig)
+{
+	siglongjmp(jmp, sig);
+}
+
+static void try_invalid_access(void *vaddr)
+{
+	sighandler_t old_sigsegv;
+	uint32_t dummy;
+
+	old_sigsegv = signal(SIGSEGV, sigtrap);
+	switch (sigsetjmp(jmp, SIGSEGV)) {
+	case SIGSEGV:
+		break;
+	case 0:
+		dummy = READ_ONCE(*((uint32_t *)vaddr));
+		(void) dummy;
+	default:
+		igt_assert(!"reached");
+		break;
+	}
+	signal(SIGSEGV, old_sigsegv);
+}
+
+static void invalid_param_map_oa_buffer(void)
+{
+	struct drm_i915_perf_oa_buffer_info oa_buffer = { 0 };
+	void *oa_vaddr = NULL;
+
+	do_ioctl(stream_fd, I915_PERF_IOCTL_GET_OA_BUFFER_INFO, &oa_buffer);
+
+	igt_debug("size        = %llu\n", oa_buffer.size);
+	igt_debug("offset      = %llx\n", oa_buffer.offset);
+
+	igt_assert_eq(oa_buffer.size & (oa_buffer.size - 1), 0);
+
+	/* try a couple invalid mmaps */
+	/* bad prots */
+	oa_vaddr = mmap(0, oa_buffer.size, PROT_WRITE, MAP_PRIVATE, stream_fd, oa_buffer.offset);
+	igt_assert(oa_vaddr == MAP_FAILED);
+
+	oa_vaddr = mmap(0, oa_buffer.size, PROT_EXEC, MAP_PRIVATE, stream_fd, oa_buffer.offset);
+	igt_assert(oa_vaddr == MAP_FAILED);
+
+	/* bad MAPs */
+	oa_vaddr = mmap(0, oa_buffer.size, PROT_READ, MAP_SHARED, stream_fd, oa_buffer.offset);
+	igt_assert(oa_vaddr == MAP_FAILED);
+
+	/* bad offsets */
+	oa_vaddr = mmap(0, oa_buffer.size, PROT_READ, MAP_PRIVATE, stream_fd, 0);
+	igt_assert(oa_vaddr == MAP_FAILED);
+
+	oa_vaddr = mmap(0, oa_buffer.size, PROT_READ, MAP_PRIVATE, stream_fd, 8192);
+	igt_assert(oa_vaddr == MAP_FAILED);
+
+	oa_vaddr = mmap(0, oa_buffer.size, PROT_READ, MAP_PRIVATE, stream_fd, 11);
+	igt_assert(oa_vaddr == MAP_FAILED);
+
+	/* bad size */
+	oa_vaddr = mmap(0, oa_buffer.size + 1, PROT_READ, MAP_PRIVATE, stream_fd, oa_buffer.offset);
+	igt_assert(oa_vaddr == MAP_FAILED);
+
+	/* do the right thing */
+	oa_vaddr = mmap(0, oa_buffer.size, PROT_READ, MAP_PRIVATE, stream_fd, oa_buffer.offset);
+	igt_assert(oa_vaddr != MAP_FAILED && oa_vaddr != NULL);
+
+	munmap(oa_vaddr, oa_buffer.size);
+}
+
+static void *map_oa_buffer(uint32_t *size)
+{
+	struct drm_i915_perf_oa_buffer_info oa_buffer = { 0 };
+	void *vaddr;
+
+	do_ioctl(stream_fd, I915_PERF_IOCTL_GET_OA_BUFFER_INFO, &oa_buffer);
+
+	igt_debug("size        = %llu\n", oa_buffer.size);
+	igt_debug("offset      = %llx\n", oa_buffer.offset);
+
+	igt_assert_eq(oa_buffer.size & (oa_buffer.size - 1), 0);
+	igt_assert_eq(oa_status_reg(), 0);
+
+	vaddr = mmap(0, oa_buffer.size, PROT_READ, MAP_PRIVATE, stream_fd, oa_buffer.offset);
+	igt_assert(vaddr != MAP_FAILED && vaddr != NULL);
+
+	*size = oa_buffer.size;
+
+	return vaddr;
+}
+
+static void check_reports(void *oa_vaddr, uint32_t oa_size)
+{
+	struct oa_format format = get_oa_format(test_set->perf_oa_format);
+	size_t report_words = format.size >> 2;
+	uint32_t *reports;
+	uint32_t timer_reports = 0;
+
+	for (reports = (uint32_t *)oa_vaddr;
+	     timer_reports < 20 && reports[0] && reports[1];
+	     reports += report_words) {
+		if (!oa_report_is_periodic(oa_exp_1_millisec, reports))
+			continue;
+
+		timer_reports++;
+		if (timer_reports >= 3)
+			sanity_check_reports(reports - 2 * report_words,
+					     reports - report_words,
+					     test_set->perf_oa_format);
+	}
+
+	igt_assert(timer_reports >= 3);
+}
+
+static void check_reports_from_mapped_buffer(void)
+{
+	void *vaddr;
+	uint32_t size;
+	uint32_t period_us = oa_exponent_to_ns(oa_exp_1_millisec) / 1000;
+
+	vaddr = map_oa_buffer(&size);
+
+	/* wait for approx 100 reports */
+	usleep(100 * period_us);
+	check_reports(vaddr, size);
+
+	munmap(vaddr, size);
+}
+
+static void unprivileged_try_to_map_oa_buffer(void)
+{
+	struct drm_i915_perf_oa_buffer_info oa_buffer = { 0 };
+	void *oa_vaddr;
+
+	do_ioctl_err(stream_fd, I915_PERF_IOCTL_GET_OA_BUFFER_INFO,
+		     &oa_buffer, EACCES);
+
+	oa_vaddr = mmap(0, 4096, PROT_READ, MAP_PRIVATE, stream_fd, 4096);
+	igt_assert(oa_vaddr == MAP_FAILED);
+	igt_assert_eq(errno, EACCES);
+}
+
+static void unprivileged_map_oa_buffer(void)
+{
+	igt_fork(child, 1) {
+		igt_drop_root();
+		unprivileged_try_to_map_oa_buffer();
+	}
+	igt_waitchildren();
+}
+
+static void map_oa_buffer_unprivilege_access(void)
+{
+	void *vaddr;
+	uint32_t size;
+
+	vaddr = map_oa_buffer(&size);
+
+	igt_fork(child, 1) {
+		igt_drop_root();
+		try_invalid_access(vaddr);
+	}
+	igt_waitchildren();
+
+	munmap(vaddr, size);
+}
+
+static void map_oa_buffer_forked_access(void)
+{
+	void *vaddr;
+	uint32_t size;
+
+	vaddr = map_oa_buffer(&size);
+
+	igt_fork(child, 1) {
+		try_invalid_access(vaddr);
+	}
+	igt_waitchildren();
+
+	munmap(vaddr, size);
+}
+
+static void test_mapped_oa_buffer(void (*test_with_fd_open)(void))
+{
+	uint64_t properties[] = {
+		DRM_I915_PERF_PROP_SAMPLE_OA, true,
+		DRM_I915_PERF_PROP_OA_METRICS_SET, test_set->perf_oa_metrics_set,
+		DRM_I915_PERF_PROP_OA_FORMAT, test_set->perf_oa_format,
+		DRM_I915_PERF_PROP_OA_EXPONENT, oa_exp_1_millisec,
+
+	};
+	struct drm_i915_perf_open_param param = {
+		.flags = I915_PERF_FLAG_FD_CLOEXEC,
+		.num_properties = sizeof(properties) / 16,
+		.properties_ptr = to_user_pointer(properties),
+	};
+
+	stream_fd = __perf_open(drm_fd, &param, false);
+
+	igt_assert(test_with_fd_open);
+	test_with_fd_open();
+
+	__perf_close(stream_fd);
+}
+
+static void closed_fd_and_unmapped_access(void)
+{
+	uint64_t properties[] = {
+		DRM_I915_PERF_PROP_SAMPLE_OA, true,
+		DRM_I915_PERF_PROP_OA_METRICS_SET, test_set->perf_oa_metrics_set,
+		DRM_I915_PERF_PROP_OA_FORMAT, test_set->perf_oa_format,
+		DRM_I915_PERF_PROP_OA_EXPONENT, oa_exp_1_millisec,
+
+	};
+	struct drm_i915_perf_open_param param = {
+		.flags = I915_PERF_FLAG_FD_CLOEXEC,
+		.num_properties = sizeof(properties) / 16,
+		.properties_ptr = to_user_pointer(properties),
+	};
+	void *vaddr;
+	uint32_t size;
+	uint32_t period_us = oa_exponent_to_ns(oa_exp_1_millisec) / 1000;
+
+	stream_fd = __perf_open(drm_fd, &param, false);
+	vaddr = map_oa_buffer(&size);
+
+	usleep(100 * period_us);
+	check_reports(vaddr, size);
+
+	munmap(vaddr, size);
+	__perf_close(stream_fd);
+
+	try_invalid_access(vaddr);
+}
+
 static unsigned
 read_i915_module_ref(void)
 {
@@ -5506,6 +5763,36 @@ igt_main
 			test_triggered_oa_reports(1);
 	}
 
+	igt_subtest_group {
+		igt_fixture {
+			igt_require(i915_perf_revision(drm_fd) >= 8);
+		}
+
+		igt_describe("Verify mapping of oa buffer");
+		igt_subtest("map-oa-buffer")
+			test_mapped_oa_buffer(check_reports_from_mapped_buffer);
+
+		igt_describe("Verify invalid mappings of oa buffer");
+		igt_subtest("invalid-map-oa-buffer")
+			test_mapped_oa_buffer(invalid_param_map_oa_buffer);
+
+		igt_describe("Verify if non-privileged user can map oa buffer");
+		igt_subtest("non-privileged-map-oa-buffer")
+			test_mapped_oa_buffer(unprivileged_map_oa_buffer);
+
+		igt_describe("Verify if non-privileged user can map oa buffer");
+		igt_subtest("non-privileged-access-vaddr")
+			test_mapped_oa_buffer(map_oa_buffer_unprivilege_access);
+
+		igt_describe("Verify that forked access to mapped buffer fails");
+		igt_subtest("privileged-forked-access-vaddr")
+			test_mapped_oa_buffer(map_oa_buffer_forked_access);
+
+		igt_describe("Unmap buffer, close fd and try to access");
+		igt_subtest("closed-fd-and-unmapped-access")
+			closed_fd_and_unmapped_access();
+	}
+
 	igt_fixture {
 		/* leave sysctl options in their default state... */
 		write_u64_file("/proc/sys/dev/i915/oa_max_sample_rate", 100000);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] [PATCH 3/5] lib/i915/perf: Add new record for mmaped OA buffer
  2021-08-30 19:33 [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports Umesh Nerlige Ramappa
  2021-08-30 19:33 ` [igt-dev] [PATCH 2/5] i915/perf: Add tests for mapped OA buffer Umesh Nerlige Ramappa
@ 2021-08-30 19:33 ` Umesh Nerlige Ramappa
  2021-08-30 19:33 ` [igt-dev] [PATCH 4/5] tools/i915-perf: Add mmapped OA buffer support to i915-perf-recorder Umesh Nerlige Ramappa
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Umesh Nerlige Ramappa @ 2021-08-30 19:33 UTC (permalink / raw)
  To: igt-dev, Ashutosh Dixit; +Cc: Lionel G Landwerlin

DRM_I915_PERF_RECORD_SAMPLE header is added by i915 when user issues a
read to read the counter reports from the OA buffer. When user mmaps the
OA buffer, user has a view into the raw reports without this header.

Introduce INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE in the perf library to
track reports from an mmapped OA buffer.

While each DRM_I915_PERF_RECORD_SAMPLE record corresponds to a single OA
report, INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE corresponds to multiple
OA reports.

By design, these 2 record types cannot be mixed. The i915-perf-recorder
chooses to use mmaped OA buffer using the -M option. Once -M is chosen,
all samples are INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE.

The way timeline events are created and displayed in GPUvis remains
the same, the only change is that the source of these events now is
multiple INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE records.

Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
---
 lib/i915/perf.c                    |  7 ++-
 lib/i915/perf.h                    |  4 +-
 lib/i915/perf_data.h               |  3 +
 lib/i915/perf_data_reader.c        | 95 +++++++++++++++++++++++++++++-
 lib/i915/perf_data_reader.h        |  2 +
 tools/i915-perf/i915_perf_reader.c |  3 +-
 6 files changed, 106 insertions(+), 8 deletions(-)

diff --git a/lib/i915/perf.c b/lib/i915/perf.c
index 9cfa3bca..3ace687c 100644
--- a/lib/i915/perf.c
+++ b/lib/i915/perf.c
@@ -626,10 +626,11 @@ accumulate_uint40(int a_index,
 void intel_perf_accumulate_reports(struct intel_perf_accumulator *acc,
 				   int oa_format,
 				   const struct drm_i915_perf_record_header *record0,
-				   const struct drm_i915_perf_record_header *record1)
+				   const struct drm_i915_perf_record_header *record1,
+				   uint32_t offset0, uint32_t offset1)
 {
-	const uint32_t *start = (const uint32_t *)(record0 + 1);
-	const uint32_t *end = (const uint32_t *)(record1 + 1);
+	const uint32_t *start = (const uint32_t *)(record0 + 1) + (offset0 / 4);
+	const uint32_t *end = (const uint32_t *)(record1 + 1) + (offset1 / 4);
 	uint64_t *deltas = acc->deltas;
 	int idx = 0;
 	int i;
diff --git a/lib/i915/perf.h b/lib/i915/perf.h
index d2429c47..7706eb43 100644
--- a/lib/i915/perf.h
+++ b/lib/i915/perf.h
@@ -238,7 +238,9 @@ void intel_perf_load_perf_configs(struct intel_perf *perf, int drm_fd);
 void intel_perf_accumulate_reports(struct intel_perf_accumulator *acc,
 				   int oa_format,
 				   const struct drm_i915_perf_record_header *record0,
-				   const struct drm_i915_perf_record_header *record1);
+				   const struct drm_i915_perf_record_header *record1,
+				   uint32_t report_start_offset,
+				   uint32_t report_end_offset);
 
 #ifdef __cplusplus
 };
diff --git a/lib/i915/perf_data.h b/lib/i915/perf_data.h
index fb3556f6..a730a0b4 100644
--- a/lib/i915/perf_data.h
+++ b/lib/i915/perf_data.h
@@ -52,6 +52,9 @@ enum intel_perf_record_type {
 
 	/* intel_perf_record_timestamp_correlation */
 	INTEL_PERF_RECORD_TYPE_TIMESTAMP_CORRELATION,
+
+	/* intel_perf_record_timestamp_correlation */
+	INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE,
 };
 
 /* This structure cannot ever change. */
diff --git a/lib/i915/perf_data_reader.c b/lib/i915/perf_data_reader.c
index e69189ac..ad0b2daf 100644
--- a/lib/i915/perf_data_reader.c
+++ b/lib/i915/perf_data_reader.c
@@ -131,6 +131,7 @@ parse_data(struct intel_perf_data_reader *reader)
 
 		switch (header->type) {
 		case DRM_I915_PERF_RECORD_SAMPLE:
+		case INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE:
 			append_record(reader, header);
 			break;
 
@@ -254,6 +255,7 @@ static void
 append_timeline_event(struct intel_perf_data_reader *reader,
 		      uint64_t ts_start, uint64_t ts_end,
 		      uint32_t record_start, uint32_t record_end,
+		      uint32_t start_offset, uint32_t end_offset,
 		      uint32_t hw_id)
 {
 	if (reader->n_timelines >= reader->n_allocated_timelines) {
@@ -274,12 +276,81 @@ append_timeline_event(struct intel_perf_data_reader *reader,
 		correlate_gpu_timestamp(reader, ts_end);
 	reader->timelines[reader->n_timelines].record_start = record_start;
 	reader->timelines[reader->n_timelines].record_end = record_end;
+	reader->timelines[reader->n_timelines].report_start_offset = start_offset;
+	reader->timelines[reader->n_timelines].report_end_offset = end_offset;
 	reader->timelines[reader->n_timelines].hw_id = hw_id;
 	reader->n_timelines++;
 }
 
+struct perf_record_report {
+	uint32_t record_idx;
+	uint32_t report_offset;
+	uint32_t ctx_id;
+	uint64_t gpu_ts;
+};
+
 static void
-generate_cpu_events(struct intel_perf_data_reader *reader)
+__init_perf_record_report(struct intel_perf_data_reader *reader,
+			  struct perf_record_report *prr)
+{
+	const struct drm_i915_perf_record_header *record;
+	const uint8_t *report;
+
+	record = reader->records[prr->record_idx];
+	report = (const uint8_t *)(record + 1) + prr->report_offset;
+	prr->ctx_id = oa_report_ctx_id(&reader->devinfo, report);
+	prr->gpu_ts = oa_report_timestamp(report);
+}
+
+static bool
+__context_switched(struct intel_perf_data_reader *reader,
+		   struct perf_record_report *prev,
+		   struct perf_record_report *curr)
+{
+	__init_perf_record_report(reader, prev);
+	__init_perf_record_report(reader, curr);
+
+	return (prev->ctx_id != curr->ctx_id);
+}
+
+static void
+append_timeline(struct intel_perf_data_reader *reader,
+		struct perf_record_report *prev,
+		struct perf_record_report *curr)
+{
+	append_timeline_event(reader, prev->gpu_ts, curr->gpu_ts,
+			prev->record_idx, curr->record_idx,
+			prev->report_offset, curr->report_offset,
+			prev->ctx_id);
+}
+
+static void
+generate_cpu_events_multi_sample(struct intel_perf_data_reader *reader)
+{
+	uint32_t report_size = reader->metric_set->perf_raw_size;
+	struct perf_record_report prev = {0}, curr = {0};
+	int i;
+
+	for (i = 0; i < reader->n_records; i++) {
+		uint32_t length = reader->records[i]->size -
+				  sizeof(*(reader->records[i]));
+
+		curr.record_idx = i;
+		for (curr.report_offset = 0;
+		     curr.report_offset < length;
+		     curr.report_offset += report_size)
+			if (__context_switched(reader, &prev, &curr)) {
+				append_timeline(reader, &prev, &curr);
+				prev = curr;
+			}
+	}
+
+	if (!memcmp(&prev, &curr, sizeof(prev)))
+		append_timeline(reader, &prev, &curr);
+}
+
+static void
+generate_cpu_events_oa_sample(struct intel_perf_data_reader *reader)
 {
 	uint32_t last_header_idx = 0;
 	const struct drm_i915_perf_record_header *last_header = reader->records[0],
@@ -303,14 +374,32 @@ generate_cpu_events(struct intel_perf_data_reader *reader)
 		if (last_ctx_id == current_ctx_id)
 			continue;
 
-		append_timeline_event(reader, gpu_ts_start, gpu_ts_end, last_header_idx, i, last_ctx_id);
+		append_timeline_event(reader, gpu_ts_start, gpu_ts_end,
+				      last_header_idx, i,
+				      0, 0,
+				      last_ctx_id);
 
 		last_header = current_header;
 		last_header_idx = i;
 	}
 
 	if (last_header != current_header)
-		append_timeline_event(reader, gpu_ts_start, gpu_ts_end, last_header_idx, reader->n_records - 1, last_ctx_id);
+		append_timeline_event(reader, gpu_ts_start, gpu_ts_end,
+				      last_header_idx, reader->n_records - 1,
+				      0, 0,
+				      last_ctx_id);
+}
+
+static void
+generate_cpu_events(struct intel_perf_data_reader *reader)
+{
+	const struct drm_i915_perf_record_header *hdr = reader->records[0];
+
+	if (hdr->type == DRM_I915_PERF_RECORD_SAMPLE)
+		generate_cpu_events_oa_sample(reader);
+
+	if (hdr->type == INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE)
+		generate_cpu_events_multi_sample(reader);
 }
 
 static void
diff --git a/lib/i915/perf_data_reader.h b/lib/i915/perf_data_reader.h
index f625f12d..a9f14a1d 100644
--- a/lib/i915/perf_data_reader.h
+++ b/lib/i915/perf_data_reader.h
@@ -44,6 +44,8 @@ struct intel_perf_timeline_item {
 	/* Offsets into intel_perf_data_reader.records */
 	uint32_t record_start;
 	uint32_t record_end;
+	uint32_t report_start_offset;
+	uint32_t report_end_offset;
 
 	uint32_t hw_id;
 
diff --git a/tools/i915-perf/i915_perf_reader.c b/tools/i915-perf/i915_perf_reader.c
index e51f5a5d..12638685 100644
--- a/tools/i915-perf/i915_perf_reader.c
+++ b/tools/i915-perf/i915_perf_reader.c
@@ -252,7 +252,8 @@ main(int argc, char *argv[])
 			item->hw_id, item->hw_id == 0xffffffff ? "(idle)" : "");
 
 		intel_perf_accumulate_reports(&accu, reader.metric_set->perf_oa_format,
-					      i915_report0, i915_report1);
+					      i915_report0, i915_report1,
+					      item->report_start_offset, item->report_end_offset);
 
 		for (uint32_t c = 0; c < n_counters; c++) {
 			struct intel_perf_logical_counter *counter = counters[c];
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] [PATCH 4/5] tools/i915-perf: Add mmapped OA buffer support to i915-perf-recorder
  2021-08-30 19:33 [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports Umesh Nerlige Ramappa
  2021-08-30 19:33 ` [igt-dev] [PATCH 2/5] i915/perf: Add tests for mapped OA buffer Umesh Nerlige Ramappa
  2021-08-30 19:33 ` [igt-dev] [PATCH 3/5] lib/i915/perf: Add new record for mmaped " Umesh Nerlige Ramappa
@ 2021-08-30 19:33 ` Umesh Nerlige Ramappa
  2021-08-30 19:33 ` [igt-dev] [PATCH 5/5] tools/i915-perf: Add a command to trigger a report in OA buffer Umesh Nerlige Ramappa
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Umesh Nerlige Ramappa @ 2021-08-30 19:33 UTC (permalink / raw)
  To: igt-dev, Ashutosh Dixit; +Cc: Lionel G Landwerlin

Currently report from OA buffer are read from the perf_fd. The kernel
patches enable mmaping the OA buffer into user space to allow for faster
report queries across different platforms and engines.

Enable OA buffer to be mmaped by the recorder tool based on command line
option -M.

Example:
i915-perf-recorder -m RenderBasic -s 8000 -k "mono" -M

The recorder processes the mmaped OA buffer by periodically reading the
OA TAIL PTR register from a batch and determining the number of reports
available. These reports are then logged in the circular-buffer as
INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE records. In this implementation
the periodicity of checking the TAIL is the same as writing correlation
timestamps (1 sec).

v2: Avoid unnecessarily draining the OA buffer (Ashutosh)
v3: Use igt lib helpers (Ashutosh)

Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
---
 tools/i915-perf/i915_perf_recorder.c | 375 ++++++++++++++++++++++++++-
 tools/i915-perf/meson.build          |   6 +-
 2 files changed, 366 insertions(+), 15 deletions(-)

diff --git a/tools/i915-perf/i915_perf_recorder.c b/tools/i915-perf/i915_perf_recorder.c
index 00195290..7481f33c 100644
--- a/tools/i915-perf/i915_perf_recorder.c
+++ b/tools/i915-perf/i915_perf_recorder.c
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 #include <sys/time.h>
@@ -44,11 +45,16 @@
 #include <i915_drm.h>
 
 #include "igt_core.h"
+#include "intel_allocator.h"
 #include "intel_chipset.h"
+#include "intel_ctx.h"
+#include "i915/gem_create.h"
+#include "i915/gem_mman.h"
 #include "i915/perf.h"
 #include "i915/perf_data.h"
 
 #include "i915_perf_recorder_commands.h"
+#include "ioctl_wrappers.h"
 
 #define ALIGN(v, a) (((v) + (a)-1) & ~((a)-1))
 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))
@@ -331,6 +337,18 @@ get_device_timestamp_frequency(const struct intel_device_info *devinfo, int drm_
 	return 12000000;
 }
 
+struct bb_context {
+	struct drm_i915_gem_relocation_entry reloc[2];
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_execbuffer2 execbuf;
+	uint32_t *batch;
+	uint32_t *dest;
+	uint32_t offset;
+	uint32_t reloc_idx;
+	uint64_t ahnd;
+	const intel_ctx_t *ctx;
+};
+
 struct recording_context {
 	int drm_fd;
 	int perf_fd;
@@ -355,6 +373,19 @@ struct recording_context {
 	int command_fifo_fd;
 
 	uint64_t poll_period;
+	double perf_period;
+
+	uint32_t max_record_length;
+
+	uint8_t *oa_buffer_vaddr;
+	uint32_t oa_buffer_size;
+	uint32_t tail_offset;
+	uint32_t head_offset;
+	uint32_t oa_status_reg;
+	uint32_t oa_buffer_reg;
+	uint32_t oa_tail_reg;
+
+	struct bb_context bb;
 };
 
 static int
@@ -527,6 +558,270 @@ write_i915_perf_data(FILE *output, int perf_fd)
 	return true;
 }
 
+#define BATCH_SIZE 4096
+#define DEST_SIZE 4096
+
+#define _MI_INSTR(opcode, flags)	(((opcode) << 23) | (flags))
+#define MI_STORE_REGISTER_MEM      	_MI_INSTR(0x24, 1)
+#define MI_STORE_REGISTER_MEM_GEN8 	_MI_INSTR(0x24, 2)
+#define MI_BATCH_BUFFER_END		(0xA << 23)
+
+static void
+bb_emit_srm(struct bb_context *bb, uint32_t reg, uint32_t devid)
+{
+	bool gen8_plus = devid >= 8;
+	uint64_t mem;
+
+	assert(bb->reloc_idx < ARRAY_SIZE(bb->reloc));
+	assert(bb->offset < BATCH_SIZE);
+
+	bb->batch[bb->offset++] = gen8_plus ? MI_STORE_REGISTER_MEM_GEN8 :
+					      MI_STORE_REGISTER_MEM;
+	bb->batch[bb->offset++] = reg;
+
+	bb->reloc[bb->reloc_idx].target_handle = bb->obj[0].handle;
+	bb->reloc[bb->reloc_idx].presumed_offset = bb->obj[0].offset;
+	bb->reloc[bb->reloc_idx].offset = bb->offset * sizeof(uint32_t);
+	bb->reloc[bb->reloc_idx].delta = bb->reloc_idx * sizeof(uint32_t);
+	bb->reloc[bb->reloc_idx].read_domains = I915_GEM_DOMAIN_RENDER;
+	bb->reloc[bb->reloc_idx].write_domain = I915_GEM_DOMAIN_RENDER;
+
+	mem = bb->obj[0].offset + bb->reloc[bb->reloc_idx].delta;
+	bb->batch[bb->offset++] = mem;
+	if (gen8_plus)
+		bb->batch[bb->offset++] = mem >> 32;
+
+	bb->reloc_idx++;
+}
+
+static void
+bb_emit_bbe(struct bb_context *bb)
+{
+	bb->batch[bb->offset++] = MI_BATCH_BUFFER_END;
+}
+
+static void
+bb_exec(int fd, struct bb_context *bb)
+{
+	struct drm_i915_gem_execbuffer2 *execbuf = &bb->execbuf;
+
+	memset(execbuf, 0, sizeof(*execbuf));
+	if (bb->reloc_idx) {
+		bb->obj[1].relocation_count = !bb->ahnd ? bb->reloc_idx : 0;
+		execbuf->buffers_ptr = to_user_pointer(bb->obj);
+		execbuf->buffer_count = 2;
+	} else {
+		bb->obj[1].relocation_count = 0;
+		execbuf->buffers_ptr = to_user_pointer(&bb->obj[1]);
+		execbuf->buffer_count = 1;
+	}
+	execbuf->rsvd1 = bb->ctx->id;
+	gem_execbuf(fd, execbuf);
+
+	bb->reloc_idx = 0;
+	bb->offset = 0;
+}
+
+static void
+bb_ctx_fini(struct recording_context *ctx)
+{
+	struct bb_context *bb = &ctx->bb;
+
+	intel_ctx_destroy(ctx->drm_fd, bb->ctx);
+
+	if (bb->batch)
+		munmap(bb->batch, BATCH_SIZE);
+
+	if (bb->obj[1].handle)
+		gem_close(ctx->drm_fd, bb->obj[1].handle);
+
+	if (bb->obj[0].handle)
+		gem_close(ctx->drm_fd, bb->obj[0].handle);
+
+	put_ahnd(bb->ahnd);
+}
+
+static int
+bb_ctx_init(struct recording_context *ctx)
+{
+	struct bb_context *bb = &ctx->bb;
+	struct drm_i915_gem_exec_object2 *obj = bb->obj;
+	int fd = ctx->drm_fd;
+
+	memset(bb, 0, sizeof(struct bb_context));
+
+	bb->ctx = intel_ctx_create(fd, NULL);
+	bb->ahnd = get_reloc_ahnd(fd, bb->ctx->id);
+
+	obj[0].handle = gem_create(fd, DEST_SIZE);
+	obj[1].handle = gem_create(fd, BATCH_SIZE);
+	obj[1].relocs_ptr = to_user_pointer(bb->reloc);
+	if (bb->ahnd) {
+		obj[0].offset = get_offset(bb->ahnd, obj[0].handle, DEST_SIZE, 0);
+		obj[0].flags |= EXEC_OBJECT_PINNED | EXEC_OBJECT_WRITE;
+		obj[1].offset = get_offset(bb->ahnd, obj[1].handle, BATCH_SIZE, 0);
+		obj[1].flags |= EXEC_OBJECT_PINNED;
+	}
+
+	bb->batch = gem_mmap__cpu_coherent(fd, obj[1].handle, 0, BATCH_SIZE, PROT_WRITE);
+	if (!bb->batch)
+		goto err;
+
+	gem_set_domain(fd, obj[1].handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+
+	return 0;
+err:
+	bb_ctx_fini(ctx);
+	return -1;
+}
+
+#define OA_PTR_MASK 0xffffffc0
+
+#define GEN8_OABUFFER	0x2b14
+#define GEN8_OATAILPTR	0x2B10
+#define GEN8_OASTATUS   0x2b08
+#define  GEN8_OASTATUS_OABUFFER_OVERFLOW    (1 << 1)
+#define  GEN8_OASTATUS_REPORT_LOST	    (1 << 0)
+
+#define GEN12_OAG_OABUFFER   0xdb08
+#define GEN12_OAG_OATAILPTR  0xdb04
+#define GEN12_OAG_OASTATUS   0xdafc
+
+static void
+init_oa_regs(struct recording_context *ctx)
+{
+	if (ctx->devinfo->graphics_ver >= 12) {
+		ctx->oa_status_reg = GEN12_OAG_OASTATUS;
+		ctx->oa_buffer_reg = GEN12_OAG_OABUFFER;
+		ctx->oa_tail_reg = GEN12_OAG_OATAILPTR;
+	} else if (ctx->devinfo->graphics_ver >= 9) {
+		ctx->oa_status_reg = GEN8_OASTATUS;
+		ctx->oa_buffer_reg = GEN8_OABUFFER;
+		ctx->oa_tail_reg = GEN8_OATAILPTR;
+	}
+}
+
+static void
+__read_oa_reg(struct recording_context *ctx, uint32_t reg, uint32_t *val)
+{
+	struct bb_context *bb = &ctx->bb;
+	int fd = ctx->drm_fd;
+
+	bb_emit_srm(bb, reg, ctx->perf->devinfo.devid);
+	bb_emit_bbe(bb);
+	bb_exec(fd, bb);
+	bb->dest = gem_mmap__cpu_coherent(fd, bb->obj[0].handle, 0, DEST_SIZE, PROT_READ);
+	assert(bb->dest);
+	gem_set_domain(fd, bb->obj[0].handle, I915_GEM_DOMAIN_CPU, 0);
+
+	*val = bb->dest[0];
+	munmap(bb->dest, DEST_SIZE);
+}
+
+static bool
+__process_oa_status(struct recording_context *ctx)
+{
+	struct drm_i915_perf_record_header header = {
+		.type = 0,
+		.pad = 0,
+		.size = sizeof(header)
+	};
+	uint32_t status;
+
+	__read_oa_reg(ctx, ctx->oa_status_reg, &status);
+	if (status & GEN8_OASTATUS_REPORT_LOST) {
+		header.type = DRM_I915_PERF_RECORD_OA_REPORT_LOST;
+		if (fwrite(&header, sizeof(header), 1, ctx->output_stream) != 1)
+			return false;
+	}
+
+	return true;
+}
+
+static inline uint32_t
+__data_available(uint32_t tail, uint32_t head, uint32_t size)
+{
+	return tail >= head ? tail - head : size - (head - tail);
+}
+
+static inline uint32_t
+__rewind_tail(uint32_t tail, uint32_t report_size, uint32_t oa_buffer_size)
+{
+	return tail >= report_size ?
+	       tail - report_size :
+	       oa_buffer_size - (report_size - tail);
+}
+
+static bool
+write_i915_perf_mmapped_data(struct recording_context *ctx)
+{
+	uint32_t report_size = ctx->metric_set->perf_raw_size;
+	struct drm_i915_perf_record_header header;
+	uint32_t buff, tail, data_len;
+
+	if (!__process_oa_status(ctx))
+		return false;
+
+	__read_oa_reg(ctx, ctx->oa_buffer_reg, &buff);
+	buff = buff & OA_PTR_MASK;
+
+	__read_oa_reg(ctx, ctx->oa_tail_reg, &tail);
+	tail = (tail & OA_PTR_MASK) - buff;
+
+	/*
+	 * tail increments in 64 bytes, so round up to nearest report. note that
+	 * oa buffer size may not be a power of 2 and a report may split across
+	 * the boundary of the oa buffer
+	 */
+	data_len = __data_available(tail, ctx->head_offset, ctx->oa_buffer_size);
+	assert(data_len <= ctx->oa_buffer_size);
+
+	tail -= data_len % report_size;
+	ctx->tail_offset = tail;
+
+	while (ctx->tail_offset != ctx->head_offset) {
+		const uint32_t *report32 = (uint32_t *)(ctx->oa_buffer_vaddr +
+							ctx->tail_offset);
+
+		if (report32[0] || report32[1])
+			break;
+
+		ctx->tail_offset = __rewind_tail(ctx->tail_offset, report_size,
+						 ctx->oa_buffer_size);
+	}
+
+	data_len = __data_available(ctx->tail_offset, ctx->head_offset,
+				    ctx->oa_buffer_size);
+	if (!data_len)
+		return true;
+
+	assert(data_len < ctx->oa_buffer_size);
+
+	header.type = INTEL_PERF_RECORD_TYPE_MULTIPLE_SAMPLE;
+	while (data_len > 0) {
+		uint32_t len;
+
+		len = MIN(data_len, ctx->max_record_length);
+		len = MIN(len, ctx->oa_buffer_size - ctx->head_offset);
+
+		header.size = sizeof(header) + len;
+		if (fwrite(&header, sizeof(header), 1, ctx->output_stream) != 1)
+			return false;
+
+		if (fwrite(ctx->oa_buffer_vaddr + ctx->head_offset, len, 1, ctx->output_stream) != 1)
+			return false;
+
+		data_len -= len;
+		ctx->head_offset = ctx->head_offset + len;
+
+		assert(ctx->head_offset <= ctx->oa_buffer_size);
+		if (ctx->head_offset == ctx->oa_buffer_size)
+			ctx->head_offset = 0;
+	}
+
+	return true;
+}
+
 static uint64_t timespec_diff(struct timespec *begin,
 			      struct timespec *end)
 {
@@ -667,6 +962,21 @@ read_command_file(struct recording_context *ctx)
 	}
 }
 
+static void
+mmap_oa_buffer(struct recording_context *ctx)
+{
+	struct drm_i915_perf_oa_buffer_info oa_info = {0};
+	void *vaddr;
+
+	perf_ioctl(ctx->perf_fd, I915_PERF_IOCTL_GET_OA_BUFFER_INFO, &oa_info);
+	vaddr = mmap(0, oa_info.size, PROT_READ, MAP_PRIVATE, ctx->perf_fd,
+		     oa_info.offset);
+	assert(vaddr != NULL);
+
+	ctx->oa_buffer_size = oa_info.size;
+	ctx->oa_buffer_vaddr = vaddr;
+}
+
 static void
 print_metric_sets(const struct intel_perf *perf)
 {
@@ -761,6 +1071,11 @@ teardown_recording_context(struct recording_context *ctx)
 
 	free(ctx->circular_buffer.data);
 
+	if (ctx->oa_buffer_vaddr)
+		munmap(ctx->oa_buffer_vaddr, ctx->oa_buffer_size);
+
+	bb_ctx_fini(ctx);
+
 	if (ctx->perf_fd != -1)
 		close(ctx->perf_fd);
 	if (ctx->drm_fd != -1)
@@ -781,6 +1096,7 @@ main(int argc, char *argv[])
 		{"command-fifo",         required_argument, 0, 'f'},
 		{"cpu-clock",            required_argument, 0, 'k'},
 		{"poll-period",          required_argument, 0, 'P'},
+		{"mmap-buffer",                no_argument, 0, 'M'},
 		{0, 0, 0, 0}
 	};
 	const struct {
@@ -791,7 +1107,7 @@ main(int argc, char *argv[])
 		{ CLOCK_MONOTONIC,     "mono" },
 		{ CLOCK_MONOTONIC_RAW, "mono_raw" },
 	};
-	double corr_period = 1.0, perf_period = 0.001;
+	double corr_period = 1.0;
 	const char *metric_name = NULL, *output_file = "i915_perf.record";
 	struct intel_perf_metric_set *metric_set;
 	struct intel_perf_record_timestamp_correlation initial_correlation;
@@ -799,7 +1115,7 @@ main(int argc, char *argv[])
 	uint64_t corr_period_ns, poll_time_ns;
 	uint32_t circular_size = 0;
 	int opt;
-	bool list_counters = false;
+	bool list_counters = false, mmap_buffer = false;
 	FILE *output = NULL;
 	struct recording_context ctx = {
 		.drm_fd = -1,
@@ -810,9 +1126,16 @@ main(int argc, char *argv[])
 
 		/* 5 ms poll period */
 		.poll_period = 5 * 1000 * 1000,
+		.perf_period = 0.001,
+
+		.oa_buffer_vaddr = NULL,
+		.head_offset = 0,
+		.tail_offset = 0,
+		.oa_buffer_size = 0,
 	};
 
-	while ((opt = getopt_long(argc, argv, "hc:p:m:Co:s:f:k:P:", long_options, NULL)) != -1) {
+	memset(&ctx.bb, 0, sizeof(ctx.bb));
+	while ((opt = getopt_long(argc, argv, "hc:p:m:Co:s:f:k:P:M", long_options, NULL)) != -1) {
 		switch (opt) {
 		case 'h':
 			usage(argv[0]);
@@ -821,7 +1144,7 @@ main(int argc, char *argv[])
 			corr_period = atof(optarg);
 			break;
 		case 'p':
-			perf_period = atof(optarg);
+			ctx.perf_period = atof(optarg);
 			break;
 		case 'm':
 			metric_name = optarg;
@@ -857,6 +1180,9 @@ main(int argc, char *argv[])
 		case 'P':
 			ctx.poll_period = MAX(100, atol(optarg)) * 1000;
 			break;
+		case 'M':
+			mmap_buffer = true;
+			break;
 		default:
 			fprintf(stderr, "Internal error: "
 				"unexpected getopt value: %d\n", opt);
@@ -876,6 +1202,10 @@ main(int argc, char *argv[])
 		fprintf(stderr, "No device info found.\n");
 		goto fail;
 	}
+	if (ctx.devinfo->graphics_ver < 9 && mmap_buffer) {
+		fprintf(stderr, "mmap_buffer not supported on graphics version less than 9\n");
+		goto fail;
+	}
 
 	fprintf(stdout, "Device name=%s gen=%i gt=%i id=0x%x\n",
 		ctx.devinfo->codename, ctx.devinfo->graphics_ver, ctx.devinfo->gt, ctx.devid);
@@ -926,6 +1256,11 @@ main(int argc, char *argv[])
 		goto fail;
 	}
 
+	/* header size is a uint16_t, so accomodate the header first */
+	ctx.max_record_length = 65535 - sizeof(struct drm_i915_perf_record_header);
+	/* accomodate only full report sizes */
+	ctx.max_record_length -= (ctx.max_record_length % ctx.metric_set->perf_raw_size);
+
 	intel_perf_load_perf_configs(ctx.perf, ctx.drm_fd);
 
 	ctx.timestamp_frequency = get_device_timestamp_frequency(ctx.devinfo, ctx.drm_fd);
@@ -1000,7 +1335,7 @@ main(int argc, char *argv[])
 		goto fail;
 	}
 
-	ctx.oa_exponent = oa_exponent_for_period(ctx.timestamp_frequency, perf_period);
+	ctx.oa_exponent = oa_exponent_for_period(ctx.timestamp_frequency, ctx.perf_period);
 	fprintf(stdout, "Opening perf stream with metric_id=%"PRIu64" oa_exponent=%u oa_format=%u\n",
 		ctx.metric_set->perf_oa_metrics_set, ctx.oa_exponent,
 		ctx.metric_set->perf_oa_format);
@@ -1015,16 +1350,27 @@ main(int argc, char *argv[])
 	corr_period_ns = corr_period * 1000000000ul;
 	poll_time_ns = corr_period_ns;
 
+	if (mmap_buffer) {
+		if (bb_ctx_init(&ctx)) {
+			fprintf(stderr, "Unable to initialize batch buffer %s\n", strerror(errno));
+			goto fail;
+		}
+
+		init_oa_regs(&ctx);
+		mmap_oa_buffer(&ctx);
+	}
+
 	while (!quit) {
 		struct pollfd pollfd[2] = {
-			{         ctx.perf_fd, POLLIN, 0 },
 			{ ctx.command_fifo_fd, POLLIN, 0 },
+			{ ctx.perf_fd, POLLIN, 0 },
 		};
 		uint64_t elapsed_ns;
+		nfds_t num_fds = mmap_buffer ? 1 : 2;
 		int ret;
 
 		igt_gettime(&now);
-		ret = poll(pollfd, ctx.command_fifo_fd != -1 ? 2 : 1, poll_time_ns / 1000000);
+		ret = poll(pollfd, num_fds, poll_time_ns / 1000000);
 		if (ret < 0 && errno != EINTR) {
 			fprintf(stderr, "Failed to poll i915-perf stream: %s\n",
 				strerror(errno));
@@ -1032,17 +1378,16 @@ main(int argc, char *argv[])
 		}
 
 		if (ret > 0) {
-			if (pollfd[0].revents & POLLIN) {
+			if (pollfd[0].revents & POLLIN)
+				read_command_file(&ctx);
+
+			if (num_fds > 1 && pollfd[1].revents & POLLIN) {
 				if (!write_i915_perf_data(ctx.output_stream, ctx.perf_fd)) {
 					fprintf(stderr, "Failed to write i915-perf data: %s\n",
 						strerror(errno));
 					break;
 				}
 			}
-
-			if (pollfd[1].revents & POLLIN) {
-				read_command_file(&ctx);
-			}
 		}
 
 		elapsed_ns = igt_nsec_elapsed(&now);
@@ -1054,6 +1399,12 @@ main(int argc, char *argv[])
 					strerror(errno));
 				break;
 			}
+
+			if (mmap_buffer && !write_i915_perf_mmapped_data(&ctx)) {
+				fprintf(stderr, "Failed to write i915-perf mmapped data: %s\n",
+					strerror(errno));
+				break;
+			}
 		} else {
 			poll_time_ns -= elapsed_ns;
 		}
diff --git a/tools/i915-perf/meson.build b/tools/i915-perf/meson.build
index 3fbf20a0..60abb694 100644
--- a/tools/i915-perf/meson.build
+++ b/tools/i915-perf/meson.build
@@ -5,9 +5,9 @@ executable('i915-perf-configs',
            install: true)
 
 executable('i915-perf-recorder',
-           [ 'i915_perf_recorder.c' ],
-           include_directories: inc,
-           dependencies: [lib_igt, lib_igt_i915_perf],
+           [ 'i915_perf_recorder.c', '../../lib/stubs/drm/intel_bufmgr.c' ],
+           include_directories: [ inc, include_directories('../../lib/stubs/drm') ],
+           dependencies: [ lib_igt, lib_igt_i915_perf ],
            install: true)
 
 executable('i915-perf-control',
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] [PATCH 5/5] tools/i915-perf: Add a command to trigger a report in OA buffer
  2021-08-30 19:33 [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports Umesh Nerlige Ramappa
                   ` (2 preceding siblings ...)
  2021-08-30 19:33 ` [igt-dev] [PATCH 4/5] tools/i915-perf: Add mmapped OA buffer support to i915-perf-recorder Umesh Nerlige Ramappa
@ 2021-08-30 19:33 ` Umesh Nerlige Ramappa
  2021-08-30 20:08 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [1/5] i915/perf: add tests for triggered OA reports Patchwork
  2021-08-30 21:50 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  5 siblings, 0 replies; 8+ messages in thread
From: Umesh Nerlige Ramappa @ 2021-08-30 19:33 UTC (permalink / raw)
  To: igt-dev, Ashutosh Dixit; +Cc: Lionel G Landwerlin

Current OA captures used by GPUvis show timelines corresponding to
individual contexts as parsed from the OA buffer.

Add support to query OA report using the command line interface -
i915_perf_control. The query will take a snapshot of the counters and
store it in the OA buffer. The snapshots can be viewed as a separate
trigger event timeline in GPUvis. The command line allows passing a
distinct 32 bit trigger value that can be used to identify the triggers
in the visulaization.

The idea is to show counter deltas between these on-demand trigger
events. More fine grained triggerring can be achieved by adding the
trigger commands into a batch.

Example: i915_perf_control -t <distinct_32bit_value>

Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
---
 tools/i915-perf/i915_perf_control.c           |  43 ++++++-
 tools/i915-perf/i915_perf_recorder.c          | 109 ++++++++++++++++--
 tools/i915-perf/i915_perf_recorder_commands.h |   1 +
 3 files changed, 142 insertions(+), 11 deletions(-)

diff --git a/tools/i915-perf/i915_perf_control.c b/tools/i915-perf/i915_perf_control.c
index be5996c0..509549d8 100644
--- a/tools/i915-perf/i915_perf_control.c
+++ b/tools/i915-perf/i915_perf_control.c
@@ -26,9 +26,19 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <limits.h>
 
 #include "i915_perf_recorder_commands.h"
 
+static bool
+__valid_trigger_value(const char *value)
+{
+	char *endptr = '\0';
+
+	return strtoul(value, &endptr, 0) != ULONG_MAX &&
+	       *endptr == '\0';
+}
+
 static void
 usage(const char *name)
 {
@@ -37,7 +47,9 @@ usage(const char *name)
 		"\n"
 		"     --help,               -h         Print this screen\n"
 		"     --command-fifo,       -f <path>  Path to a command fifo\n"
-		"     --dump,               -d <path>  Write a content of circular buffer to path\n",
+		"     --dump,               -d <path>  Write a content of circular buffer to path\n"
+		"     --quit,               -q         Quit capturing reports fromm perf recorder\n"
+		"     --trigger,            -t <value> Trigger a report into OA buffer with this 32 bit unsigned value\n",
 		name);
 }
 
@@ -49,14 +61,16 @@ main(int argc, char *argv[])
 		{"dump",                 required_argument, 0, 'd'},
 		{"command-fifo",         required_argument, 0, 'f'},
 		{"quit",                       no_argument, 0, 'q'},
+		{"trigger",              required_argument, 0, 't'},
 		{0, 0, 0, 0}
 	};
 	const char *command_fifo = I915_PERF_RECORD_FIFO_PATH, *dump_file = NULL;
 	FILE *command_fifo_file;
 	int opt;
-	bool quit = false;
+	bool triggered = false, quit = false;
+	char *trigger_value;
 
-	while ((opt = getopt_long(argc, argv, "hd:f:q", long_options, NULL)) != -1) {
+	while ((opt = getopt_long(argc, argv, "hd:f:qt:", long_options, NULL)) != -1) {
 		switch (opt) {
 		case 'h':
 			usage(argv[0]);
@@ -70,6 +84,14 @@ main(int argc, char *argv[])
 		case 'q':
 			quit = true;
 			break;
+		case 't':
+			if (!__valid_trigger_value(optarg)) {
+				fprintf(stderr, "Invalid trigger value: %s\n", optarg);
+				return EXIT_FAILURE;
+			}
+			trigger_value = optarg;
+			triggered = true;
+			break;
 		default:
 			fprintf(stderr, "Internal error: "
 				"unexpected getopt value: %d\n", opt);
@@ -118,6 +140,21 @@ main(int argc, char *argv[])
 		}
 	}
 
+	if (triggered) {
+		uint32_t total_len =
+			sizeof(struct recorder_command_base) + strlen(trigger_value) + 1;
+		struct {
+			struct recorder_command_base base;
+			uint8_t trigger[];
+		} *data = malloc(total_len);
+
+		data->base.command = RECORDER_COMMAND_TRIGGER;
+		data->base.size = total_len;
+		snprintf((char *) data->trigger, strlen(trigger_value) + 1, "%s", trigger_value);
+
+		fwrite(data, total_len, 1, command_fifo_file);
+	}
+
 	if (quit) {
 		struct recorder_command_base base = {
 			.command = RECORDER_COMMAND_QUIT,
diff --git a/tools/i915-perf/i915_perf_recorder.c b/tools/i915-perf/i915_perf_recorder.c
index 7481f33c..12908ae7 100644
--- a/tools/i915-perf/i915_perf_recorder.c
+++ b/tools/i915-perf/i915_perf_recorder.c
@@ -26,6 +26,7 @@
 #include <fcntl.h>
 #include <getopt.h>
 #include <inttypes.h>
+#include <limits.h>
 #include <poll.h>
 #include <signal.h>
 #include <stdbool.h>
@@ -384,6 +385,8 @@ struct recording_context {
 	uint32_t oa_status_reg;
 	uint32_t oa_buffer_reg;
 	uint32_t oa_tail_reg;
+	uint32_t oa_trigger_reg;
+	uint32_t oa_marker_reg;
 
 	struct bb_context bb;
 };
@@ -564,8 +567,21 @@ write_i915_perf_data(FILE *output, int perf_fd)
 #define _MI_INSTR(opcode, flags)	(((opcode) << 23) | (flags))
 #define MI_STORE_REGISTER_MEM      	_MI_INSTR(0x24, 1)
 #define MI_STORE_REGISTER_MEM_GEN8 	_MI_INSTR(0x24, 2)
+#define MI_LOAD_REGISTER_IMM		((0x22 << 23) | 1)
+#define MI_NOOP				0x00
 #define MI_BATCH_BUFFER_END		(0xA << 23)
 
+static void
+bb_emit_lri(struct bb_context *bb, uint32_t reg, uint32_t val)
+{
+	assert(bb->offset < BATCH_SIZE);
+
+	bb->batch[bb->offset++] = MI_LOAD_REGISTER_IMM;
+	bb->batch[bb->offset++] = reg;
+	bb->batch[bb->offset++] = val;
+	bb->batch[bb->offset++] = MI_NOOP;
+}
+
 static void
 bb_emit_srm(struct bb_context *bb, uint32_t reg, uint32_t devid)
 {
@@ -687,6 +703,18 @@ err:
 #define GEN12_OAG_OATAILPTR  0xdb04
 #define GEN12_OAG_OASTATUS   0xdafc
 
+#define OAREPORTTRIG2 (0x2744)
+#define   OAREPORTTRIG2_INVERT_C_1  (1 << 21)
+#define   OAREPORTTRIG2_INVERT_D_0  (1 << 22)
+#define   OAREPORTTRIG2_REPORT_TRIGGER_ENABLE (1 << 31)
+#define OAREPORTTRIG6 (0x2754)
+#define OA_PERF_COUNTER_A(idx) (0x2800 + 8 * (idx))
+
+#define GEN12_OAREPORTTRIG2 (0xd924)
+#define GEN12_OAREPORTTRIG6 (0xd934)
+#define GEN12_OAG_PERF_COUNTER_A(idx) (0xD980 + 8 * (idx))
+
+
 static void
 init_oa_regs(struct recording_context *ctx)
 {
@@ -694,10 +722,14 @@ init_oa_regs(struct recording_context *ctx)
 		ctx->oa_status_reg = GEN12_OAG_OASTATUS;
 		ctx->oa_buffer_reg = GEN12_OAG_OABUFFER;
 		ctx->oa_tail_reg = GEN12_OAG_OATAILPTR;
+		ctx->oa_trigger_reg = GEN12_OAREPORTTRIG2;
+		ctx->oa_marker_reg = GEN12_OAG_PERF_COUNTER_A(18);
 	} else if (ctx->devinfo->graphics_ver >= 9) {
 		ctx->oa_status_reg = GEN8_OASTATUS;
 		ctx->oa_buffer_reg = GEN8_OABUFFER;
 		ctx->oa_tail_reg = GEN8_OATAILPTR;
+		ctx->oa_trigger_reg = OAREPORTTRIG2;
+		ctx->oa_marker_reg = OA_PERF_COUNTER_A(18);
 	}
 }
 
@@ -718,6 +750,22 @@ __read_oa_reg(struct recording_context *ctx, uint32_t reg, uint32_t *val)
 	munmap(bb->dest, DEST_SIZE);
 }
 
+static void
+oa_trigger_report(struct recording_context *ctx, uint32_t reg,
+		  uint32_t trigger_marker)
+{
+	bb_emit_lri(&ctx->bb, ctx->oa_marker_reg, trigger_marker);
+	bb_emit_lri(&ctx->bb, reg,
+		    OAREPORTTRIG2_INVERT_C_1 |
+		    OAREPORTTRIG2_REPORT_TRIGGER_ENABLE);
+	bb_emit_lri(&ctx->bb, reg,
+		    OAREPORTTRIG2_INVERT_C_1 |
+		    OAREPORTTRIG2_INVERT_D_0 |
+		    OAREPORTTRIG2_REPORT_TRIGGER_ENABLE);
+	bb_emit_bbe(&ctx->bb);
+	bb_exec(ctx->drm_fd, &ctx->bb);
+}
+
 static bool
 __process_oa_status(struct recording_context *ctx)
 {
@@ -903,6 +951,35 @@ write_correlation_timestamps(FILE *output, int drm_fd)
 	return write_saved_correlation_timestamps(output, &corr);
 }
 
+static bool
+__valid_trigger_value(const char *str, uint32_t *trigger_value)
+{
+	char *endptr = '\0';
+	uint32_t value = strtoul(str, &endptr, 0);
+
+	if (value != ULONG_MAX && *endptr == '\0') {
+		*trigger_value = value;
+		return true;
+	}
+
+	return false;
+}
+
+static int read_command_data(int fd, uint8_t *buf, uint32_t len)
+{
+	uint32_t offset = 0;
+	ssize_t ret;
+
+	while (offset < len &&
+	       ((ret = read(fd, (void *)(buf + offset), len - offset)) > 0
+		|| errno == EAGAIN)) {
+		if (ret > 0)
+			offset += ret;
+	}
+
+	return ret;
+}
+
 static void
 read_command_file(struct recording_context *ctx)
 {
@@ -914,17 +991,12 @@ read_command_file(struct recording_context *ctx)
 
 	switch (header.command) {
 	case RECORDER_COMMAND_DUMP: {
-		uint32_t len = header.size - sizeof(header), offset = 0;
+		uint32_t len = header.size - sizeof(header);
 		uint8_t *dump = malloc(len);
 		FILE *file;
 
-		while (offset < len &&
-		       ((ret = read(ctx->command_fifo_fd,
-				    (void *) dump + offset, len - offset)) > 0
-			|| errno == EAGAIN)) {
-			if (ret > 0)
-				offset += ret;
-		}
+		assert(dump);
+		assert(read_command_data(ctx->command_fifo_fd, dump, len) > 0);
 
 		fprintf(stdout, "Writing circular buffer to %s\n", dump);
 
@@ -956,6 +1028,27 @@ read_command_file(struct recording_context *ctx)
 	case RECORDER_COMMAND_QUIT:
 		quit = true;
 		break;
+	case RECORDER_COMMAND_TRIGGER: {
+		uint32_t len = header.size - sizeof(header);
+		uint32_t value;
+		char *trigger;
+
+		if (ctx->perf->devinfo.devid < 9) {
+			fprintf(stderr, "OA report trigger not supported on gen %d\n",
+				ctx->perf->devinfo.devid);
+			break;
+		}
+
+		trigger = malloc(len);
+		assert(trigger);
+		assert(read_command_data(ctx->command_fifo_fd, (uint8_t *)trigger, len) > 0);
+
+		if (__valid_trigger_value(trigger, &value))
+			oa_trigger_report(ctx, ctx->oa_trigger_reg, value);
+
+		free(trigger);
+		break;
+	}
 	default:
 		fprintf(stderr, "Unknown command 0x%x\n", header.command);
 		break;
diff --git a/tools/i915-perf/i915_perf_recorder_commands.h b/tools/i915-perf/i915_perf_recorder_commands.h
index d9353cfa..e48d9426 100644
--- a/tools/i915-perf/i915_perf_recorder_commands.h
+++ b/tools/i915-perf/i915_perf_recorder_commands.h
@@ -30,6 +30,7 @@
 enum recorder_command {
 	RECORDER_COMMAND_DUMP = 1,
 	RECORDER_COMMAND_QUIT,
+	RECORDER_COMMAND_TRIGGER,
 };
 
 struct recorder_command_base {
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for series starting with [1/5] i915/perf: add tests for triggered OA reports
  2021-08-30 19:33 [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports Umesh Nerlige Ramappa
                   ` (3 preceding siblings ...)
  2021-08-30 19:33 ` [igt-dev] [PATCH 5/5] tools/i915-perf: Add a command to trigger a report in OA buffer Umesh Nerlige Ramappa
@ 2021-08-30 20:08 ` Patchwork
  2021-08-30 21:50 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  5 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2021-08-30 20:08 UTC (permalink / raw)
  To: Umesh Nerlige Ramappa; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 4456 bytes --]

== Series Details ==

Series: series starting with [1/5] i915/perf: add tests for triggered OA reports
URL   : https://patchwork.freedesktop.org/series/94172/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_10537 -> IGTPW_6174
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/index.html

Known issues
------------

  Here are the changes found in IGTPW_6174 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_basic@cs-gfx:
    - fi-rkl-guc:         NOTRUN -> [SKIP][1] ([fdo#109315]) +17 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/fi-rkl-guc/igt@amdgpu/amd_basic@cs-gfx.html
    - fi-skl-6700k2:      NOTRUN -> [SKIP][2] ([fdo#109271]) +29 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/fi-skl-6700k2/igt@amdgpu/amd_basic@cs-gfx.html

  * igt@gem_huc_copy@huc-copy:
    - fi-skl-6700k2:      NOTRUN -> [SKIP][3] ([fdo#109271] / [i915#2190])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/fi-skl-6700k2/igt@gem_huc_copy@huc-copy.html

  * igt@i915_selftest@live@gt_lrc:
    - fi-rkl-guc:         NOTRUN -> [DMESG-WARN][4] ([i915#3958])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/fi-rkl-guc/igt@i915_selftest@live@gt_lrc.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-d:
    - fi-skl-6700k2:      NOTRUN -> [SKIP][5] ([fdo#109271] / [i915#533])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/fi-skl-6700k2/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-d.html

  
#### Possible fixes ####

  * igt@gem_exec_suspend@basic-s0:
    - fi-skl-6700k2:      [DMESG-WARN][6] ([i915#1602]) -> [PASS][7]
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/fi-skl-6700k2/igt@gem_exec_suspend@basic-s0.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/fi-skl-6700k2/igt@gem_exec_suspend@basic-s0.html

  * igt@i915_selftest@live@gt_heartbeat:
    - {fi-tgl-dsi}:       [DMESG-FAIL][8] ([i915#541]) -> [PASS][9]
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/fi-tgl-dsi/igt@i915_selftest@live@gt_heartbeat.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/fi-tgl-dsi/igt@i915_selftest@live@gt_heartbeat.html

  * igt@i915_selftest@live@workarounds:
    - fi-rkl-guc:         [DMESG-FAIL][10] ([i915#3928]) -> [PASS][11]
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/fi-rkl-guc/igt@i915_selftest@live@workarounds.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/fi-rkl-guc/igt@i915_selftest@live@workarounds.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109315]: https://bugs.freedesktop.org/show_bug.cgi?id=109315
  [i915#1602]: https://gitlab.freedesktop.org/drm/intel/issues/1602
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#3928]: https://gitlab.freedesktop.org/drm/intel/issues/3928
  [i915#3958]: https://gitlab.freedesktop.org/drm/intel/issues/3958
  [i915#533]: https://gitlab.freedesktop.org/drm/intel/issues/533
  [i915#541]: https://gitlab.freedesktop.org/drm/intel/issues/541


Participating hosts (44 -> 36)
------------------------------

  Missing    (8): fi-ilk-m540 bat-adls-5 bat-dg1-6 bat-dg1-5 fi-bsw-cyan fi-ctg-p8600 fi-bdw-samus bat-jsl-1 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_6191 -> IGTPW_6174

  CI-20190529: 20190529
  CI_DRM_10537: 81c643b64b3cb96bcfb72ae1a151c5cb728781c9 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_6174: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/index.html
  IGT_6191: e9292b533691784f46eeb9bae522ca7a8710c920 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git



== Testlist changes ==

+igt@perf@closed-fd-and-unmapped-access
+igt@perf@invalid-map-oa-buffer
+igt@perf@map-oa-buffer
+igt@perf@non-privileged-access-vaddr
+igt@perf@non-privileged-map-oa-buffer
+igt@perf@oa-regs-not-whitelisted
+igt@perf@oa-regs-whitelisted
+igt@perf@privileged-forked-access-vaddr
+igt@perf@triggered-oa-reports-paranoid-0
+igt@perf@triggered-oa-reports-paranoid-1

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/index.html

[-- Attachment #2: Type: text/html, Size: 5445 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [igt-dev] ✓ Fi.CI.IGT: success for series starting with [1/5] i915/perf: add tests for triggered OA reports
  2021-08-30 19:33 [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports Umesh Nerlige Ramappa
                   ` (4 preceding siblings ...)
  2021-08-30 20:08 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [1/5] i915/perf: add tests for triggered OA reports Patchwork
@ 2021-08-30 21:50 ` Patchwork
  5 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2021-08-30 21:50 UTC (permalink / raw)
  To: Umesh Nerlige Ramappa; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 30287 bytes --]

== Series Details ==

Series: series starting with [1/5] i915/perf: add tests for triggered OA reports
URL   : https://patchwork.freedesktop.org/series/94172/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_10537_full -> IGTPW_6174_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_6174_full:

### IGT changes ###

#### Possible regressions ####

  * {igt@perf@non-privileged-access-vaddr} (NEW):
    - shard-iclb:         NOTRUN -> [SKIP][1] +8 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb4/igt@perf@non-privileged-access-vaddr.html

  * {igt@perf@non-privileged-map-oa-buffer} (NEW):
    - shard-tglb:         NOTRUN -> [SKIP][2] +8 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb2/igt@perf@non-privileged-map-oa-buffer.html

  
New tests
---------

  New tests have been introduced between CI_DRM_10537_full and IGTPW_6174_full:

### New IGT tests (10) ###

  * igt@perf@closed-fd-and-unmapped-access:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@perf@invalid-map-oa-buffer:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@perf@map-oa-buffer:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@perf@non-privileged-access-vaddr:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@perf@non-privileged-map-oa-buffer:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@perf@oa-regs-not-whitelisted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@perf@oa-regs-whitelisted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@perf@privileged-forked-access-vaddr:
    - Statuses :
    - Exec time: [None] s

  * igt@perf@triggered-oa-reports-paranoid-0:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@perf@triggered-oa-reports-paranoid-1:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  

Known issues
------------

  Here are the changes found in IGTPW_6174_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_create@create-massive:
    - shard-snb:          NOTRUN -> [DMESG-WARN][3] ([i915#3002])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-snb7/igt@gem_create@create-massive.html

  * igt@gem_ctx_persistence@smoketest:
    - shard-snb:          NOTRUN -> [SKIP][4] ([fdo#109271] / [i915#1099]) +3 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-snb2/igt@gem_ctx_persistence@smoketest.html

  * igt@gem_eio@unwedge-stress:
    - shard-snb:          NOTRUN -> [FAIL][5] ([i915#3354])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-snb6/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_fair@basic-deadline:
    - shard-apl:          NOTRUN -> [FAIL][6] ([i915#2846])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl2/igt@gem_exec_fair@basic-deadline.html

  * igt@gem_exec_fair@basic-none-vip@rcs0:
    - shard-tglb:         [PASS][7] -> [FAIL][8] ([i915#2842]) +2 similar issues
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-tglb6/igt@gem_exec_fair@basic-none-vip@rcs0.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb3/igt@gem_exec_fair@basic-none-vip@rcs0.html

  * igt@gem_exec_fair@basic-none@rcs0:
    - shard-glk:          [PASS][9] -> [FAIL][10] ([i915#2842])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk7/igt@gem_exec_fair@basic-none@rcs0.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk7/igt@gem_exec_fair@basic-none@rcs0.html

  * igt@gem_exec_fair@basic-sync@rcs0:
    - shard-kbl:          [PASS][11] -> [SKIP][12] ([fdo#109271])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-kbl3/igt@gem_exec_fair@basic-sync@rcs0.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl4/igt@gem_exec_fair@basic-sync@rcs0.html

  * igt@gem_exec_fair@basic-throttle@rcs0:
    - shard-iclb:         [PASS][13] -> [FAIL][14] ([i915#2842]) +1 similar issue
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-iclb4/igt@gem_exec_fair@basic-throttle@rcs0.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb1/igt@gem_exec_fair@basic-throttle@rcs0.html

  * igt@gem_exec_params@secure-non-root:
    - shard-tglb:         NOTRUN -> [SKIP][15] ([fdo#112283]) +1 similar issue
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb5/igt@gem_exec_params@secure-non-root.html

  * igt@gem_render_copy@y-tiled-mc-ccs-to-yf-tiled-ccs:
    - shard-iclb:         NOTRUN -> [SKIP][16] ([i915#768])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb5/igt@gem_render_copy@y-tiled-mc-ccs-to-yf-tiled-ccs.html

  * igt@gem_softpin@evict-snoop:
    - shard-iclb:         NOTRUN -> [SKIP][17] ([fdo#109312])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb1/igt@gem_softpin@evict-snoop.html
    - shard-tglb:         NOTRUN -> [SKIP][18] ([fdo#109312])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb7/igt@gem_softpin@evict-snoop.html

  * igt@gem_workarounds@suspend-resume-context:
    - shard-kbl:          NOTRUN -> [INCOMPLETE][19] ([i915#155])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl4/igt@gem_workarounds@suspend-resume-context.html

  * igt@gen9_exec_parse@batch-invalid-length:
    - shard-snb:          NOTRUN -> [SKIP][20] ([fdo#109271]) +372 similar issues
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-snb2/igt@gen9_exec_parse@batch-invalid-length.html

  * igt@gen9_exec_parse@unaligned-jump:
    - shard-iclb:         NOTRUN -> [SKIP][21] ([i915#2856])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb5/igt@gen9_exec_parse@unaligned-jump.html
    - shard-tglb:         NOTRUN -> [SKIP][22] ([i915#2856])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb1/igt@gen9_exec_parse@unaligned-jump.html

  * igt@i915_pm_rpm@gem-mmap-type@fixed:
    - shard-iclb:         NOTRUN -> [SKIP][23] ([i915#3976])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb8/igt@i915_pm_rpm@gem-mmap-type@fixed.html

  * igt@kms_big_fb@linear-8bpp-rotate-270:
    - shard-tglb:         NOTRUN -> [SKIP][24] ([fdo#111614])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb6/igt@kms_big_fb@linear-8bpp-rotate-270.html
    - shard-iclb:         NOTRUN -> [SKIP][25] ([fdo#110725] / [fdo#111614]) +1 similar issue
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb4/igt@kms_big_fb@linear-8bpp-rotate-270.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip:
    - shard-apl:          NOTRUN -> [SKIP][26] ([fdo#109271] / [i915#3777]) +2 similar issues
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl3/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html
    - shard-glk:          NOTRUN -> [SKIP][27] ([fdo#109271] / [i915#3777])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk2/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html
    - shard-kbl:          NOTRUN -> [SKIP][28] ([fdo#109271] / [i915#3777])
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl7/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip:
    - shard-tglb:         NOTRUN -> [SKIP][29] ([fdo#111615]) +2 similar issues
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb2/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip.html

  * igt@kms_ccs@pipe-a-bad-rotation-90-y_tiled_gen12_mc_ccs:
    - shard-glk:          NOTRUN -> [SKIP][30] ([fdo#109271] / [i915#3886]) +5 similar issues
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk9/igt@kms_ccs@pipe-a-bad-rotation-90-y_tiled_gen12_mc_ccs.html
    - shard-apl:          NOTRUN -> [SKIP][31] ([fdo#109271] / [i915#3886]) +10 similar issues
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl6/igt@kms_ccs@pipe-a-bad-rotation-90-y_tiled_gen12_mc_ccs.html
    - shard-kbl:          NOTRUN -> [SKIP][32] ([fdo#109271] / [i915#3886]) +2 similar issues
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl6/igt@kms_ccs@pipe-a-bad-rotation-90-y_tiled_gen12_mc_ccs.html
    - shard-tglb:         NOTRUN -> [SKIP][33] ([i915#3689] / [i915#3886]) +3 similar issues
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb6/igt@kms_ccs@pipe-a-bad-rotation-90-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_mc_ccs:
    - shard-iclb:         NOTRUN -> [SKIP][34] ([fdo#109278] / [i915#3886]) +2 similar issues
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb6/igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-d-missing-ccs-buffer-y_tiled_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][35] ([i915#3689]) +5 similar issues
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb7/igt@kms_ccs@pipe-d-missing-ccs-buffer-y_tiled_ccs.html

  * igt@kms_cdclk@mode-transition:
    - shard-apl:          NOTRUN -> [SKIP][36] ([fdo#109271]) +282 similar issues
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl1/igt@kms_cdclk@mode-transition.html

  * igt@kms_cdclk@plane-scaling:
    - shard-iclb:         NOTRUN -> [SKIP][37] ([i915#3742]) +1 similar issue
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb7/igt@kms_cdclk@plane-scaling.html
    - shard-tglb:         NOTRUN -> [SKIP][38] ([i915#3742]) +1 similar issue
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb8/igt@kms_cdclk@plane-scaling.html

  * igt@kms_chamelium@dp-mode-timings:
    - shard-apl:          NOTRUN -> [SKIP][39] ([fdo#109271] / [fdo#111827]) +22 similar issues
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl1/igt@kms_chamelium@dp-mode-timings.html

  * igt@kms_chamelium@hdmi-aspect-ratio:
    - shard-glk:          NOTRUN -> [SKIP][40] ([fdo#109271] / [fdo#111827]) +5 similar issues
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk4/igt@kms_chamelium@hdmi-aspect-ratio.html

  * igt@kms_chamelium@hdmi-hpd-storm:
    - shard-kbl:          NOTRUN -> [SKIP][41] ([fdo#109271] / [fdo#111827]) +8 similar issues
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl3/igt@kms_chamelium@hdmi-hpd-storm.html

  * igt@kms_chamelium@vga-hpd-without-ddc:
    - shard-snb:          NOTRUN -> [SKIP][42] ([fdo#109271] / [fdo#111827]) +15 similar issues
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-snb6/igt@kms_chamelium@vga-hpd-without-ddc.html
    - shard-iclb:         NOTRUN -> [SKIP][43] ([fdo#109284] / [fdo#111827]) +1 similar issue
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb4/igt@kms_chamelium@vga-hpd-without-ddc.html

  * igt@kms_color@pipe-b-gamma:
    - shard-glk:          [PASS][44] -> [FAIL][45] ([i915#71])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk7/igt@kms_color@pipe-b-gamma.html
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk7/igt@kms_color@pipe-b-gamma.html

  * igt@kms_color_chamelium@pipe-d-ctm-limited-range:
    - shard-tglb:         NOTRUN -> [SKIP][46] ([fdo#109284] / [fdo#111827]) +6 similar issues
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb5/igt@kms_color_chamelium@pipe-d-ctm-limited-range.html
    - shard-iclb:         NOTRUN -> [SKIP][47] ([fdo#109278] / [fdo#109284] / [fdo#111827])
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb3/igt@kms_color_chamelium@pipe-d-ctm-limited-range.html

  * igt@kms_content_protection@content_type_change:
    - shard-tglb:         NOTRUN -> [SKIP][48] ([fdo#111828]) +1 similar issue
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb5/igt@kms_content_protection@content_type_change.html

  * igt@kms_content_protection@dp-mst-type-0:
    - shard-iclb:         NOTRUN -> [SKIP][49] ([i915#3116])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb6/igt@kms_content_protection@dp-mst-type-0.html

  * igt@kms_content_protection@srm:
    - shard-apl:          NOTRUN -> [TIMEOUT][50] ([i915#1319]) +1 similar issue
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl3/igt@kms_content_protection@srm.html

  * igt@kms_content_protection@type1:
    - shard-iclb:         NOTRUN -> [SKIP][51] ([fdo#109300] / [fdo#111066])
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb5/igt@kms_content_protection@type1.html

  * igt@kms_cursor_crc@pipe-a-cursor-suspend:
    - shard-kbl:          [PASS][52] -> [DMESG-WARN][53] ([i915#180]) +4 similar issues
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-kbl3/igt@kms_cursor_crc@pipe-a-cursor-suspend.html
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl3/igt@kms_cursor_crc@pipe-a-cursor-suspend.html

  * igt@kms_cursor_crc@pipe-c-cursor-32x32-random:
    - shard-tglb:         NOTRUN -> [SKIP][54] ([i915#3319])
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb7/igt@kms_cursor_crc@pipe-c-cursor-32x32-random.html

  * igt@kms_cursor_crc@pipe-c-cursor-512x170-random:
    - shard-iclb:         NOTRUN -> [SKIP][55] ([fdo#109278] / [fdo#109279]) +1 similar issue
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb4/igt@kms_cursor_crc@pipe-c-cursor-512x170-random.html

  * igt@kms_cursor_crc@pipe-c-cursor-512x512-random:
    - shard-tglb:         NOTRUN -> [SKIP][56] ([fdo#109279] / [i915#3359])
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb7/igt@kms_cursor_crc@pipe-c-cursor-512x512-random.html

  * igt@kms_cursor_crc@pipe-d-cursor-32x10-sliding:
    - shard-tglb:         NOTRUN -> [SKIP][57] ([i915#3359]) +2 similar issues
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb5/igt@kms_cursor_crc@pipe-d-cursor-32x10-sliding.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-atomic:
    - shard-iclb:         NOTRUN -> [SKIP][58] ([fdo#109274] / [fdo#109278])
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb6/igt@kms_cursor_legacy@cursora-vs-flipb-atomic.html

  * igt@kms_dsc@basic-dsc-enable:
    - shard-iclb:         NOTRUN -> [SKIP][59] ([i915#3840])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb3/igt@kms_dsc@basic-dsc-enable.html

  * igt@kms_flip@2x-dpms-vs-vblank-race-interruptible:
    - shard-iclb:         NOTRUN -> [SKIP][60] ([fdo#109274]) +1 similar issue
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb8/igt@kms_flip@2x-dpms-vs-vblank-race-interruptible.html

  * igt@kms_flip@2x-plain-flip-fb-recreate@bc-hdmi-a1-hdmi-a2:
    - shard-glk:          [PASS][61] -> [FAIL][62] ([i915#2122])
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk4/igt@kms_flip@2x-plain-flip-fb-recreate@bc-hdmi-a1-hdmi-a2.html
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk4/igt@kms_flip@2x-plain-flip-fb-recreate@bc-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset@ab-hdmi-a1-hdmi-a2:
    - shard-glk:          NOTRUN -> [DMESG-WARN][63] ([i915#118] / [i915#95])
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk4/igt@kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset@ab-hdmi-a1-hdmi-a2.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-blt:
    - shard-iclb:         NOTRUN -> [SKIP][64] ([fdo#109280]) +11 similar issues
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb2/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-gtt:
    - shard-tglb:         NOTRUN -> [SKIP][65] ([fdo#111825]) +18 similar issues
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb5/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-cpu:
    - shard-glk:          NOTRUN -> [SKIP][66] ([fdo#109271]) +71 similar issues
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk8/igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-cpu.html

  * igt@kms_pipe_b_c_ivb@enable-pipe-c-while-b-has-3-lanes:
    - shard-tglb:         NOTRUN -> [SKIP][67] ([fdo#109289])
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb3/igt@kms_pipe_b_c_ivb@enable-pipe-c-while-b-has-3-lanes.html
    - shard-iclb:         NOTRUN -> [SKIP][68] ([fdo#109289])
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb2/igt@kms_pipe_b_c_ivb@enable-pipe-c-while-b-has-3-lanes.html

  * igt@kms_pipe_crc_basic@nonblocking-crc-pipe-d-frame-sequence:
    - shard-kbl:          NOTRUN -> [SKIP][69] ([fdo#109271] / [i915#533])
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl4/igt@kms_pipe_crc_basic@nonblocking-crc-pipe-d-frame-sequence.html

  * igt@kms_plane_alpha_blend@pipe-b-constant-alpha-max:
    - shard-apl:          NOTRUN -> [FAIL][70] ([fdo#108145] / [i915#265]) +3 similar issues
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl6/igt@kms_plane_alpha_blend@pipe-b-constant-alpha-max.html

  * igt@kms_plane_alpha_blend@pipe-c-alpha-transparent-fb:
    - shard-apl:          NOTRUN -> [FAIL][71] ([i915#265])
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl7/igt@kms_plane_alpha_blend@pipe-c-alpha-transparent-fb.html

  * igt@kms_plane_lowres@pipe-b-tiling-yf:
    - shard-tglb:         NOTRUN -> [SKIP][72] ([fdo#112054])
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb6/igt@kms_plane_lowres@pipe-b-tiling-yf.html
    - shard-iclb:         NOTRUN -> [SKIP][73] ([i915#3536])
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb2/igt@kms_plane_lowres@pipe-b-tiling-yf.html

  * igt@kms_plane_scaling@scaler-with-clipping-clamping@pipe-c-scaler-with-clipping-clamping:
    - shard-kbl:          NOTRUN -> [SKIP][74] ([fdo#109271] / [i915#2733])
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl7/igt@kms_plane_scaling@scaler-with-clipping-clamping@pipe-c-scaler-with-clipping-clamping.html

  * igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-2:
    - shard-glk:          NOTRUN -> [SKIP][75] ([fdo#109271] / [i915#658]) +1 similar issue
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk3/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-2.html

  * igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-4:
    - shard-apl:          NOTRUN -> [SKIP][76] ([fdo#109271] / [i915#658]) +5 similar issues
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl8/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-4.html
    - shard-tglb:         NOTRUN -> [SKIP][77] ([i915#2920]) +1 similar issue
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb3/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-4.html
    - shard-iclb:         NOTRUN -> [SKIP][78] ([i915#2920])
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb2/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-4.html

  * igt@kms_psr2_su@page_flip:
    - shard-tglb:         NOTRUN -> [SKIP][79] ([i915#1911])
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb3/igt@kms_psr2_su@page_flip.html
    - shard-kbl:          NOTRUN -> [SKIP][80] ([fdo#109271] / [i915#658]) +1 similar issue
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl6/igt@kms_psr2_su@page_flip.html
    - shard-iclb:         NOTRUN -> [SKIP][81] ([fdo#109642] / [fdo#111068] / [i915#658])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb8/igt@kms_psr2_su@page_flip.html

  * igt@kms_psr@psr2_basic:
    - shard-tglb:         NOTRUN -> [FAIL][82] ([i915#132] / [i915#3467])
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb6/igt@kms_psr@psr2_basic.html
    - shard-iclb:         NOTRUN -> [SKIP][83] ([fdo#109441])
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb5/igt@kms_psr@psr2_basic.html

  * igt@kms_psr@psr2_cursor_mmap_cpu:
    - shard-iclb:         [PASS][84] -> [SKIP][85] ([fdo#109441]) +1 similar issue
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-iclb2/igt@kms_psr@psr2_cursor_mmap_cpu.html
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb4/igt@kms_psr@psr2_cursor_mmap_cpu.html

  * igt@kms_vblank@pipe-d-ts-continuation-modeset-rpm:
    - shard-iclb:         NOTRUN -> [SKIP][86] ([fdo#109278]) +15 similar issues
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb8/igt@kms_vblank@pipe-d-ts-continuation-modeset-rpm.html

  * igt@nouveau_crc@pipe-a-source-rg:
    - shard-iclb:         NOTRUN -> [SKIP][87] ([i915#2530]) +1 similar issue
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb7/igt@nouveau_crc@pipe-a-source-rg.html

  * igt@nouveau_crc@pipe-c-source-outp-complete:
    - shard-tglb:         NOTRUN -> [SKIP][88] ([i915#2530]) +1 similar issue
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb8/igt@nouveau_crc@pipe-c-source-outp-complete.html

  * {igt@perf@oa-regs-not-whitelisted} (NEW):
    - shard-kbl:          NOTRUN -> [SKIP][89] ([fdo#109271]) +73 similar issues
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl1/igt@perf@oa-regs-not-whitelisted.html

  * igt@perf_pmu@event-wait@rcs0:
    - shard-iclb:         NOTRUN -> [SKIP][90] ([fdo#112283]) +1 similar issue
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb8/igt@perf_pmu@event-wait@rcs0.html

  * igt@perf_pmu@rc6-suspend:
    - shard-kbl:          NOTRUN -> [DMESG-WARN][91] ([i915#180])
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl3/igt@perf_pmu@rc6-suspend.html

  * igt@prime_nv_pcopy@test1_micro:
    - shard-tglb:         NOTRUN -> [SKIP][92] ([fdo#109291]) +1 similar issue
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb7/igt@prime_nv_pcopy@test1_micro.html

  * igt@sysfs_clients@fair-7:
    - shard-apl:          NOTRUN -> [SKIP][93] ([fdo#109271] / [i915#2994]) +1 similar issue
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl1/igt@sysfs_clients@fair-7.html

  * igt@sysfs_clients@recycle:
    - shard-kbl:          NOTRUN -> [SKIP][94] ([fdo#109271] / [i915#2994])
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl7/igt@sysfs_clients@recycle.html

  
#### Possible fixes ####

  * igt@feature_discovery@psr2:
    - shard-iclb:         [SKIP][95] ([i915#658]) -> [PASS][96]
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-iclb6/igt@feature_discovery@psr2.html
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb2/igt@feature_discovery@psr2.html

  * igt@gem_exec_fair@basic-none-share@rcs0:
    - shard-iclb:         [FAIL][97] ([i915#2842]) -> [PASS][98]
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-iclb6/igt@gem_exec_fair@basic-none-share@rcs0.html
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb8/igt@gem_exec_fair@basic-none-share@rcs0.html

  * igt@gem_exec_fair@basic-pace-solo@rcs0:
    - shard-glk:          [FAIL][99] ([i915#2842]) -> [PASS][100] +3 similar issues
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk6/igt@gem_exec_fair@basic-pace-solo@rcs0.html
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk3/igt@gem_exec_fair@basic-pace-solo@rcs0.html

  * igt@gem_exec_fair@basic-pace@rcs0:
    - shard-kbl:          [FAIL][101] ([i915#2842]) -> [PASS][102] +2 similar issues
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-kbl2/igt@gem_exec_fair@basic-pace@rcs0.html
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl2/igt@gem_exec_fair@basic-pace@rcs0.html

  * igt@gem_exec_fair@basic-pace@vcs0:
    - shard-tglb:         [FAIL][103] ([i915#2842]) -> [PASS][104]
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-tglb8/igt@gem_exec_fair@basic-pace@vcs0.html
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-tglb2/igt@gem_exec_fair@basic-pace@vcs0.html

  * igt@gem_exec_whisper@basic-contexts-priority-all:
    - shard-glk:          [DMESG-WARN][105] ([i915#118] / [i915#95]) -> [PASS][106]
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk4/igt@gem_exec_whisper@basic-contexts-priority-all.html
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk5/igt@gem_exec_whisper@basic-contexts-priority-all.html

  * igt@gem_mmap_gtt@cpuset-big-copy-xy:
    - shard-iclb:         [FAIL][107] ([i915#307]) -> [PASS][108]
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-iclb7/igt@gem_mmap_gtt@cpuset-big-copy-xy.html
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb5/igt@gem_mmap_gtt@cpuset-big-copy-xy.html

  * igt@gem_mmap_gtt@cpuset-medium-copy-odd:
    - shard-iclb:         [FAIL][109] ([i915#2428]) -> [PASS][110] +1 similar issue
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-iclb3/igt@gem_mmap_gtt@cpuset-medium-copy-odd.html
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb8/igt@gem_mmap_gtt@cpuset-medium-copy-odd.html

  * igt@i915_pm_rpm@gem-mmap-type@gtt:
    - shard-iclb:         [INCOMPLETE][111] -> [PASS][112]
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-iclb7/igt@i915_pm_rpm@gem-mmap-type@gtt.html
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb8/igt@i915_pm_rpm@gem-mmap-type@gtt.html

  * igt@i915_suspend@forcewake:
    - shard-apl:          [DMESG-WARN][113] ([i915#180]) -> [PASS][114]
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-apl3/igt@i915_suspend@forcewake.html
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl1/igt@i915_suspend@forcewake.html

  * igt@kms_async_flips@alternate-sync-async-flip:
    - shard-glk:          [FAIL][115] ([i915#2521]) -> [PASS][116]
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk4/igt@kms_async_flips@alternate-sync-async-flip.html
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk8/igt@kms_async_flips@alternate-sync-async-flip.html

  * igt@kms_cursor_crc@pipe-b-cursor-size-change:
    - shard-snb:          [FAIL][117] ([i915#4024]) -> [PASS][118]
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-snb2/igt@kms_cursor_crc@pipe-b-cursor-size-change.html
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-snb7/igt@kms_cursor_crc@pipe-b-cursor-size-change.html
    - shard-kbl:          [FAIL][119] ([i915#3444]) -> [PASS][120]
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-kbl1/igt@kms_cursor_crc@pipe-b-cursor-size-change.html
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl2/igt@kms_cursor_crc@pipe-b-cursor-size-change.html
    - shard-glk:          [FAIL][121] ([i915#3444]) -> [PASS][122]
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk5/igt@kms_cursor_crc@pipe-b-cursor-size-change.html
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk8/igt@kms_cursor_crc@pipe-b-cursor-size-change.html
    - shard-apl:          [FAIL][123] ([i915#3444]) -> [PASS][124]
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-apl2/igt@kms_cursor_crc@pipe-b-cursor-size-change.html
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-apl7/igt@kms_cursor_crc@pipe-b-cursor-size-change.html

  * igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ab-hdmi-a1-hdmi-a2:
    - shard-glk:          [FAIL][125] ([i915#79]) -> [PASS][126]
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk4/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ab-hdmi-a1-hdmi-a2.html
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk9/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ab-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@2x-plain-flip-fb-recreate@ab-hdmi-a1-hdmi-a2:
    - shard-glk:          [FAIL][127] ([i915#2122]) -> [PASS][128]
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-glk4/igt@kms_flip@2x-plain-flip-fb-recreate@ab-hdmi-a1-hdmi-a2.html
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-glk4/igt@kms_flip@2x-plain-flip-fb-recreate@ab-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-kbl:          [DMESG-WARN][129] ([i915#180]) -> [PASS][130] +3 similar issues
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-kbl7/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl4/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_flip@flip-vs-suspend@c-dp1:
    - shard-kbl:          [INCOMPLETE][131] ([i915#636]) -> [PASS][132]
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-kbl2/igt@kms_flip@flip-vs-suspend@c-dp1.html
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-kbl1/igt@kms_flip@flip-vs-suspend@c-dp1.html

  * igt@kms_psr2_su@frontbuffer:
    - shard-iclb:         [SKIP][133] ([fdo#109642] / [fdo#111068] / [i915#658]) -> [PASS][134]
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10537/shard-iclb3/igt@kms_psr2_su@frontbuffer.html
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/shard-iclb2/igt@kms_psr2_su@frontbuffer.html

  * igt@kms_psr@psr2_primary_mmap_cpu:

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6174/index.html

[-- Attachment #2: Type: text/html, Size: 33962 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports
@ 2021-08-03 20:07 Umesh Nerlige Ramappa
  0 siblings, 0 replies; 8+ messages in thread
From: Umesh Nerlige Ramappa @ 2021-08-03 20:07 UTC (permalink / raw)
  To: igt-dev, Ashutosh Dixit, Lionel G Landwerlin

From: Lionel G Landwerlin <lionel.g.landwerlin@intel.com>

By whitelisting a couple of registers we can allow an application
batch to trigger OA reports in the OA buffer by switching back & forth
an inverter on the condition logic.

v2: Wait before sampling the timestamp used to end the OA buffer search
v3:
- Ensure OA regs are whitelisted and reports are triggered only when
  perf_stream_paranoid is set to 0.
- Drop root to trigger reports.
v4:
- wait for children after igt_assert
- use new api for intel batch buffer
- clean up test code

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 tests/i915/perf.c | 421 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 404 insertions(+), 17 deletions(-)

diff --git a/tests/i915/perf.c b/tests/i915/perf.c
index e641d5d2..fa3840eb 100644
--- a/tests/i915/perf.c
+++ b/tests/i915/perf.c
@@ -53,6 +53,8 @@ IGT_TEST_DESCRIPTION("Test the i915 perf metrics streaming interface");
 #define OAREPORT_REASON_SHIFT          19
 #define OAREPORT_REASON_TIMER          (1<<0)
 #define OAREPORT_REASON_INTERNAL       (3<<1)
+#define OAREPORT_REASON_TRIGGER1       (1<<1)
+#define OAREPORT_REASON_TRIGGER2       (1<<2)
 #define OAREPORT_REASON_CTX_SWITCH     (1<<3)
 #define OAREPORT_REASON_GO             (1<<4)
 #define OAREPORT_REASON_CLK_RATIO      (1<<5)
@@ -204,6 +206,7 @@ static struct intel_perf *intel_perf = NULL;
 static struct intel_perf_metric_set *test_set = NULL;
 static bool *undefined_a_counters;
 static uint64_t oa_exp_1_millisec;
+struct intel_mmio_data mmio_data;
 
 static igt_render_copyfunc_t render_copy = NULL;
 static uint32_t (*read_report_ticks)(const uint32_t *report,
@@ -294,6 +297,23 @@ __perf_open(int fd, struct drm_i915_perf_open_param *param, bool prevent_pm)
 	return ret;
 }
 
+static int i915_perf_revision(int fd)
+{
+	drm_i915_getparam_t gp;
+	int value = 1, ret;
+
+	gp.param = I915_PARAM_PERF_REVISION;
+	gp.value = &value;
+	ret = igt_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	if (ret == -1) {
+		/* If the param is missing, consider version 1. */
+		igt_assert_eq(errno, EINVAL);
+		return 1;
+	}
+
+	return value;
+}
+
 static int
 lookup_format(int i915_perf_fmt_id)
 {
@@ -3151,6 +3171,283 @@ emit_stall_timestamp_and_rpc(struct intel_bb *ibb,
 	emit_report_perf_count(ibb, dst, report_dst_offset, report_id);
 }
 
+/* The following register all have the same layout. */
+#define OAREPORTTRIG2 (0x2744)
+#define   OAREPORTTRIG2_INVERT_A_0  (1 << 0)
+#define   OAREPORTTRIG2_INVERT_A_1  (1 << 1)
+#define   OAREPORTTRIG2_INVERT_A_2  (1 << 2)
+#define   OAREPORTTRIG2_INVERT_A_3  (1 << 3)
+#define   OAREPORTTRIG2_INVERT_A_4  (1 << 4)
+#define   OAREPORTTRIG2_INVERT_A_5  (1 << 5)
+#define   OAREPORTTRIG2_INVERT_A_6  (1 << 6)
+#define   OAREPORTTRIG2_INVERT_A_7  (1 << 7)
+#define   OAREPORTTRIG2_INVERT_A_8  (1 << 8)
+#define   OAREPORTTRIG2_INVERT_A_9  (1 << 9)
+#define   OAREPORTTRIG2_INVERT_A_10 (1 << 10)
+#define   OAREPORTTRIG2_INVERT_A_11 (1 << 11)
+#define   OAREPORTTRIG2_INVERT_A_12 (1 << 12)
+#define   OAREPORTTRIG2_INVERT_A_13 (1 << 13)
+#define   OAREPORTTRIG2_INVERT_A_14 (1 << 14)
+#define   OAREPORTTRIG2_INVERT_A_15 (1 << 15)
+#define   OAREPORTTRIG2_INVERT_B_0  (1 << 16)
+#define   OAREPORTTRIG2_INVERT_B_1  (1 << 17)
+#define   OAREPORTTRIG2_INVERT_B_2  (1 << 18)
+#define   OAREPORTTRIG2_INVERT_B_3  (1 << 19)
+#define   OAREPORTTRIG2_INVERT_C_0  (1 << 20)
+#define   OAREPORTTRIG2_INVERT_C_1  (1 << 21)
+#define   OAREPORTTRIG2_INVERT_D_0  (1 << 22)
+#define   OAREPORTTRIG2_THRESHOLD_ENABLE      (1 << 23)
+#define   OAREPORTTRIG2_REPORT_TRIGGER_ENABLE (1 << 31)
+#define OAREPORTTRIG6 (0x2754)
+#define OA_PERF_COUNTER_A(idx) (0x2800 + 8 * (idx))
+#define GEN8_OASTATUS (0x2b08)
+
+#define GEN12_OAREPORTTRIG2 (0xd924)
+#define GEN12_OAREPORTTRIG6 (0xd934)
+#define GEN12_OAG_PERF_COUNTER_A(idx) (0xD980 + 8 * (idx))
+#define GEN12_OAG_OASTATUS (0xdafc)
+
+#define RING_FORCE_TO_NONPRIV_ADDRESS_MASK 0x03fffffc
+
+/*
+ * We have 2 trigger registers that each generate a different
+ * report reason.
+ */
+static const uint32_t gen9_oa_wl[] = {
+	OAREPORTTRIG2,
+	OAREPORTTRIG6,
+	OA_PERF_COUNTER_A(18),
+	GEN8_OASTATUS,
+};
+static const uint32_t gen12_oa_wl[] = {
+	GEN12_OAREPORTTRIG2,
+	GEN12_OAREPORTTRIG6,
+	GEN12_OAG_PERF_COUNTER_A(18),
+	GEN12_OAG_OASTATUS,
+};
+
+static const uint32_t nonpriv_slots[] = {
+	0x24d0, 0x24d4, 0x24d8, 0x24dc, 0x24e0, 0x24e4, 0x24e8, 0x24ec,
+	0x24f0, 0x24f4, 0x24f8, 0x24fc, 0x2010, 0x2014, 0x2018, 0x201c,
+	0x21e0, 0x21e4, 0x21e8, 0x21ec,
+};
+
+struct test_perf {
+	const uint32_t *slots;
+	uint32_t num_slots;
+	const uint32_t *wl;
+	uint32_t num_wl;
+} perf;
+
+static void perf_init_whitelist(void)
+{
+	perf.slots = nonpriv_slots;
+
+	if (intel_gen(devid) >= 12) {
+		perf.num_slots = 20;
+		perf.wl = gen12_oa_wl;
+		perf.num_wl = i915_perf_revision(drm_fd) < 7 ? 2 :
+			       ARRAY_SIZE(gen12_oa_wl);
+	} else {
+		perf.num_slots = 12;
+		perf.wl = gen9_oa_wl;
+		perf.num_wl = i915_perf_revision(drm_fd) < 7 ? 2 :
+			       ARRAY_SIZE(gen9_oa_wl);
+	}
+}
+
+static void
+emit_triggered_oa_report(struct intel_bb *ibb, uint32_t trigger)
+{
+	const uint32_t *triggers = perf.wl;
+
+	assert(trigger <= 1);
+
+	intel_bb_out(ibb, MI_LOAD_REGISTER_IMM);
+	intel_bb_out(ibb, triggers[trigger]);
+	intel_bb_out(ibb, OAREPORTTRIG2_INVERT_C_1 |
+			  OAREPORTTRIG2_REPORT_TRIGGER_ENABLE);
+	intel_bb_out(ibb, MI_LOAD_REGISTER_IMM);
+	intel_bb_out(ibb, triggers[trigger]);
+	intel_bb_out(ibb, OAREPORTTRIG2_INVERT_C_1 |
+			  OAREPORTTRIG2_INVERT_D_0 |
+			  OAREPORTTRIG2_REPORT_TRIGGER_ENABLE);
+}
+
+static uint64_t
+rcs_timestmap_reg_read(int fd)
+{
+	struct drm_i915_reg_read rr = {
+		.offset = 0x2358 | I915_REG_READ_8B_WA, /* render ring timestamp */
+	};
+
+	do_ioctl(fd, DRM_IOCTL_I915_REG_READ, &rr);
+
+	return rr.val;
+}
+
+/*
+ * Verify that we can trigger OA reports into the OA buffer using
+ * MI_LRI.
+ */
+static void
+test_triggered_oa_reports(int paranoid)
+{
+	int oa_exponent = max_oa_exponent_for_period_lte(1000000);
+	uint64_t properties[] = {
+		DRM_I915_PERF_PROP_CTX_HANDLE, UINT64_MAX, /* updated below */
+
+		/* Note: we have to specify at least one sample property even
+		 * though we aren't interested in samples in this case
+		 */
+		DRM_I915_PERF_PROP_SAMPLE_OA, true,
+
+		/* OA unit configuration */
+		DRM_I915_PERF_PROP_OA_METRICS_SET, test_set->perf_oa_metrics_set,
+		DRM_I915_PERF_PROP_OA_FORMAT, test_set->perf_oa_format,
+		DRM_I915_PERF_PROP_OA_EXPONENT, oa_exponent,
+
+		/* Note: no OA exponent specified in this case */
+	};
+	struct drm_i915_perf_open_param param = {
+		.flags = I915_PERF_FLAG_FD_CLOEXEC,
+		.num_properties = ARRAY_SIZE(properties) / 2,
+		.properties_ptr = to_user_pointer(properties),
+	};
+	struct drm_i915_perf_record_header *header;
+	struct buf_ops *bops;
+	uint32_t context;
+	struct igt_helper_process child = {};
+	struct intel_bb *ibb;
+	struct intel_buf src[2], dst[2];
+	uint64_t timestamp32_mask = (1ull << 32) - 1;
+	uint64_t timestamps[2];
+	uint32_t buf_size = 16 * 1024 * 1024;
+	uint8_t *buf = malloc(buf_size);
+	int width = 800;
+	int height = 600;
+	uint32_t trigger_counts[2] = { 0, };
+	int ret;
+
+	write_u64_file("/proc/sys/dev/i915/perf_stream_paranoid", paranoid);
+
+	do {
+		igt_fork_helper(&child) {
+			if (!paranoid)
+				igt_drop_root();
+
+			bops = buf_ops_create(drm_fd);
+
+			scratch_buf_init(bops, &src[0], width, height, 0xff0000ff);
+			scratch_buf_init(bops, &dst[0], width, height, 0x00ff00ff);
+			scratch_buf_init(bops, &src[1], 2 * width, height, 0xff0000ff);
+			scratch_buf_init(bops, &dst[1], 2 * width, height, 0x00ff00ff);
+
+			context = gem_context_create(drm_fd);
+			igt_assert(context);
+			ibb = intel_bb_create_with_context(drm_fd, context, BATCH_SZ);
+			properties[1] = context;
+
+			timestamps[0] = rcs_timestmap_reg_read(drm_fd);
+
+			stream_fd = __perf_open(drm_fd, &param, false);
+
+			emit_triggered_oa_report(ibb, 0);
+
+			render_copy(ibb,
+				    &src[0], 0, 0, width, height,
+				    &dst[0], 0, 0);
+
+			emit_triggered_oa_report(ibb, 0);
+
+			emit_triggered_oa_report(ibb, 1);
+
+			render_copy(ibb,
+				    &src[1], 0, 0, 2 * width, height,
+				    &dst[1], 0, 0);
+
+			emit_triggered_oa_report(ibb, 1);
+
+			intel_bb_flush_render(ibb);
+			intel_bb_sync(ibb);
+
+			timestamps[1] = rcs_timestmap_reg_read(drm_fd);
+
+			if (timestamps[1] < timestamps[0] ||
+			    (timestamps[1] & timestamp32_mask) < (timestamps[1] & timestamp32_mask)) {
+				igt_debug("Timestamp rollover, trying again\n");
+				exit(EAGAIN);
+			}
+
+			ret = i915_read_reports_until_timestamp(test_set->perf_oa_format,
+								buf, buf_size,
+								timestamps[0] & timestamp32_mask,
+								timestamps[1] & timestamp32_mask);
+
+			for (size_t offset = 0; offset < ret; offset += header->size) {
+				uint32_t *report;
+
+				header = (void *)(buf + offset);
+
+				igt_assert_eq(header->pad, 0); /* Reserved */
+
+				igt_assert_neq(header->type, DRM_I915_PERF_RECORD_OA_BUFFER_LOST);
+
+				if (header->type == DRM_I915_PERF_RECORD_OA_REPORT_LOST)
+					continue;
+
+				/* Currently the only other record type expected is a
+				 * _SAMPLE. Notably this test will need updating if
+				 * i915-perf is extended in the future with additional
+				 * record types.
+				 */
+				igt_assert_eq(header->type, DRM_I915_PERF_RECORD_SAMPLE);
+
+				report = (void *)(header + 1);
+
+				igt_debug("report ts=0x%08x hw_id=0x%08x reason=%s\n",
+					  report[1], report[2],
+					  gen8_read_report_reason(report));
+
+				if (gen8_report_reason(report) & OAREPORT_REASON_TRIGGER1) {
+					igt_assert_eq(trigger_counts[1], 0);
+					trigger_counts[0]++;
+				}
+				if (gen8_report_reason(report) & OAREPORT_REASON_TRIGGER2) {
+					igt_assert_eq(trigger_counts[0], 2);
+					trigger_counts[1]++;
+				}
+			}
+
+			if (paranoid) {
+				igt_assert_eq(trigger_counts[0], 0);
+				igt_assert_eq(trigger_counts[1], 0);
+			} else {
+				igt_assert_eq(trigger_counts[0], 2);
+				igt_assert_eq(trigger_counts[1], 2);
+			}
+
+			for (int i = 0; i < ARRAY_SIZE(src); i++) {
+				intel_buf_close(bops, &src[i]);
+				intel_buf_close(bops, &dst[i]);
+			}
+
+			intel_bb_destroy(ibb);
+			gem_context_destroy(drm_fd, context);
+			buf_ops_destroy(bops);
+			__perf_close(stream_fd);
+		}
+
+		ret = igt_wait_helper(&child);
+
+		igt_assert(WEXITSTATUS(ret) == EAGAIN ||
+			   WEXITSTATUS(ret) == 0);
+
+	} while (WEXITSTATUS(ret) == EAGAIN);
+
+	free(buf);
+}
+
 /* Tests the INTEL_performance_query use case where an unprivileged process
  * should be able to configure the OA unit for per-context metrics (for a
  * context associated with that process' drm file descriptor) and the counters
@@ -4777,6 +5074,88 @@ test_whitelisted_registers_userspace_config(void)
 	i915_perf_remove_config(drm_fd, config_id);
 }
 
+static void dump_whitelist(const char *msg)
+{
+	int i;
+
+	igt_debug("%s\n", msg);
+
+	for (i = 0; i < perf.num_slots; i++)
+		igt_debug("FORCE_TO_NON_PRIV_%02d = %08x\n",
+			  i, intel_register_read(&mmio_data, perf.slots[i]));
+}
+
+static bool in_whitelist(uint32_t reg)
+{
+	int i;
+
+	for (i = 0; i < perf.num_slots; i++) {
+		uint32_t fpriv = intel_register_read(&mmio_data, perf.slots[i]);
+
+		if ((fpriv & RING_FORCE_TO_NONPRIV_ADDRESS_MASK) == reg)
+			return true;
+	}
+
+	return false;
+}
+
+static void oa_regs_in_whitelist(bool are_present)
+{
+	int i;
+
+	if (are_present) {
+		for (i = 0; i < perf.num_wl; i++)
+			igt_assert(in_whitelist(perf.wl[i]));
+	} else {
+		for (i = 0; i < perf.num_wl; i++)
+			igt_assert(!in_whitelist(perf.wl[i]));
+	}
+}
+
+static void test_oa_regs_whitelist(int paranoid)
+{
+	uint64_t properties[] = {
+		DRM_I915_PERF_PROP_SAMPLE_OA, true,
+		DRM_I915_PERF_PROP_OA_METRICS_SET, test_set->perf_oa_metrics_set,
+		DRM_I915_PERF_PROP_OA_FORMAT, test_set->perf_oa_format,
+		DRM_I915_PERF_PROP_OA_EXPONENT, oa_exp_1_millisec,
+
+	};
+	struct drm_i915_perf_open_param param = {
+		.flags = I915_PERF_FLAG_FD_CLOEXEC,
+		.num_properties = sizeof(properties) / 16,
+		.properties_ptr = to_user_pointer(properties),
+	};
+	write_u64_file("/proc/sys/dev/i915/perf_stream_paranoid", paranoid);
+	intel_register_access_init(&mmio_data, intel_get_pci_device(),
+				   0, drm_fd);
+	stream_fd = __perf_open(drm_fd, &param, false);
+
+	dump_whitelist("oa whitelisted");
+
+	/*
+	 * oa registers are whitelisted only if paranoid = 0. if so, make sure
+	 * that the registers are in the nonpriv slots. if not, make sure the
+	 * registers are NOT present in the nonpriv slots.
+	 */
+	if (paranoid)
+		oa_regs_in_whitelist(false);
+	else
+		oa_regs_in_whitelist(true);
+
+	__perf_close(stream_fd);
+
+	dump_whitelist("oa remove whitelist");
+
+	/*
+	 * after perf close, check that registers are removed from the nonpriv
+	 * slots
+	 */
+	oa_regs_in_whitelist(false);
+
+	intel_register_access_fini(&mmio_data);
+}
+
 static unsigned
 read_i915_module_ref(void)
 {
@@ -4889,23 +5268,6 @@ test_sysctl_defaults(void)
 	igt_assert_eq(max_freq, 100000);
 }
 
-static int i915_perf_revision(int fd)
-{
-	drm_i915_getparam_t gp;
-	int value = 1, ret;
-
-	gp.param = I915_PARAM_PERF_REVISION;
-	gp.value = &value;
-	ret = igt_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
-	if (ret == -1) {
-		/* If the param is missing, consider version 1. */
-		igt_assert_eq(errno, EINVAL);
-		return 1;
-	}
-
-	return value;
-}
-
 igt_main
 {
 	igt_fixture {
@@ -5119,6 +5481,31 @@ igt_main
 	igt_subtest("whitelisted-registers-userspace-config")
 		test_whitelisted_registers_userspace_config();
 
+
+	igt_subtest_group {
+		igt_fixture {
+			igt_require(intel_gen(devid) > 8);
+			igt_require(i915_perf_revision(drm_fd) >= 6);
+			perf_init_whitelist();
+		}
+
+		igt_describe("Verify that OA registers are whitelisted for paranoid 0");
+		igt_subtest("oa-regs-whitelisted")
+			test_oa_regs_whitelist(0);
+
+		igt_describe("Verify that OA registers are not whitelisted for paranoid 1");
+		igt_subtest("oa-regs-not-whitelisted")
+			test_oa_regs_whitelist(1);
+
+		igt_describe("Verify reports triggered when perf_stream_paranoid is 0");
+		igt_subtest("triggered-oa-reports-paranoid-0")
+			test_triggered_oa_reports(0);
+
+		igt_describe("Verify reports not triggered when perf_stream_paranoid is 1");
+		igt_subtest("triggered-oa-reports-paranoid-1")
+			test_triggered_oa_reports(1);
+	}
+
 	igt_fixture {
 		/* leave sysctl options in their default state... */
 		write_u64_file("/proc/sys/dev/i915/oa_max_sample_rate", 100000);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-08-30 21:50 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-30 19:33 [igt-dev] [PATCH 1/5] i915/perf: add tests for triggered OA reports Umesh Nerlige Ramappa
2021-08-30 19:33 ` [igt-dev] [PATCH 2/5] i915/perf: Add tests for mapped OA buffer Umesh Nerlige Ramappa
2021-08-30 19:33 ` [igt-dev] [PATCH 3/5] lib/i915/perf: Add new record for mmaped " Umesh Nerlige Ramappa
2021-08-30 19:33 ` [igt-dev] [PATCH 4/5] tools/i915-perf: Add mmapped OA buffer support to i915-perf-recorder Umesh Nerlige Ramappa
2021-08-30 19:33 ` [igt-dev] [PATCH 5/5] tools/i915-perf: Add a command to trigger a report in OA buffer Umesh Nerlige Ramappa
2021-08-30 20:08 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [1/5] i915/perf: add tests for triggered OA reports Patchwork
2021-08-30 21:50 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2021-08-03 20:07 [igt-dev] [PATCH 1/5] " Umesh Nerlige Ramappa

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.