* [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
@ 2023-06-27 16:31 Venkata Ramana Nayana
2023-06-28 12:05 ` Kumar, Janga Rahul
0 siblings, 1 reply; 8+ messages in thread
From: Venkata Ramana Nayana @ 2023-06-27 16:31 UTC (permalink / raw)
To: igt-dev
There are set of engine group busyness counters provided by HW which are
exposed via PMU events. Adding a basic unit tests to read those counters.
Signed-off-by: Venkata Ramana Nayana <venkata.ramana.nayana@intel.com>
---
include/drm-uapi/xe_drm.h | 21 +++
lib/igt_perf.c | 36 ++++
lib/igt_perf.h | 5 +
tests/meson.build | 1 +
tests/xe/xe_perf_pmu.c | 335 ++++++++++++++++++++++++++++++++++++++
5 files changed, 398 insertions(+)
create mode 100644 tests/xe/xe_perf_pmu.c
diff --git a/include/drm-uapi/xe_drm.h b/include/drm-uapi/xe_drm.h
index 432bd87ca..7bfd46c02 100644
--- a/include/drm-uapi/xe_drm.h
+++ b/include/drm-uapi/xe_drm.h
@@ -732,6 +732,27 @@ struct drm_xe_engine_create {
__u64 reserved[2];
};
+/**
+ * DOC: perf_events exposed by xe through /sys/bus/event_sources/drivers/xe
+ *
+ */
+
+
+/* PMU event config IDs */
+
+/*
+ * Top 4 bits of every counter are GT id.
+ */
+#define __XE_PMU_GT_SHIFT (60)
+
+#define ___XE_PMU_OTHER(gt, x) \
+ (((__u64)(x)) | ((__u64)(gt) << __XE_PMU_GT_SHIFT))
+
+#define XE_PMU_RENDER_GROUP_BUSY(gt) ___XE_PMU_OTHER(gt, 1)
+#define XE_PMU_COPY_GROUP_BUSY(gt) ___XE_PMU_OTHER(gt, 2)
+#define XE_PMU_MEDIA_GROUP_BUSY(gt) ___XE_PMU_OTHER(gt, 3)
+#define XE_PMU_ANY_ENGINE_GROUP_BUSY(gt) ___XE_PMU_OTHER(gt, 4)
+
struct drm_xe_engine_get_property {
/** @extensions: Pointer to the first extension struct, if any */
__u64 extensions;
diff --git a/lib/igt_perf.c b/lib/igt_perf.c
index ffe078adc..3866c6d77 100644
--- a/lib/igt_perf.c
+++ b/lib/igt_perf.c
@@ -69,6 +69,36 @@ const char *i915_perf_device(int i915, char *buf, int buflen)
return buf;
}
+const char *xe_perf_device(int xe, char *buf, int buflen)
+{
+ char *s;
+ char pref[] = "xe_";
+ int len = strlen(pref);
+
+
+ if (!buf || buflen < len)
+ return "xe";
+
+ memcpy(buf, pref, len);
+
+ if (!bus_address(xe, buf + len, buflen - len))
+ buf[len - 1] = '\0';
+
+ /* Convert all colons in the address to '_', thanks perf! */
+ for (s = buf; *s; s++)
+ if (*s == ':')
+ *s = '_';
+
+ return buf;
+}
+
+uint64_t xe_perf_type_id(int xe)
+{
+ char buf[80];
+
+ return igt_perf_type_id(xe_perf_device(xe, buf, sizeof(buf)));
+}
+
uint64_t i915_perf_type_id(int i915)
{
char buf[80];
@@ -147,6 +177,12 @@ int perf_igfx_open_group(uint64_t config, int group)
PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP);
}
+int perf_xe_open(int xe, uint64_t config)
+{
+ return _perf_open(xe_perf_type_id(xe), config, -1,
+ PERF_FORMAT_TOTAL_TIME_ENABLED);
+}
+
int perf_i915_open(int i915, uint64_t config)
{
return _perf_open(i915_perf_type_id(i915), config, -1,
diff --git a/lib/igt_perf.h b/lib/igt_perf.h
index 4d86e31ae..3d9ba2917 100644
--- a/lib/igt_perf.h
+++ b/lib/igt_perf.h
@@ -61,10 +61,15 @@ int igt_perf_open_group(uint64_t type, uint64_t config, int group);
const char *i915_perf_device(int i915, char *buf, int buflen);
uint64_t i915_perf_type_id(int i915);
+const char *xe_perf_device(int xe, char *buf, int buflen);
+uint64_t xe_perf_type_id(int);
+
int perf_igfx_open(uint64_t config);
int perf_igfx_open_group(uint64_t config, int group);
int perf_i915_open(int i915, uint64_t config);
int perf_i915_open_group(int i915, uint64_t config, int group);
+int perf_xe_open(int xe, uint64_t config);
+
#endif /* I915_PERF_H */
diff --git a/tests/meson.build b/tests/meson.build
index 85ea7e74e..e64d8232e 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -270,6 +270,7 @@ xe_progs = [
'xe_vm',
'xe_waitfence',
'xe_spin_batch',
+ 'xe_perf_pmu',
]
msm_progs = [
diff --git a/tests/xe/xe_perf_pmu.c b/tests/xe/xe_perf_pmu.c
new file mode 100644
index 000000000..97c2f84a3
--- /dev/null
+++ b/tests/xe/xe_perf_pmu.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+/**
+ * TEST: Basic tests for verify pmu perf interface
+ * Category: Hardware building block
+ * Sub-category: pmu interface
+ * Functionality: pmu
+ * Test category: functionality test
+ */
+
+#include <fcntl.h>
+
+#include "igt.h"
+#include "lib/igt_syncobj.h"
+#include "lib/intel_reg.h"
+#include "lib/igt_perf.h"
+#include "xe_drm.h"
+
+#include "xe/xe_ioctl.h"
+#include "xe/xe_query.h"
+#include "xe/xe_spin.h"
+#include <string.h>
+
+#define MAX_INSTANCE 9
+
+static uint64_t pmu_read(int fd)
+{
+ uint64_t data[2];
+
+ igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data));
+
+ return data[0];
+}
+
+static int open_pmu(int fd, uint64_t config)
+{
+ int perf_fd;
+
+ perf_fd = perf_xe_open(fd, config);
+ igt_skip_on(perf_fd < 0 && errno == ENODEV);
+ igt_assert(perf_fd >= 0);
+
+ return perf_fd;
+}
+
+static uint64_t engine_group_get_config(int gt, int class)
+{
+ uint64_t config;
+
+ switch (class) {
+ case DRM_XE_ENGINE_CLASS_COPY:
+ config = XE_PMU_COPY_GROUP_BUSY(gt);
+ break;
+ case DRM_XE_ENGINE_CLASS_RENDER:
+ case DRM_XE_ENGINE_CLASS_COMPUTE:
+ config = XE_PMU_RENDER_GROUP_BUSY(gt);
+ break;
+ case DRM_XE_ENGINE_CLASS_VIDEO_DECODE:
+ case DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE:
+ config = XE_PMU_MEDIA_GROUP_BUSY(gt);
+ break;
+ }
+
+ return config;
+}
+
+/**
+ * Test: Basic test for measure the active time when engine of any class active
+ *
+ * SUBTEST: any-engine-group-busy
+ * Description:
+ * Run a test to measure the global activity time by submitting
+ * the WL to all existing engines.
+ * Run type: FULL
+ * TODO: change ``'Run type' == FULL`` to a better category
+ */
+static void test_any_engine_busyness(int fd, struct drm_xe_engine_class_instance *eci)
+{
+ uint32_t vm;
+ uint64_t addr = 0x1a0000;
+ struct drm_xe_sync sync[2] = {
+ { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
+ { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
+ };
+ struct drm_xe_exec exec = {
+ .num_batch_buffer = 1,
+ .num_syncs = 2,
+ .syncs = to_user_pointer(sync),
+ };
+ uint32_t engine;
+ uint32_t syncobj;
+ size_t bo_size;
+ uint32_t bo = 0;
+ struct xe_spin *spin;
+ uint32_t pmu_fd;
+ uint64_t count, idle = 0;
+
+ vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
+ bo_size = sizeof(*spin);
+ bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd),
+ xe_get_default_alignment(fd));
+
+ bo = xe_bo_create(fd, eci->gt_id, vm, bo_size);
+ spin = xe_bo_map(fd, bo, bo_size);
+
+ engine = xe_engine_create(fd, vm, eci, 0);
+ syncobj = syncobj_create(fd, 0);
+
+ sync[0].handle = syncobj_create(fd, 0);
+ xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
+
+ pmu_fd = open_pmu(fd, XE_PMU_ANY_ENGINE_GROUP_BUSY(eci->gt_id));
+
+ xe_spin_init(spin, addr, false);
+
+ sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
+ sync[1].flags |= DRM_XE_SYNC_SIGNAL;
+ sync[1].handle = syncobj;
+
+ exec.engine_id = engine;
+ exec.address = addr;
+ xe_exec(fd, &exec);
+
+ xe_spin_wait_started(spin);
+ usleep(50000);
+
+ igt_assert(!syncobj_wait(fd, &syncobj, 1, 1, 0, NULL));
+ xe_spin_end(spin);
+
+ igt_assert(syncobj_wait(fd, &syncobj, 1, INT64_MAX, 0, NULL));
+ igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+ sync[0].flags |= DRM_XE_SYNC_SIGNAL;
+ xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
+ igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+ syncobj_destroy(fd, sync[0].handle);
+ syncobj_destroy(fd, syncobj);
+
+ count = pmu_read(pmu_fd);
+ igt_assert_lt_u64(idle, count);
+ igt_debug("Incrementing counter all-busy-group %ld ns\n", count);
+
+ xe_engine_destroy(fd, engine);
+ munmap(spin, bo_size);
+ gem_close(fd, bo);
+ xe_vm_destroy(fd, vm);
+ close(pmu_fd);
+}
+
+/**
+ * Test: Basic test for measure the active time across engine class
+ *
+ * SUBTEST: render-busy
+ * Description:
+ * Run a test to measure the active engine class time by submitting the
+ * WL to all instances of a class
+ * Run type: FULL
+ * TODO: change ``'Run type' == FULL`` to a better category
+ *
+ * SUBTEST: compute-busy
+ * Description: Run copy-group-busy test
+ * Run type: FULL
+ * TODO: change ``'Run type' == FULL`` to a better category
+ *
+ * SUBTEST: copy-busy
+ * Description: Run copy-group-busy test
+ * Run type: FULL
+ * TODO: change ``'Run type' == FULL`` to a better category
+ *
+ * SUBTEST: vcs-busy
+ * Description: Run copy-group-busy test
+ * Run type: FULL
+ * TODO: change ``'Run type' == FULL`` to a better category
+ *
+ * SUBTEST: vecs-busy
+ * Description: Run copy-group-busy test
+ * Run type: FULL
+ * TODO: change ``'Run type' == FULL`` to a better category
+ *
+ */
+
+static void test_engine_group_busyness(int fd, int gt, int class, const char *name)
+{
+ uint32_t vm;
+ uint64_t addr = 0x1a0000;
+ struct drm_xe_sync sync[2] = {
+ { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
+ { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
+ };
+ struct drm_xe_exec exec = {
+ .num_batch_buffer = 1,
+ .num_syncs = 2,
+ .syncs = to_user_pointer(sync),
+ };
+ uint32_t engines[MAX_INSTANCE];
+ uint32_t syncobjs[MAX_INSTANCE];
+ int pmu_fd;
+ size_t bo_size;
+ uint32_t bo = 0, i = 0;
+ struct {
+ struct xe_spin spin;
+ } *data;
+ struct drm_xe_engine_class_instance *hwe;
+ struct drm_xe_engine_class_instance eci[MAX_INSTANCE];
+ int num_placements = 0;
+ uint64_t config, count, idle = 0;
+
+ config = engine_group_get_config(gt, class);
+
+ xe_for_each_hw_engine(fd, hwe) {
+ if (hwe->engine_class != class || hwe->gt_id != gt)
+ continue;
+
+ eci[num_placements++] = *hwe;
+ }
+
+ if (!num_placements) {
+ igt_info("Engine class:%d gt:%d not enabled on this platform\n", class, gt);
+ return;
+ }
+
+ vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
+ bo_size = sizeof(*data) * num_placements;
+ bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd), xe_get_default_alignment(fd));
+
+ bo = xe_bo_create(fd, gt, vm, bo_size);
+ data = xe_bo_map(fd, bo, bo_size);
+
+ for (i = 0; i < num_placements; i++) {
+ struct drm_xe_engine_create create = {
+ .vm_id = vm,
+ .width = 1,
+ .num_placements = num_placements,
+ .instances = to_user_pointer(eci),
+ };
+
+ igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_ENGINE_CREATE,
+ &create), 0);
+ engines[i] = create.engine_id;
+ syncobjs[i] = syncobj_create(fd, 0);
+ };
+
+ sync[0].handle = syncobj_create(fd, 0);
+ xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
+
+ pmu_fd = open_pmu(fd, config);
+
+ for (i = 0; i < num_placements; i++) {
+ uint64_t spin_offset = (char *)&data[i].spin - (char *)data;
+ uint64_t spin_addr = addr + spin_offset;
+
+ xe_spin_init(&data[i].spin, spin_addr, false);
+ sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
+ sync[1].flags |= DRM_XE_SYNC_SIGNAL;
+ sync[1].handle = syncobjs[i];
+
+ exec.engine_id = engines[i];
+ exec.address = spin_addr;
+ xe_exec(fd, &exec);
+ xe_spin_wait_started(&data[i].spin);
+ }
+
+ for (i = 0; i < num_placements; i++) {
+ xe_spin_end(&data[i].spin);
+ igt_assert(syncobj_wait(fd, &syncobjs[i], 1, INT64_MAX, 0,
+ NULL));
+ }
+
+ igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+ sync[0].flags |= DRM_XE_SYNC_SIGNAL;
+ xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
+ igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+
+ syncobj_destroy(fd, sync[0].handle);
+ for (i = 0; i < num_placements; i++) {
+ syncobj_destroy(fd, syncobjs[i]);
+ xe_engine_destroy(fd, engines[i]);
+ }
+
+ count = pmu_read(pmu_fd);
+ igt_assert_lt_u64(idle, count);
+ igt_debug("Incrementing counter %s-gt-%d %ld ns\n", name, gt, count);
+
+ munmap(data, bo_size);
+ gem_close(fd, bo);
+ xe_vm_destroy(fd, vm);
+ close(pmu_fd);
+}
+
+igt_main
+{
+ struct drm_xe_engine_class_instance *hwe;
+ const struct section {
+ const char *name;
+ int class;
+ } sections[] = {
+ { "render-busy", DRM_XE_ENGINE_CLASS_RENDER },
+ { "compute-busy", DRM_XE_ENGINE_CLASS_COMPUTE },
+ { "copy-busy", DRM_XE_ENGINE_CLASS_COPY },
+ { "vcs-busy", DRM_XE_ENGINE_CLASS_VIDEO_DECODE },
+ { "vecs-busy", DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE },
+ { NULL },
+ };
+ int gt;
+ int class;
+ int fd;
+
+ igt_fixture {
+ fd = drm_open_driver(DRIVER_XE);
+ xe_device_get(fd);
+ }
+
+ for (const struct section *s = sections; s->name; s++) {
+ igt_subtest_f("%s", s->name)
+ xe_for_each_gt(fd, gt)
+ xe_for_each_hw_engine_class(class)
+ if (class == s->class)
+ test_engine_group_busyness(fd, gt, class, s->name);
+ }
+
+ igt_subtest("any-engine-group-busy")
+ xe_for_each_hw_engine(fd, hwe)
+ test_any_engine_busyness(fd, hwe);
+
+ igt_fixture {
+ xe_device_put(fd);
+ close(fd);
+ }
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
2023-06-27 16:31 Venkata Ramana Nayana
@ 2023-06-28 12:05 ` Kumar, Janga Rahul
2023-07-04 9:59 ` Nayana, Venkata Ramana
0 siblings, 1 reply; 8+ messages in thread
From: Kumar, Janga Rahul @ 2023-06-28 12:05 UTC (permalink / raw)
To: Nayana, Venkata Ramana, igt-dev@lists.freedesktop.org
> -----Original Message-----
> From: igt-dev <igt-dev-bounces@lists.freedesktop.org> On Behalf Of Venkata
> Ramana Nayana
> Sent: 27 June 2023 22:02
> To: igt-dev@lists.freedesktop.org
> Subject: [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
>
> There are set of engine group busyness counters provided by HW which are
> exposed via PMU events. Adding a basic unit tests to read those counters.
Pls mention driver patch details exposing PMU events if It is in review.
> Signed-off-by: Venkata Ramana Nayana <venkata.ramana.nayana@intel.com>
> ---
> include/drm-uapi/xe_drm.h | 21 +++
> lib/igt_perf.c | 36 ++++
> lib/igt_perf.h | 5 +
> tests/meson.build | 1 +
> tests/xe/xe_perf_pmu.c | 335 ++++++++++++++++++++++++++++++++++++++
> 5 files changed, 398 insertions(+)
> create mode 100644 tests/xe/xe_perf_pmu.c
>
> diff --git a/include/drm-uapi/xe_drm.h b/include/drm-uapi/xe_drm.h index
> 432bd87ca..7bfd46c02 100644
> --- a/include/drm-uapi/xe_drm.h
> +++ b/include/drm-uapi/xe_drm.h
Do not edit this file.
See "drm-uapi/xe_drm: Sync from drm-xe-next" commit to sync this file.
> @@ -732,6 +732,27 @@ struct drm_xe_engine_create {
> __u64 reserved[2];
> };
>
> +/**
> + * DOC: perf_events exposed by xe through
> +/sys/bus/event_sources/drivers/xe
> + *
> + */
> +
> +
> +/* PMU event config IDs */
> +
> +/*
> + * Top 4 bits of every counter are GT id.
> + */
> +#define __XE_PMU_GT_SHIFT (60)
> +
> +#define ___XE_PMU_OTHER(gt, x) \
> + (((__u64)(x)) | ((__u64)(gt) << __XE_PMU_GT_SHIFT))
> +
> +#define XE_PMU_RENDER_GROUP_BUSY(gt)
> ___XE_PMU_OTHER(gt, 1)
> +#define XE_PMU_COPY_GROUP_BUSY(gt)
> ___XE_PMU_OTHER(gt, 2)
> +#define XE_PMU_MEDIA_GROUP_BUSY(gt)
> ___XE_PMU_OTHER(gt, 3)
> +#define XE_PMU_ANY_ENGINE_GROUP_BUSY(gt)
> ___XE_PMU_OTHER(gt, 4)
> +
> struct drm_xe_engine_get_property {
> /** @extensions: Pointer to the first extension struct, if any */
> __u64 extensions;
> diff --git a/lib/igt_perf.c b/lib/igt_perf.c index ffe078adc..3866c6d77 100644
> --- a/lib/igt_perf.c
> +++ b/lib/igt_perf.c
> @@ -69,6 +69,36 @@ const char *i915_perf_device(int i915, char *buf, int
> buflen)
> return buf;
> }
>
> +const char *xe_perf_device(int xe, char *buf, int buflen) {
> + char *s;
> + char pref[] = "xe_";
> + int len = strlen(pref);
> +
> +
> + if (!buf || buflen < len)
> + return "xe";
> +
> + memcpy(buf, pref, len);
> +
> + if (!bus_address(xe, buf + len, buflen - len))
> + buf[len - 1] = '\0';
> +
> + /* Convert all colons in the address to '_', thanks perf! */
> + for (s = buf; *s; s++)
> + if (*s == ':')
> + *s = '_';
> +
> + return buf;
> +}
> +
> +uint64_t xe_perf_type_id(int xe)
> +{
> + char buf[80];
> +
> + return igt_perf_type_id(xe_perf_device(xe, buf, sizeof(buf))); }
> +
> uint64_t i915_perf_type_id(int i915)
> {
> char buf[80];
> @@ -147,6 +177,12 @@ int perf_igfx_open_group(uint64_t config, int group)
> PERF_FORMAT_TOTAL_TIME_ENABLED |
> PERF_FORMAT_GROUP); }
>
> +int perf_xe_open(int xe, uint64_t config) {
> + return _perf_open(xe_perf_type_id(xe), config, -1,
> + PERF_FORMAT_TOTAL_TIME_ENABLED);
> +}
> +
> int perf_i915_open(int i915, uint64_t config) {
> return _perf_open(i915_perf_type_id(i915), config, -1, diff --git
> a/lib/igt_perf.h b/lib/igt_perf.h index 4d86e31ae..3d9ba2917 100644
> --- a/lib/igt_perf.h
> +++ b/lib/igt_perf.h
> @@ -61,10 +61,15 @@ int igt_perf_open_group(uint64_t type, uint64_t config,
> int group); const char *i915_perf_device(int i915, char *buf, int buflen);
> uint64_t i915_perf_type_id(int i915);
>
> +const char *xe_perf_device(int xe, char *buf, int buflen); uint64_t
> +xe_perf_type_id(int);
> +
> int perf_igfx_open(uint64_t config);
> int perf_igfx_open_group(uint64_t config, int group);
>
> int perf_i915_open(int i915, uint64_t config); int perf_i915_open_group(int
> i915, uint64_t config, int group);
>
> +int perf_xe_open(int xe, uint64_t config);
> +
> #endif /* I915_PERF_H */
> diff --git a/tests/meson.build b/tests/meson.build index 85ea7e74e..e64d8232e
> 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -270,6 +270,7 @@ xe_progs = [
> 'xe_vm',
> 'xe_waitfence',
> 'xe_spin_batch',
> + 'xe_perf_pmu',
> ]
>
> msm_progs = [
> diff --git a/tests/xe/xe_perf_pmu.c b/tests/xe/xe_perf_pmu.c new file mode
> 100644 index 000000000..97c2f84a3
> --- /dev/null
> +++ b/tests/xe/xe_perf_pmu.c
> @@ -0,0 +1,335 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +
> +/**
> + * TEST: Basic tests for verify pmu perf interface
> + * Category: Hardware building block
> + * Sub-category: pmu interface
> + * Functionality: pmu
> + * Test category: functionality test
Add Run Type here.
> + */
> +
> +#include <fcntl.h>
> +
> +#include "igt.h"
> +#include "lib/igt_syncobj.h"
> +#include "lib/intel_reg.h"
> +#include "lib/igt_perf.h"
> +#include "xe_drm.h"
> +
> +#include "xe/xe_ioctl.h"
> +#include "xe/xe_query.h"
> +#include "xe/xe_spin.h"
> +#include <string.h>
Keep includes sorted alphabetically, also please put system includes
first, then write one newline, then igt includes.
> +
> +#define MAX_INSTANCE 9
> +
> +static uint64_t pmu_read(int fd)
> +{
> + uint64_t data[2];
> +
> + igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data));
> +
> + return data[0];
> +}
> +
> +static int open_pmu(int fd, uint64_t config) {
> + int perf_fd;
> +
> + perf_fd = perf_xe_open(fd, config);
> + igt_skip_on(perf_fd < 0 && errno == ENODEV);
> + igt_assert(perf_fd >= 0);
> +
> + return perf_fd;
> +}
> +
> +static uint64_t engine_group_get_config(int gt, int class) {
> + uint64_t config;
> +
> + switch (class) {
> + case DRM_XE_ENGINE_CLASS_COPY:
> + config = XE_PMU_COPY_GROUP_BUSY(gt);
> + break;
> + case DRM_XE_ENGINE_CLASS_RENDER:
> + case DRM_XE_ENGINE_CLASS_COMPUTE:
> + config = XE_PMU_RENDER_GROUP_BUSY(gt);
> + break;
> + case DRM_XE_ENGINE_CLASS_VIDEO_DECODE:
> + case DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE:
> + config = XE_PMU_MEDIA_GROUP_BUSY(gt);
> + break;
> + }
> +
> + return config;
> +}
> +
> +/**
> + * Test: Basic test for measure the active time when engine of any
> +class active
> + *
> + * SUBTEST: any-engine-group-busy
> + * Description:
> + * Run a test to measure the global activity time by submitting
> + * the WL to all existing engines.
> + * Run type: FULL
> + * TODO: change ``'Run type' == FULL`` to a better category */ static
> +void test_any_engine_busyness(int fd, struct
> +drm_xe_engine_class_instance *eci) {
> + uint32_t vm;
> + uint64_t addr = 0x1a0000;
> + struct drm_xe_sync sync[2] = {
> + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
> + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
> + };
> + struct drm_xe_exec exec = {
> + .num_batch_buffer = 1,
> + .num_syncs = 2,
> + .syncs = to_user_pointer(sync),
> + };
> + uint32_t engine;
> + uint32_t syncobj;
> + size_t bo_size;
> + uint32_t bo = 0;
> + struct xe_spin *spin;
> + uint32_t pmu_fd;
> + uint64_t count, idle = 0;
> +
> + vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
> + bo_size = sizeof(*spin);
> + bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd),
> + xe_get_default_alignment(fd));
> +
> + bo = xe_bo_create(fd, eci->gt_id, vm, bo_size);
> + spin = xe_bo_map(fd, bo, bo_size);
> +
> + engine = xe_engine_create(fd, vm, eci, 0);
> + syncobj = syncobj_create(fd, 0);
> +
> + sync[0].handle = syncobj_create(fd, 0);
> + xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
> +
> + pmu_fd = open_pmu(fd, XE_PMU_ANY_ENGINE_GROUP_BUSY(eci-
> >gt_id));
> +
> + xe_spin_init(spin, addr, false);
> +
> + sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
> + sync[1].flags |= DRM_XE_SYNC_SIGNAL;
> + sync[1].handle = syncobj;
> +
> + exec.engine_id = engine;
> + exec.address = addr;
> + xe_exec(fd, &exec);
> +
> + xe_spin_wait_started(spin);
> + usleep(50000);
> +
> + igt_assert(!syncobj_wait(fd, &syncobj, 1, 1, 0, NULL));
> + xe_spin_end(spin);
> +
> + igt_assert(syncobj_wait(fd, &syncobj, 1, INT64_MAX, 0, NULL));
> + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> + sync[0].flags |= DRM_XE_SYNC_SIGNAL;
> + xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
> + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> + syncobj_destroy(fd, sync[0].handle);
> + syncobj_destroy(fd, syncobj);
> +
> + count = pmu_read(pmu_fd);
> + igt_assert_lt_u64(idle, count);
> + igt_debug("Incrementing counter all-busy-group %ld ns\n", count);
> +
> + xe_engine_destroy(fd, engine);
> + munmap(spin, bo_size);
> + gem_close(fd, bo);
> + xe_vm_destroy(fd, vm);
> + close(pmu_fd);
> +}
> +
> +/**
> + * Test: Basic test for measure the active time across engine class
> + *
> + * SUBTEST: render-busy
> + * Description:
> + * Run a test to measure the active engine class time by submitting the
> + * WL to all instances of a class
> + * Run type: FULL
> + * TODO: change ``'Run type' == FULL`` to a better category
Remove TODO's these are not required now.
Existing ones are removed by "tests/xe: remove an useless TODO message"
> + *
> + * SUBTEST: compute-busy
> + * Description: Run copy-group-busy test
> + * Run type: FULL
> + * TODO: change ``'Run type' == FULL`` to a better category
> + *
> + * SUBTEST: copy-busy
> + * Description: Run copy-group-busy test
> + * Run type: FULL
> + * TODO: change ``'Run type' == FULL`` to a better category
> + *
> + * SUBTEST: vcs-busy
> + * Description: Run copy-group-busy test
> + * Run type: FULL
> + * TODO: change ``'Run type' == FULL`` to a better category
> + *
> + * SUBTEST: vecs-busy
> + * Description: Run copy-group-busy test
> + * Run type: FULL
> + * TODO: change ``'Run type' == FULL`` to a better category
> + *
> + */
> +
> +static void test_engine_group_busyness(int fd, int gt, int class, const
> +char *name) {
> + uint32_t vm;
> + uint64_t addr = 0x1a0000;
> + struct drm_xe_sync sync[2] = {
> + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
> + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
> + };
> + struct drm_xe_exec exec = {
> + .num_batch_buffer = 1,
> + .num_syncs = 2,
> + .syncs = to_user_pointer(sync),
> + };
> + uint32_t engines[MAX_INSTANCE];
> + uint32_t syncobjs[MAX_INSTANCE];
> + int pmu_fd;
> + size_t bo_size;
> + uint32_t bo = 0, i = 0;
> + struct {
> + struct xe_spin spin;
> + } *data;
> + struct drm_xe_engine_class_instance *hwe;
> + struct drm_xe_engine_class_instance eci[MAX_INSTANCE];
> + int num_placements = 0;
> + uint64_t config, count, idle = 0;
> +
> + config = engine_group_get_config(gt, class);
> +
> + xe_for_each_hw_engine(fd, hwe) {
> + if (hwe->engine_class != class || hwe->gt_id != gt)
> + continue;
> +
> + eci[num_placements++] = *hwe;
> + }
> +
> + if (!num_placements) {
> + igt_info("Engine class:%d gt:%d not enabled on this
> platform\n", class, gt);
> + return;
> + }
> +
> + vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
> + bo_size = sizeof(*data) * num_placements;
> + bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd),
> +xe_get_default_alignment(fd));
> +
> + bo = xe_bo_create(fd, gt, vm, bo_size);
> + data = xe_bo_map(fd, bo, bo_size);
> +
> + for (i = 0; i < num_placements; i++) {
> + struct drm_xe_engine_create create = {
> + .vm_id = vm,
> + .width = 1,
> + .num_placements = num_placements,
> + .instances = to_user_pointer(eci),
> + };
> +
> + igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_ENGINE_CREATE,
> + &create), 0);
> + engines[i] = create.engine_id;
> + syncobjs[i] = syncobj_create(fd, 0);
> + };
> +
> + sync[0].handle = syncobj_create(fd, 0);
> + xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
> +
> + pmu_fd = open_pmu(fd, config);
Pls check for engine idleness before submitting the workload.
Thanks,
Rahul
> +
> + for (i = 0; i < num_placements; i++) {
> + uint64_t spin_offset = (char *)&data[i].spin - (char *)data;
> + uint64_t spin_addr = addr + spin_offset;
> +
> + xe_spin_init(&data[i].spin, spin_addr, false);
> + sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
> + sync[1].flags |= DRM_XE_SYNC_SIGNAL;
> + sync[1].handle = syncobjs[i];
> +
> + exec.engine_id = engines[i];
> + exec.address = spin_addr;
> + xe_exec(fd, &exec);
> + xe_spin_wait_started(&data[i].spin);
> + }
> +
> + for (i = 0; i < num_placements; i++) {
> + xe_spin_end(&data[i].spin);
> + igt_assert(syncobj_wait(fd, &syncobjs[i], 1, INT64_MAX, 0,
> + NULL));
> + }
> +
> + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> + sync[0].flags |= DRM_XE_SYNC_SIGNAL;
> + xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
> + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> +
> + syncobj_destroy(fd, sync[0].handle);
> + for (i = 0; i < num_placements; i++) {
> + syncobj_destroy(fd, syncobjs[i]);
> + xe_engine_destroy(fd, engines[i]);
> + }
> +
> + count = pmu_read(pmu_fd);
> + igt_assert_lt_u64(idle, count);
> + igt_debug("Incrementing counter %s-gt-%d %ld ns\n", name, gt, count);
> +
> + munmap(data, bo_size);
> + gem_close(fd, bo);
> + xe_vm_destroy(fd, vm);
> + close(pmu_fd);
> +}
> +
> +igt_main
> +{
> + struct drm_xe_engine_class_instance *hwe;
> + const struct section {
> + const char *name;
> + int class;
> + } sections[] = {
> + { "render-busy", DRM_XE_ENGINE_CLASS_RENDER },
> + { "compute-busy", DRM_XE_ENGINE_CLASS_COMPUTE },
> + { "copy-busy", DRM_XE_ENGINE_CLASS_COPY },
> + { "vcs-busy", DRM_XE_ENGINE_CLASS_VIDEO_DECODE },
> + { "vecs-busy", DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE },
> + { NULL },
> + };
> + int gt;
> + int class;
> + int fd;
> +
> + igt_fixture {
> + fd = drm_open_driver(DRIVER_XE);
> + xe_device_get(fd);
> + }
> +
> + for (const struct section *s = sections; s->name; s++) {
> + igt_subtest_f("%s", s->name)
> + xe_for_each_gt(fd, gt)
> + xe_for_each_hw_engine_class(class)
> + if (class == s->class)
> +
> test_engine_group_busyness(fd, gt, class, s->name);
> + }
> +
> + igt_subtest("any-engine-group-busy")
> + xe_for_each_hw_engine(fd, hwe)
> + test_any_engine_busyness(fd, hwe);
> +
> + igt_fixture {
> + xe_device_put(fd);
> + close(fd);
> + }
> +}
> --
> 2.25.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
2023-06-28 12:05 ` Kumar, Janga Rahul
@ 2023-07-04 9:59 ` Nayana, Venkata Ramana
0 siblings, 0 replies; 8+ messages in thread
From: Nayana, Venkata Ramana @ 2023-07-04 9:59 UTC (permalink / raw)
To: Kumar, Janga Rahul, igt-dev@lists.freedesktop.org
Thanks for the review.. comments inline.
> -----Original Message-----
> From: Kumar, Janga Rahul <janga.rahul.kumar@intel.com>
> Sent: Wednesday, June 28, 2023 5:35 PM
> To: Nayana, Venkata Ramana <venkata.ramana.nayana@intel.com>; igt-
> dev@lists.freedesktop.org
> Subject: RE: [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu
> interface
>
>
>
> > -----Original Message-----
> > From: igt-dev <igt-dev-bounces@lists.freedesktop.org> On Behalf Of
> > Venkata Ramana Nayana
> > Sent: 27 June 2023 22:02
> > To: igt-dev@lists.freedesktop.org
> > Subject: [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu
> > interface
> >
> > There are set of engine group busyness counters provided by HW which
> > are exposed via PMU events. Adding a basic unit tests to read those
> counters.
>
> Pls mention driver patch details exposing PMU events if It is in review.
>
sure. Will include driver patch in the next series.
> > Signed-off-by: Venkata Ramana Nayana
> <venkata.ramana.nayana@intel.com>
> > ---
> > include/drm-uapi/xe_drm.h | 21 +++
> > lib/igt_perf.c | 36 ++++
> > lib/igt_perf.h | 5 +
> > tests/meson.build | 1 +
> > tests/xe/xe_perf_pmu.c | 335
> ++++++++++++++++++++++++++++++++++++++
> > 5 files changed, 398 insertions(+)
> > create mode 100644 tests/xe/xe_perf_pmu.c
> >
> > diff --git a/include/drm-uapi/xe_drm.h b/include/drm-uapi/xe_drm.h
> > index
> > 432bd87ca..7bfd46c02 100644
> > --- a/include/drm-uapi/xe_drm.h
> > +++ b/include/drm-uapi/xe_drm.h
> Do not edit this file.
> See "drm-uapi/xe_drm: Sync from drm-xe-next" commit to sync this file.
>
Currently the PMU xe kmd changes not yet merged so to avoid compilation issues and
to verify the functionality including/editing these header files.
> > @@ -732,6 +732,27 @@ struct drm_xe_engine_create {
> > __u64 reserved[2];
> > };
> >
> > +/**
> > + * DOC: perf_events exposed by xe through
> > +/sys/bus/event_sources/drivers/xe
> > + *
> > + */
> > +
> > +
> > +/* PMU event config IDs */
> > +
> > +/*
> > + * Top 4 bits of every counter are GT id.
> > + */
> > +#define __XE_PMU_GT_SHIFT (60)
> > +
> > +#define ___XE_PMU_OTHER(gt, x) \
> > + (((__u64)(x)) | ((__u64)(gt) << __XE_PMU_GT_SHIFT))
> > +
> > +#define XE_PMU_RENDER_GROUP_BUSY(gt)
> > ___XE_PMU_OTHER(gt, 1)
> > +#define XE_PMU_COPY_GROUP_BUSY(gt)
> > ___XE_PMU_OTHER(gt, 2)
> > +#define XE_PMU_MEDIA_GROUP_BUSY(gt)
> > ___XE_PMU_OTHER(gt, 3)
> > +#define XE_PMU_ANY_ENGINE_GROUP_BUSY(gt)
> > ___XE_PMU_OTHER(gt, 4)
> > +
> > struct drm_xe_engine_get_property {
> > /** @extensions: Pointer to the first extension struct, if any */
> > __u64 extensions;
> > diff --git a/lib/igt_perf.c b/lib/igt_perf.c index
> > ffe078adc..3866c6d77 100644
> > --- a/lib/igt_perf.c
> > +++ b/lib/igt_perf.c
> > @@ -69,6 +69,36 @@ const char *i915_perf_device(int i915, char *buf,
> > int
> > buflen)
> > return buf;
> > }
> >
> > +const char *xe_perf_device(int xe, char *buf, int buflen) {
> > + char *s;
> > + char pref[] = "xe_";
> > + int len = strlen(pref);
> > +
> > +
> > + if (!buf || buflen < len)
> > + return "xe";
> > +
> > + memcpy(buf, pref, len);
> > +
> > + if (!bus_address(xe, buf + len, buflen - len))
> > + buf[len - 1] = '\0';
> > +
> > + /* Convert all colons in the address to '_', thanks perf! */
> > + for (s = buf; *s; s++)
> > + if (*s == ':')
> > + *s = '_';
> > +
> > + return buf;
> > +}
> > +
> > +uint64_t xe_perf_type_id(int xe)
> > +{
> > + char buf[80];
> > +
> > + return igt_perf_type_id(xe_perf_device(xe, buf, sizeof(buf))); }
> > +
> > uint64_t i915_perf_type_id(int i915)
> > {
> > char buf[80];
> > @@ -147,6 +177,12 @@ int perf_igfx_open_group(uint64_t config, int
> group)
> > PERF_FORMAT_TOTAL_TIME_ENABLED |
> PERF_FORMAT_GROUP); }
> >
> > +int perf_xe_open(int xe, uint64_t config) {
> > + return _perf_open(xe_perf_type_id(xe), config, -1,
> > + PERF_FORMAT_TOTAL_TIME_ENABLED);
> > +}
> > +
> > int perf_i915_open(int i915, uint64_t config) {
> > return _perf_open(i915_perf_type_id(i915), config, -1, diff --git
> > a/lib/igt_perf.h b/lib/igt_perf.h index 4d86e31ae..3d9ba2917 100644
> > --- a/lib/igt_perf.h
> > +++ b/lib/igt_perf.h
> > @@ -61,10 +61,15 @@ int igt_perf_open_group(uint64_t type, uint64_t
> > config, int group); const char *i915_perf_device(int i915, char *buf,
> > int buflen); uint64_t i915_perf_type_id(int i915);
> >
> > +const char *xe_perf_device(int xe, char *buf, int buflen); uint64_t
> > +xe_perf_type_id(int);
> > +
> > int perf_igfx_open(uint64_t config);
> > int perf_igfx_open_group(uint64_t config, int group);
> >
> > int perf_i915_open(int i915, uint64_t config); int
> > perf_i915_open_group(int i915, uint64_t config, int group);
> >
> > +int perf_xe_open(int xe, uint64_t config);
> > +
> > #endif /* I915_PERF_H */
> > diff --git a/tests/meson.build b/tests/meson.build index
> > 85ea7e74e..e64d8232e
> > 100644
> > --- a/tests/meson.build
> > +++ b/tests/meson.build
> > @@ -270,6 +270,7 @@ xe_progs = [
> > 'xe_vm',
> > 'xe_waitfence',
> > 'xe_spin_batch',
> > + 'xe_perf_pmu',
> > ]
> >
> > msm_progs = [
> > diff --git a/tests/xe/xe_perf_pmu.c b/tests/xe/xe_perf_pmu.c new file
> > mode
> > 100644 index 000000000..97c2f84a3
> > --- /dev/null
> > +++ b/tests/xe/xe_perf_pmu.c
> > @@ -0,0 +1,335 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2021 Intel Corporation */
> > +
> > +/**
> > + * TEST: Basic tests for verify pmu perf interface
> > + * Category: Hardware building block
> > + * Sub-category: pmu interface
> > + * Functionality: pmu
> > + * Test category: functionality test
> Add Run Type here.
>
I have gone through some other igt's.. looks like sub-test comments require "Run Type".
Here it is not required.
> > + */
> > +
> > +#include <fcntl.h>
> > +
> > +#include "igt.h"
> > +#include "lib/igt_syncobj.h"
> > +#include "lib/intel_reg.h"
> > +#include "lib/igt_perf.h"
> > +#include "xe_drm.h"
> > +
> > +#include "xe/xe_ioctl.h"
> > +#include "xe/xe_query.h"
> > +#include "xe/xe_spin.h"
> > +#include <string.h>
> Keep includes sorted alphabetically, also please put system includes first,
> then write one newline, then igt includes.
>
Will make the changes and send the new series.
> > +
> > +#define MAX_INSTANCE 9
> > +
> > +static uint64_t pmu_read(int fd)
> > +{
> > + uint64_t data[2];
> > +
> > + igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data));
> > +
> > + return data[0];
> > +}
> > +
> > +static int open_pmu(int fd, uint64_t config) {
> > + int perf_fd;
> > +
> > + perf_fd = perf_xe_open(fd, config);
> > + igt_skip_on(perf_fd < 0 && errno == ENODEV);
> > + igt_assert(perf_fd >= 0);
> > +
> > + return perf_fd;
> > +}
> > +
> > +static uint64_t engine_group_get_config(int gt, int class) {
> > + uint64_t config;
> > +
> > + switch (class) {
> > + case DRM_XE_ENGINE_CLASS_COPY:
> > + config = XE_PMU_COPY_GROUP_BUSY(gt);
> > + break;
> > + case DRM_XE_ENGINE_CLASS_RENDER:
> > + case DRM_XE_ENGINE_CLASS_COMPUTE:
> > + config = XE_PMU_RENDER_GROUP_BUSY(gt);
> > + break;
> > + case DRM_XE_ENGINE_CLASS_VIDEO_DECODE:
> > + case DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE:
> > + config = XE_PMU_MEDIA_GROUP_BUSY(gt);
> > + break;
> > + }
> > +
> > + return config;
> > +}
> > +
> > +/**
> > + * Test: Basic test for measure the active time when engine of any
> > +class active
> > + *
> > + * SUBTEST: any-engine-group-busy
> > + * Description:
> > + * Run a test to measure the global activity time by submitting
> > + * the WL to all existing engines.
> > + * Run type: FULL
> > + * TODO: change ``'Run type' == FULL`` to a better category */
> > +static void test_any_engine_busyness(int fd, struct
> > +drm_xe_engine_class_instance *eci) {
> > + uint32_t vm;
> > + uint64_t addr = 0x1a0000;
> > + struct drm_xe_sync sync[2] = {
> > + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
> },
> > + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
> },
> > + };
> > + struct drm_xe_exec exec = {
> > + .num_batch_buffer = 1,
> > + .num_syncs = 2,
> > + .syncs = to_user_pointer(sync),
> > + };
> > + uint32_t engine;
> > + uint32_t syncobj;
> > + size_t bo_size;
> > + uint32_t bo = 0;
> > + struct xe_spin *spin;
> > + uint32_t pmu_fd;
> > + uint64_t count, idle = 0;
> > +
> > + vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
> > + bo_size = sizeof(*spin);
> > + bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd),
> > + xe_get_default_alignment(fd));
> > +
> > + bo = xe_bo_create(fd, eci->gt_id, vm, bo_size);
> > + spin = xe_bo_map(fd, bo, bo_size);
> > +
> > + engine = xe_engine_create(fd, vm, eci, 0);
> > + syncobj = syncobj_create(fd, 0);
> > +
> > + sync[0].handle = syncobj_create(fd, 0);
> > + xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
> > +
> > + pmu_fd = open_pmu(fd, XE_PMU_ANY_ENGINE_GROUP_BUSY(eci-
> > >gt_id));
> > +
> > + xe_spin_init(spin, addr, false);
> > +
> > + sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
> > + sync[1].flags |= DRM_XE_SYNC_SIGNAL;
> > + sync[1].handle = syncobj;
> > +
> > + exec.engine_id = engine;
> > + exec.address = addr;
> > + xe_exec(fd, &exec);
> > +
> > + xe_spin_wait_started(spin);
> > + usleep(50000);
> > +
> > + igt_assert(!syncobj_wait(fd, &syncobj, 1, 1, 0, NULL));
> > + xe_spin_end(spin);
> > +
> > + igt_assert(syncobj_wait(fd, &syncobj, 1, INT64_MAX, 0, NULL));
> > + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0,
> > +NULL));
> > +
> > + sync[0].flags |= DRM_XE_SYNC_SIGNAL;
> > + xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
> > + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0,
> > +NULL));
> > +
> > + syncobj_destroy(fd, sync[0].handle);
> > + syncobj_destroy(fd, syncobj);
> > +
> > + count = pmu_read(pmu_fd);
> > + igt_assert_lt_u64(idle, count);
> > + igt_debug("Incrementing counter all-busy-group %ld ns\n", count);
> > +
> > + xe_engine_destroy(fd, engine);
> > + munmap(spin, bo_size);
> > + gem_close(fd, bo);
> > + xe_vm_destroy(fd, vm);
> > + close(pmu_fd);
> > +}
> > +
> > +/**
> > + * Test: Basic test for measure the active time across engine class
> > + *
> > + * SUBTEST: render-busy
> > + * Description:
> > + * Run a test to measure the active engine class time by submitting the
> > + * WL to all instances of a class
> > + * Run type: FULL
> > + * TODO: change ``'Run type' == FULL`` to a better category
> Remove TODO's these are not required now.
> Existing ones are removed by "tests/xe: remove an useless TODO message"
> > + *
> > + * SUBTEST: compute-busy
> > + * Description: Run copy-group-busy test
> > + * Run type: FULL
> > + * TODO: change ``'Run type' == FULL`` to a better category
> > + *
> > + * SUBTEST: copy-busy
> > + * Description: Run copy-group-busy test
> > + * Run type: FULL
> > + * TODO: change ``'Run type' == FULL`` to a better category
> > + *
> > + * SUBTEST: vcs-busy
> > + * Description: Run copy-group-busy test
> > + * Run type: FULL
> > + * TODO: change ``'Run type' == FULL`` to a better category
> > + *
> > + * SUBTEST: vecs-busy
> > + * Description: Run copy-group-busy test
> > + * Run type: FULL
> > + * TODO: change ``'Run type' == FULL`` to a better category
> > + *
> > + */
> > +
> > +static void test_engine_group_busyness(int fd, int gt, int class,
> > +const char *name) {
> > + uint32_t vm;
> > + uint64_t addr = 0x1a0000;
> > + struct drm_xe_sync sync[2] = {
> > + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
> },
> > + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
> },
> > + };
> > + struct drm_xe_exec exec = {
> > + .num_batch_buffer = 1,
> > + .num_syncs = 2,
> > + .syncs = to_user_pointer(sync),
> > + };
> > + uint32_t engines[MAX_INSTANCE];
> > + uint32_t syncobjs[MAX_INSTANCE];
> > + int pmu_fd;
> > + size_t bo_size;
> > + uint32_t bo = 0, i = 0;
> > + struct {
> > + struct xe_spin spin;
> > + } *data;
> > + struct drm_xe_engine_class_instance *hwe;
> > + struct drm_xe_engine_class_instance eci[MAX_INSTANCE];
> > + int num_placements = 0;
> > + uint64_t config, count, idle = 0;
> > +
> > + config = engine_group_get_config(gt, class);
> > +
> > + xe_for_each_hw_engine(fd, hwe) {
> > + if (hwe->engine_class != class || hwe->gt_id != gt)
> > + continue;
> > +
> > + eci[num_placements++] = *hwe;
> > + }
> > +
> > + if (!num_placements) {
> > + igt_info("Engine class:%d gt:%d not enabled on this
> > platform\n", class, gt);
> > + return;
> > + }
> > +
> > + vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
> > + bo_size = sizeof(*data) * num_placements;
> > + bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd),
> > +xe_get_default_alignment(fd));
> > +
> > + bo = xe_bo_create(fd, gt, vm, bo_size);
> > + data = xe_bo_map(fd, bo, bo_size);
> > +
> > + for (i = 0; i < num_placements; i++) {
> > + struct drm_xe_engine_create create = {
> > + .vm_id = vm,
> > + .width = 1,
> > + .num_placements = num_placements,
> > + .instances = to_user_pointer(eci),
> > + };
> > +
> > + igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_ENGINE_CREATE,
> > + &create), 0);
> > + engines[i] = create.engine_id;
> > + syncobjs[i] = syncobj_create(fd, 0);
> > + };
> > +
> > + sync[0].handle = syncobj_create(fd, 0);
> > + xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
> > +
> > + pmu_fd = open_pmu(fd, config);
> Pls check for engine idleness before submitting the workload.
>
Will add the idle code checks and send new series.
Thanks,
Venkat.
> Thanks,
> Rahul
> > +
> > + for (i = 0; i < num_placements; i++) {
> > + uint64_t spin_offset = (char *)&data[i].spin - (char *)data;
> > + uint64_t spin_addr = addr + spin_offset;
> > +
> > + xe_spin_init(&data[i].spin, spin_addr, false);
> > + sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
> > + sync[1].flags |= DRM_XE_SYNC_SIGNAL;
> > + sync[1].handle = syncobjs[i];
> > +
> > + exec.engine_id = engines[i];
> > + exec.address = spin_addr;
> > + xe_exec(fd, &exec);
> > + xe_spin_wait_started(&data[i].spin);
> > + }
> > +
> > + for (i = 0; i < num_placements; i++) {
> > + xe_spin_end(&data[i].spin);
> > + igt_assert(syncobj_wait(fd, &syncobjs[i], 1, INT64_MAX, 0,
> > + NULL));
> > + }
> > +
> > + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0,
> > +NULL));
> > +
> > + sync[0].flags |= DRM_XE_SYNC_SIGNAL;
> > + xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
> > + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0,
> > +NULL));
> > +
> > +
> > + syncobj_destroy(fd, sync[0].handle);
> > + for (i = 0; i < num_placements; i++) {
> > + syncobj_destroy(fd, syncobjs[i]);
> > + xe_engine_destroy(fd, engines[i]);
> > + }
> > +
> > + count = pmu_read(pmu_fd);
> > + igt_assert_lt_u64(idle, count);
> > + igt_debug("Incrementing counter %s-gt-%d %ld ns\n", name, gt,
> > +count);
> > +
> > + munmap(data, bo_size);
> > + gem_close(fd, bo);
> > + xe_vm_destroy(fd, vm);
> > + close(pmu_fd);
> > +}
> > +
> > +igt_main
> > +{
> > + struct drm_xe_engine_class_instance *hwe;
> > + const struct section {
> > + const char *name;
> > + int class;
> > + } sections[] = {
> > + { "render-busy", DRM_XE_ENGINE_CLASS_RENDER },
> > + { "compute-busy", DRM_XE_ENGINE_CLASS_COMPUTE },
> > + { "copy-busy", DRM_XE_ENGINE_CLASS_COPY },
> > + { "vcs-busy", DRM_XE_ENGINE_CLASS_VIDEO_DECODE },
> > + { "vecs-busy", DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE },
> > + { NULL },
> > + };
> > + int gt;
> > + int class;
> > + int fd;
> > +
> > + igt_fixture {
> > + fd = drm_open_driver(DRIVER_XE);
> > + xe_device_get(fd);
> > + }
> > +
> > + for (const struct section *s = sections; s->name; s++) {
> > + igt_subtest_f("%s", s->name)
> > + xe_for_each_gt(fd, gt)
> > + xe_for_each_hw_engine_class(class)
> > + if (class == s->class)
> > +
> > test_engine_group_busyness(fd, gt, class, s->name);
> > + }
> > +
> > + igt_subtest("any-engine-group-busy")
> > + xe_for_each_hw_engine(fd, hwe)
> > + test_any_engine_busyness(fd, hwe);
> > +
> > + igt_fixture {
> > + xe_device_put(fd);
> > + close(fd);
> > + }
> > +}
> > --
> > 2.25.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
@ 2023-10-06 5:15 priyanka.dandamudi
2023-10-06 7:30 ` [igt-dev] ✗ Fi.CI.BAT: failure for tests/xe/perf_pmu: Tests for the XE pmu interface (rev3) Patchwork
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: priyanka.dandamudi @ 2023-10-06 5:15 UTC (permalink / raw)
To: janga.rahul.kumar, igt-dev, priyanka.dandamudi
From: Venkata Ramana Nayana <venkata.ramana.nayana@intel.com>
There are set of engine group busyness counters provided by HW which are
exposed via PMU events. Adding a basic unit tests to read those counters.
v2: Added idle condition checks while reading the counters. (Rahul)
v3: Moved test from tests/xe/ location to tests/intel.
Modified code to work for xe_exec_queue_create xe_spin_init changes.
Cc: Janga Rahul Kumar <janga.rahul.kumar@intel.com>
Signed-off-by: Venkata Ramana Nayana <venkata.ramana.nayana@intel.com>
Signed-off-by: Priyanka Dandamudi <priyanka.dandamudi@intel.com>
---
include/drm-uapi/xe_drm.h | 22 +++
lib/igt_perf.c | 36 +++++
lib/igt_perf.h | 5 +
tests/intel/xe_perf_pmu.c | 331 ++++++++++++++++++++++++++++++++++++++
tests/meson.build | 1 +
5 files changed, 395 insertions(+)
create mode 100644 tests/intel/xe_perf_pmu.c
diff --git a/include/drm-uapi/xe_drm.h b/include/drm-uapi/xe_drm.h
index 804c02270..425b7d2b8 100644
--- a/include/drm-uapi/xe_drm.h
+++ b/include/drm-uapi/xe_drm.h
@@ -783,6 +783,28 @@ struct drm_xe_exec_queue_create {
__u64 reserved[2];
};
+/**
+ * DOC: perf_events exposed by xe through /sys/bus/event_sources/drivers/xe
+ *
+ */
+
+
+/* PMU event config IDs */
+
+/*
+ * Top 4 bits of every counter are GT id.
+ */
+#define __XE_PMU_GT_SHIFT (60)
+
+#define ___XE_PMU_OTHER(gt, x) \
+ (((__u64)(x)) | ((__u64)(gt) << __XE_PMU_GT_SHIFT))
+
+#define XE_PMU_INTERRUPTS(gt) ___XE_PMU_OTHER(gt, 0)
+#define XE_PMU_RENDER_GROUP_BUSY(gt) ___XE_PMU_OTHER(gt, 1)
+#define XE_PMU_COPY_GROUP_BUSY(gt) ___XE_PMU_OTHER(gt, 2)
+#define XE_PMU_MEDIA_GROUP_BUSY(gt) ___XE_PMU_OTHER(gt, 3)
+#define XE_PMU_ANY_ENGINE_GROUP_BUSY(gt) ___XE_PMU_OTHER(gt, 4)
+
struct drm_xe_exec_queue_get_property {
/** @extensions: Pointer to the first extension struct, if any */
__u64 extensions;
diff --git a/lib/igt_perf.c b/lib/igt_perf.c
index ffe078adc..3866c6d77 100644
--- a/lib/igt_perf.c
+++ b/lib/igt_perf.c
@@ -69,6 +69,36 @@ const char *i915_perf_device(int i915, char *buf, int buflen)
return buf;
}
+const char *xe_perf_device(int xe, char *buf, int buflen)
+{
+ char *s;
+ char pref[] = "xe_";
+ int len = strlen(pref);
+
+
+ if (!buf || buflen < len)
+ return "xe";
+
+ memcpy(buf, pref, len);
+
+ if (!bus_address(xe, buf + len, buflen - len))
+ buf[len - 1] = '\0';
+
+ /* Convert all colons in the address to '_', thanks perf! */
+ for (s = buf; *s; s++)
+ if (*s == ':')
+ *s = '_';
+
+ return buf;
+}
+
+uint64_t xe_perf_type_id(int xe)
+{
+ char buf[80];
+
+ return igt_perf_type_id(xe_perf_device(xe, buf, sizeof(buf)));
+}
+
uint64_t i915_perf_type_id(int i915)
{
char buf[80];
@@ -147,6 +177,12 @@ int perf_igfx_open_group(uint64_t config, int group)
PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP);
}
+int perf_xe_open(int xe, uint64_t config)
+{
+ return _perf_open(xe_perf_type_id(xe), config, -1,
+ PERF_FORMAT_TOTAL_TIME_ENABLED);
+}
+
int perf_i915_open(int i915, uint64_t config)
{
return _perf_open(i915_perf_type_id(i915), config, -1,
diff --git a/lib/igt_perf.h b/lib/igt_perf.h
index 4d86e31ae..3d9ba2917 100644
--- a/lib/igt_perf.h
+++ b/lib/igt_perf.h
@@ -61,10 +61,15 @@ int igt_perf_open_group(uint64_t type, uint64_t config, int group);
const char *i915_perf_device(int i915, char *buf, int buflen);
uint64_t i915_perf_type_id(int i915);
+const char *xe_perf_device(int xe, char *buf, int buflen);
+uint64_t xe_perf_type_id(int);
+
int perf_igfx_open(uint64_t config);
int perf_igfx_open_group(uint64_t config, int group);
int perf_i915_open(int i915, uint64_t config);
int perf_i915_open_group(int i915, uint64_t config, int group);
+int perf_xe_open(int xe, uint64_t config);
+
#endif /* I915_PERF_H */
diff --git a/tests/intel/xe_perf_pmu.c b/tests/intel/xe_perf_pmu.c
new file mode 100644
index 000000000..dc825f7f8
--- /dev/null
+++ b/tests/intel/xe_perf_pmu.c
@@ -0,0 +1,331 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+/**
+ * TEST: Basic tests for verify pmu perf interface
+ * Category: Hardware building block
+ * Sub-category: pmu interface
+ * Functionality: pmu
+ * Test category: functionality test
+ */
+
+#include <fcntl.h>
+#include <string.h>
+
+#include "igt.h"
+#include "lib/igt_syncobj.h"
+#include "lib/intel_reg.h"
+#include "lib/igt_perf.h"
+#include "xe_drm.h"
+#include "xe/xe_ioctl.h"
+#include "xe/xe_query.h"
+#include "xe/xe_spin.h"
+
+#define MAX_INSTANCE 9
+
+static uint64_t pmu_read(int fd)
+{
+ uint64_t data[2];
+
+ igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data));
+
+ return data[0];
+}
+
+static int open_pmu(int fd, uint64_t config)
+{
+ int perf_fd;
+
+ perf_fd = perf_xe_open(fd, config);
+ igt_skip_on(perf_fd < 0 && errno == ENODEV);
+ igt_assert(perf_fd >= 0);
+
+ return perf_fd;
+}
+
+static uint64_t engine_group_get_config(int gt, int class)
+{
+ uint64_t config;
+
+ switch (class) {
+ case DRM_XE_ENGINE_CLASS_COPY:
+ config = XE_PMU_COPY_GROUP_BUSY(gt);
+ break;
+ case DRM_XE_ENGINE_CLASS_RENDER:
+ case DRM_XE_ENGINE_CLASS_COMPUTE:
+ config = XE_PMU_RENDER_GROUP_BUSY(gt);
+ break;
+ case DRM_XE_ENGINE_CLASS_VIDEO_DECODE:
+ case DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE:
+ config = XE_PMU_MEDIA_GROUP_BUSY(gt);
+ break;
+ }
+
+ return config;
+}
+
+/**
+ * Test: Basic test for measure the active time when engine of any class active
+ *
+ * SUBTEST: any-engine-group-busy
+ * Description:
+ * Run a test to measure the global activity time by submitting
+ * the WL to all existing engines.
+ * Run type: FULL
+ *
+ */
+static void test_any_engine_busyness(int fd, struct drm_xe_engine_class_instance *eci)
+{
+ uint32_t vm;
+ uint64_t addr = 0x1a0000;
+ struct drm_xe_sync sync[2] = {
+ { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
+ { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
+ };
+ struct drm_xe_exec exec = {
+ .num_batch_buffer = 1,
+ .num_syncs = 2,
+ .syncs = to_user_pointer(sync),
+ };
+ uint32_t exec_queue;
+ uint32_t syncobj;
+ size_t bo_size;
+ uint32_t bo = 0;
+ struct xe_spin *spin;
+ struct xe_spin_opts spin_opts = { .addr = addr, .preempt = false };
+ uint32_t pmu_fd;
+ uint64_t count, idle;
+
+ vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
+ bo_size = sizeof(*spin);
+ bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd),
+ xe_get_default_alignment(fd));
+
+ bo = xe_bo_create(fd, eci->gt_id, vm, bo_size);
+ spin = xe_bo_map(fd, bo, bo_size);
+
+ exec_queue = xe_exec_queue_create(fd, vm, eci, 0);
+ syncobj = syncobj_create(fd, 0);
+
+ sync[0].handle = syncobj_create(fd, 0);
+ xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
+
+ pmu_fd = open_pmu(fd, XE_PMU_ANY_ENGINE_GROUP_BUSY(eci->gt_id));
+ idle = pmu_read(pmu_fd);
+ igt_assert(!idle);
+
+ xe_spin_init(spin, &spin_opts);
+
+ sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
+ sync[1].flags |= DRM_XE_SYNC_SIGNAL;
+ sync[1].handle = syncobj;
+
+ exec.exec_queue_id = exec_queue;
+ exec.address = addr;
+ xe_exec(fd, &exec);
+
+ xe_spin_wait_started(spin);
+ usleep(50000);
+
+ igt_assert(!syncobj_wait(fd, &syncobj, 1, 1, 0, NULL));
+ xe_spin_end(spin);
+
+ igt_assert(syncobj_wait(fd, &syncobj, 1, INT64_MAX, 0, NULL));
+ igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+ sync[0].flags |= DRM_XE_SYNC_SIGNAL;
+ xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
+ igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+ syncobj_destroy(fd, sync[0].handle);
+ syncobj_destroy(fd, syncobj);
+
+ count = pmu_read(pmu_fd);
+ igt_assert_lt_u64(idle, count);
+ igt_debug("Incrementing counter all-busy-group %ld ns\n", count);
+
+ xe_exec_queue_destroy(fd, exec_queue);
+ munmap(spin, bo_size);
+ gem_close(fd, bo);
+ xe_vm_destroy(fd, vm);
+ close(pmu_fd);
+}
+
+/**
+ * Test: Basic test for measure the active time across engine class
+ *
+ * SUBTEST: render-busy
+ * Description:
+ * Run a test to measure the active engine class time by submitting the
+ * WL to all instances of a class
+ * Run type: FULL
+ *
+ * SUBTEST: compute-busy
+ * Description: Run copy-group-busy test
+ * Run type: FULL
+ *
+ * SUBTEST: copy-busy
+ * Description: Run copy-group-busy test
+ * Run type: FULL
+ *
+ * SUBTEST: vcs-busy
+ * Description: Run copy-group-busy test
+ * Run type: FULL
+ *
+ * SUBTEST: vecs-busy
+ * Description: Run copy-group-busy test
+ * Run type: FULL
+ *
+ */
+
+static void test_engine_group_busyness(int fd, int gt, int class, const char *name)
+{
+ uint32_t vm;
+ uint64_t addr = 0x1a0000;
+ struct drm_xe_sync sync[2] = {
+ { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
+ { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL, },
+ };
+ struct drm_xe_exec exec = {
+ .num_batch_buffer = 1,
+ .num_syncs = 2,
+ .syncs = to_user_pointer(sync),
+ };
+ uint32_t exec_queues[MAX_INSTANCE];
+ uint32_t syncobjs[MAX_INSTANCE];
+ int pmu_fd;
+ size_t bo_size;
+ uint32_t bo = 0, i = 0;
+ struct {
+ struct xe_spin spin;
+ } *data;
+ struct xe_spin_opts spin_opts = { .addr = addr, .preempt = false };
+ struct drm_xe_engine_class_instance *hwe;
+ struct drm_xe_engine_class_instance eci[MAX_INSTANCE];
+ int num_placements = 0;
+ uint64_t config, count, idle;
+
+ config = engine_group_get_config(gt, class);
+
+ xe_for_each_hw_engine(fd, hwe) {
+ if (hwe->engine_class != class || hwe->gt_id != gt)
+ continue;
+
+ eci[num_placements++] = *hwe;
+ }
+
+ igt_skip_on_f(!num_placements, "Engine class:%d gt:%d not enabled on this platform\n",
+ class, gt);
+
+ vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
+ bo_size = sizeof(*data) * num_placements;
+ bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd), xe_get_default_alignment(fd));
+
+ bo = xe_bo_create(fd, gt, vm, bo_size);
+ data = xe_bo_map(fd, bo, bo_size);
+
+ for (i = 0; i < num_placements; i++) {
+ struct drm_xe_exec_queue_create create = {
+ .vm_id = vm,
+ .width = 1,
+ .num_placements = num_placements,
+ .instances = to_user_pointer(eci),
+ };
+
+ igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE,
+ &create), 0);
+ exec_queues[i] = create.exec_queue_id;
+ syncobjs[i] = syncobj_create(fd, 0);
+ };
+
+ sync[0].handle = syncobj_create(fd, 0);
+ xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
+
+ pmu_fd = open_pmu(fd, config);
+ idle = pmu_read(pmu_fd);
+ igt_assert(!idle);
+
+ for (i = 0; i < num_placements; i++) {
+ spin_opts.addr = addr + (char *)&data[i].spin - (char *)data;
+ xe_spin_init(&data[i].spin, &spin_opts);
+ sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
+ sync[1].flags |= DRM_XE_SYNC_SIGNAL;
+ sync[1].handle = syncobjs[i];
+
+ exec.exec_queue_id = exec_queues[i];
+ exec.address = spin_opts.addr;
+ xe_exec(fd, &exec);
+ xe_spin_wait_started(&data[i].spin);
+ }
+
+ for (i = 0; i < num_placements; i++) {
+ xe_spin_end(&data[i].spin);
+ igt_assert(syncobj_wait(fd, &syncobjs[i], 1, INT64_MAX, 0,
+ NULL));
+ }
+
+ igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+ sync[0].flags |= DRM_XE_SYNC_SIGNAL;
+ xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
+ igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+
+ syncobj_destroy(fd, sync[0].handle);
+ for (i = 0; i < num_placements; i++) {
+ syncobj_destroy(fd, syncobjs[i]);
+ xe_exec_queue_destroy(fd, exec_queues[i]);
+ }
+
+ count = pmu_read(pmu_fd);
+ igt_assert_lt_u64(idle, count);
+ igt_debug("Incrementing counter %s-gt-%d %ld ns\n", name, gt, count);
+
+ munmap(data, bo_size);
+ gem_close(fd, bo);
+ xe_vm_destroy(fd, vm);
+ close(pmu_fd);
+}
+
+igt_main
+{
+ struct drm_xe_engine_class_instance *hwe;
+ const struct section {
+ const char *name;
+ int class;
+ } sections[] = {
+ { "render-busy", DRM_XE_ENGINE_CLASS_RENDER },
+ { "compute-busy", DRM_XE_ENGINE_CLASS_COMPUTE },
+ { "copy-busy", DRM_XE_ENGINE_CLASS_COPY },
+ { "vcs-busy", DRM_XE_ENGINE_CLASS_VIDEO_DECODE },
+ { "vecs-busy", DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE },
+ { NULL },
+ };
+ int gt;
+ int class;
+ int fd;
+
+ igt_fixture {
+ fd = drm_open_driver(DRIVER_XE);
+ xe_device_get(fd);
+ }
+
+ for (const struct section *s = sections; s->name; s++) {
+ igt_subtest_f("%s", s->name)
+ xe_for_each_gt(fd, gt)
+ xe_for_each_hw_engine_class(class)
+ if (class == s->class)
+ test_engine_group_busyness(fd, gt, class, s->name);
+ }
+
+ igt_subtest("any-engine-group-busy")
+ xe_for_each_hw_engine(fd, hwe)
+ test_any_engine_busyness(fd, hwe);
+
+ igt_fixture {
+ xe_device_put(fd);
+ close(fd);
+ }
+}
diff --git a/tests/meson.build b/tests/meson.build
index 974cb433b..51773e9fa 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -299,6 +299,7 @@ intel_xe_progs = [
'xe_pm',
'xe_pm_residency',
'xe_prime_self_import',
+ 'xe_perf_pmu',
'xe_query',
'xe_sysfs_tile',
'xe_uevent',
--
2.25.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [igt-dev] ✗ Fi.CI.BAT: failure for tests/xe/perf_pmu: Tests for the XE pmu interface (rev3)
2023-10-06 5:15 [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface priyanka.dandamudi
@ 2023-10-06 7:30 ` Patchwork
2023-10-06 7:31 ` [igt-dev] ✓ CI.xeBAT: success " Patchwork
2023-10-06 9:31 ` [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface Kumar, Janga Rahul
2 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2023-10-06 7:30 UTC (permalink / raw)
To: Venkata Ramana Nayana; +Cc: igt-dev
[-- Attachment #1: Type: text/plain, Size: 10860 bytes --]
== Series Details ==
Series: tests/xe/perf_pmu: Tests for the XE pmu interface (rev3)
URL : https://patchwork.freedesktop.org/series/119936/
State : failure
== Summary ==
CI Bug Log - changes from IGT_7518 -> IGTPW_9936
====================================================
Summary
-------
**FAILURE**
Serious unknown changes coming with IGTPW_9936 absolutely need to be
verified manually.
If you think the reported changes have nothing to do with the changes
introduced in IGTPW_9936, please notify your bug team (lgci.bug.filing@intel.com) to allow them
to document this new failure mode, which will reduce false positives in CI.
External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/index.html
Participating hosts (39 -> 39)
------------------------------
Additional (1): bat-dg2-9
Missing (1): fi-snb-2520m
Possible new issues
-------------------
Here are the unknown changes that may have been introduced in IGTPW_9936:
### IGT changes ###
#### Possible regressions ####
* igt@gem_exec_suspend@basic-s3@smem:
- fi-skl-guc: [PASS][1] -> [ABORT][2]
[1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_7518/fi-skl-guc/igt@gem_exec_suspend@basic-s3@smem.html
[2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/fi-skl-guc/igt@gem_exec_suspend@basic-s3@smem.html
* igt@kms_pipe_crc_basic@suspend-read-crc@pipe-c-hdmi-a-3:
- bat-dg2-11: [PASS][3] -> [INCOMPLETE][4]
[3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_7518/bat-dg2-11/igt@kms_pipe_crc_basic@suspend-read-crc@pipe-c-hdmi-a-3.html
[4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-11/igt@kms_pipe_crc_basic@suspend-read-crc@pipe-c-hdmi-a-3.html
Known issues
------------
Here are the changes found in IGTPW_9936 that come from known issues:
### IGT changes ###
#### Issues hit ####
* igt@gem_lmem_swapping@random-engines:
- fi-bsw-n3050: NOTRUN -> [SKIP][5] ([fdo#109271]) +18 other tests skip
[5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/fi-bsw-n3050/igt@gem_lmem_swapping@random-engines.html
* igt@gem_mmap@basic:
- bat-dg2-9: NOTRUN -> [SKIP][6] ([i915#4083])
[6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@gem_mmap@basic.html
* igt@gem_mmap_gtt@basic:
- bat-dg2-9: NOTRUN -> [SKIP][7] ([i915#4077]) +2 other tests skip
[7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@gem_mmap_gtt@basic.html
* igt@gem_render_tiled_blits@basic:
- bat-dg2-9: NOTRUN -> [SKIP][8] ([i915#4079]) +1 other test skip
[8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@gem_render_tiled_blits@basic.html
* igt@i915_pm_rps@basic-api:
- bat-dg2-9: NOTRUN -> [SKIP][9] ([i915#6621])
[9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@i915_pm_rps@basic-api.html
* igt@i915_selftest@live@requests:
- bat-mtlp-8: [PASS][10] -> [ABORT][11] ([i915#9414])
[10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_7518/bat-mtlp-8/igt@i915_selftest@live@requests.html
[11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-mtlp-8/igt@i915_selftest@live@requests.html
* igt@kms_addfb_basic@addfb25-y-tiled-small-legacy:
- bat-dg2-9: NOTRUN -> [SKIP][12] ([i915#5190])
[12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_addfb_basic@addfb25-y-tiled-small-legacy.html
* igt@kms_addfb_basic@basic-y-tiled-legacy:
- bat-dg2-9: NOTRUN -> [SKIP][13] ([i915#4215] / [i915#5190])
[13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_addfb_basic@basic-y-tiled-legacy.html
* igt@kms_addfb_basic@framebuffer-vs-set-tiling:
- bat-dg2-9: NOTRUN -> [SKIP][14] ([i915#4212]) +6 other tests skip
[14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_addfb_basic@framebuffer-vs-set-tiling.html
* igt@kms_addfb_basic@tile-pitch-mismatch:
- bat-dg2-9: NOTRUN -> [SKIP][15] ([i915#4212] / [i915#5608])
[15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_addfb_basic@tile-pitch-mismatch.html
* igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
- bat-dg2-9: NOTRUN -> [SKIP][16] ([i915#4103] / [i915#4213] / [i915#5608]) +1 other test skip
[16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
* igt@kms_force_connector_basic@force-load-detect:
- bat-dg2-9: NOTRUN -> [SKIP][17] ([fdo#109285])
[17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_force_connector_basic@force-load-detect.html
* igt@kms_force_connector_basic@prune-stale-modes:
- bat-dg2-9: NOTRUN -> [SKIP][18] ([i915#5274])
[18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_force_connector_basic@prune-stale-modes.html
* igt@kms_hdmi_inject@inject-audio:
- fi-bsw-n3050: NOTRUN -> [FAIL][19] ([IGT#3])
[19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/fi-bsw-n3050/igt@kms_hdmi_inject@inject-audio.html
* igt@kms_pipe_crc_basic@nonblocking-crc-frame-sequence:
- bat-adlp-9: NOTRUN -> [SKIP][20] ([i915#3546]) +2 other tests skip
[20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-adlp-9/igt@kms_pipe_crc_basic@nonblocking-crc-frame-sequence.html
- bat-dg2-11: NOTRUN -> [SKIP][21] ([i915#1845]) +3 other tests skip
[21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-11/igt@kms_pipe_crc_basic@nonblocking-crc-frame-sequence.html
* igt@kms_pipe_crc_basic@read-crc-frame-sequence@pipe-c-dp-5:
- bat-adlp-11: [PASS][22] -> [ABORT][23] ([i915#8668] / [i915#9451])
[22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_7518/bat-adlp-11/igt@kms_pipe_crc_basic@read-crc-frame-sequence@pipe-c-dp-5.html
[23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-adlp-11/igt@kms_pipe_crc_basic@read-crc-frame-sequence@pipe-c-dp-5.html
* igt@kms_psr@sprite_plane_onoff:
- bat-dg2-9: NOTRUN -> [SKIP][24] ([i915#1072]) +3 other tests skip
[24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_psr@sprite_plane_onoff.html
* igt@kms_setmode@basic-clone-single-crtc:
- bat-dg2-9: NOTRUN -> [SKIP][25] ([i915#3555])
[25]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@kms_setmode@basic-clone-single-crtc.html
* igt@prime_vgem@basic-fence-flip:
- bat-dg2-9: NOTRUN -> [SKIP][26] ([i915#3708])
[26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@prime_vgem@basic-fence-flip.html
* igt@prime_vgem@basic-fence-mmap:
- bat-dg2-9: NOTRUN -> [SKIP][27] ([i915#3708] / [i915#4077]) +1 other test skip
[27]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@prime_vgem@basic-fence-mmap.html
* igt@prime_vgem@basic-write:
- bat-dg2-9: NOTRUN -> [SKIP][28] ([i915#3291] / [i915#3708]) +2 other tests skip
[28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-dg2-9/igt@prime_vgem@basic-write.html
#### Possible fixes ####
* igt@debugfs_test@read_all_entries:
- bat-adlp-11: [DMESG-WARN][29] ([i915#6868]) -> [PASS][30]
[29]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_7518/bat-adlp-11/igt@debugfs_test@read_all_entries.html
[30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-adlp-11/igt@debugfs_test@read_all_entries.html
* igt@i915_pm_rpm@module-reload:
- bat-atsm-1: [SKIP][31] -> [PASS][32]
[31]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_7518/bat-atsm-1/igt@i915_pm_rpm@module-reload.html
[32]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-atsm-1/igt@i915_pm_rpm@module-reload.html
* igt@kms_pipe_crc_basic@read-crc-frame-sequence@pipe-d-dp-5:
- bat-adlp-11: [ABORT][33] ([i915#8668]) -> [PASS][34]
[33]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_7518/bat-adlp-11/igt@kms_pipe_crc_basic@read-crc-frame-sequence@pipe-d-dp-5.html
[34]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/bat-adlp-11/igt@kms_pipe_crc_basic@read-crc-frame-sequence@pipe-d-dp-5.html
{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).
[IGT#3]: https://gitlab.freedesktop.org/drm/igt-gpu-tools/issues/3
[fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
[fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
[i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
[i915#1845]: https://gitlab.freedesktop.org/drm/intel/issues/1845
[i915#3291]: https://gitlab.freedesktop.org/drm/intel/issues/3291
[i915#3546]: https://gitlab.freedesktop.org/drm/intel/issues/3546
[i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
[i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
[i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
[i915#4079]: https://gitlab.freedesktop.org/drm/intel/issues/4079
[i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
[i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
[i915#4212]: https://gitlab.freedesktop.org/drm/intel/issues/4212
[i915#4213]: https://gitlab.freedesktop.org/drm/intel/issues/4213
[i915#4215]: https://gitlab.freedesktop.org/drm/intel/issues/4215
[i915#5190]: https://gitlab.freedesktop.org/drm/intel/issues/5190
[i915#5274]: https://gitlab.freedesktop.org/drm/intel/issues/5274
[i915#5354]: https://gitlab.freedesktop.org/drm/intel/issues/5354
[i915#5608]: https://gitlab.freedesktop.org/drm/intel/issues/5608
[i915#6621]: https://gitlab.freedesktop.org/drm/intel/issues/6621
[i915#6868]: https://gitlab.freedesktop.org/drm/intel/issues/6868
[i915#8668]: https://gitlab.freedesktop.org/drm/intel/issues/8668
[i915#9414]: https://gitlab.freedesktop.org/drm/intel/issues/9414
[i915#9451]: https://gitlab.freedesktop.org/drm/intel/issues/9451
Build changes
-------------
* CI: CI-20190529 -> None
* IGT: IGT_7518 -> IGTPW_9936
CI-20190529: 20190529
CI_DRM_13720: 299f698cf70fcb526dbd00faeb85b32ecce97334 @ git://anongit.freedesktop.org/gfx-ci/linux
IGTPW_9936: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/index.html
IGT_7518: 2d4a57e28db0c2ccbf8b2e763074c9aa74a1ae52 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
Testlist changes
----------------
+igt@xe_perf_pmu@any-engine-group-busy
+igt@xe_perf_pmu@compute-busy
+igt@xe_perf_pmu@copy-busy
+igt@xe_perf_pmu@render-busy
+igt@xe_perf_pmu@vcs-busy
+igt@xe_perf_pmu@vecs-busy
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/index.html
[-- Attachment #2: Type: text/html, Size: 12597 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* [igt-dev] ✓ CI.xeBAT: success for tests/xe/perf_pmu: Tests for the XE pmu interface (rev3)
2023-10-06 5:15 [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface priyanka.dandamudi
2023-10-06 7:30 ` [igt-dev] ✗ Fi.CI.BAT: failure for tests/xe/perf_pmu: Tests for the XE pmu interface (rev3) Patchwork
@ 2023-10-06 7:31 ` Patchwork
2023-10-06 9:31 ` [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface Kumar, Janga Rahul
2 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2023-10-06 7:31 UTC (permalink / raw)
To: Venkata Ramana Nayana; +Cc: igt-dev
[-- Attachment #1: Type: text/plain, Size: 4025 bytes --]
== Series Details ==
Series: tests/xe/perf_pmu: Tests for the XE pmu interface (rev3)
URL : https://patchwork.freedesktop.org/series/119936/
State : success
== Summary ==
CI Bug Log - changes from XEIGT_7518_BAT -> XEIGTPW_9936_BAT
====================================================
Summary
-------
**SUCCESS**
No regressions found.
Participating hosts (4 -> 4)
------------------------------
No changes in participating hosts
Known issues
------------
Here are the changes found in XEIGTPW_9936_BAT that come from known issues:
### IGT changes ###
#### Issues hit ####
* igt@kms_pipe_crc_basic@hang-read-crc:
- bat-dg2-oem2: [PASS][1] -> [TIMEOUT][2] ([Intel XE#430]) +1 other test timeout
[1]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_7518/bat-dg2-oem2/igt@kms_pipe_crc_basic@hang-read-crc.html
[2]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_9936/bat-dg2-oem2/igt@kms_pipe_crc_basic@hang-read-crc.html
* igt@kms_pipe_crc_basic@nonblocking-crc:
- bat-dg2-oem2: [PASS][3] -> [INCOMPLETE][4] ([Intel XE#545]) +1 other test incomplete
[3]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_7518/bat-dg2-oem2/igt@kms_pipe_crc_basic@nonblocking-crc.html
[4]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_9936/bat-dg2-oem2/igt@kms_pipe_crc_basic@nonblocking-crc.html
#### Possible fixes ####
* igt@kms_cursor_legacy@basic-flip-after-cursor-legacy:
- bat-dg2-oem2: [FAIL][5] ([Intel XE#773]) -> [PASS][6]
[5]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_7518/bat-dg2-oem2/igt@kms_cursor_legacy@basic-flip-after-cursor-legacy.html
[6]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_9936/bat-dg2-oem2/igt@kms_cursor_legacy@basic-flip-after-cursor-legacy.html
* {igt@xe_create@create-execqueues-noleak}:
- bat-adlp-7: [FAIL][7] ([Intel XE#524]) -> [PASS][8]
[7]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_7518/bat-adlp-7/igt@xe_create@create-execqueues-noleak.html
[8]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_9936/bat-adlp-7/igt@xe_create@create-execqueues-noleak.html
#### Warnings ####
* igt@kms_pipe_crc_basic@compare-crc-sanitycheck-nv12:
- bat-dg2-oem2: [FAIL][9] ([Intel XE#400]) -> [TIMEOUT][10] ([Intel XE#430] / [Intel XE#530])
[9]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_7518/bat-dg2-oem2/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-nv12.html
[10]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_9936/bat-dg2-oem2/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-nv12.html
* igt@kms_pipe_crc_basic@compare-crc-sanitycheck-nv12@pipe-b-dp-3:
- bat-dg2-oem2: [FAIL][11] ([Intel XE#400]) -> [TIMEOUT][12] ([Intel XE#530])
[11]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_7518/bat-dg2-oem2/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-nv12@pipe-b-dp-3.html
[12]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_9936/bat-dg2-oem2/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-nv12@pipe-b-dp-3.html
{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).
[Intel XE#400]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/400
[Intel XE#430]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/430
[Intel XE#524]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/524
[Intel XE#530]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/530
[Intel XE#545]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/545
[Intel XE#773]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/773
Build changes
-------------
* IGT: IGT_7518 -> IGTPW_9936
IGTPW_9936: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_9936/index.html
IGT_7518: 2d4a57e28db0c2ccbf8b2e763074c9aa74a1ae52 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
xe-417-b3daf7f07d6accbe43feafcadeb0b0498063761e: b3daf7f07d6accbe43feafcadeb0b0498063761e
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_9936/index.html
[-- Attachment #2: Type: text/html, Size: 4946 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
2023-10-06 5:15 [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface priyanka.dandamudi
2023-10-06 7:30 ` [igt-dev] ✗ Fi.CI.BAT: failure for tests/xe/perf_pmu: Tests for the XE pmu interface (rev3) Patchwork
2023-10-06 7:31 ` [igt-dev] ✓ CI.xeBAT: success " Patchwork
@ 2023-10-06 9:31 ` Kumar, Janga Rahul
2023-10-07 1:15 ` Dixit, Ashutosh
2 siblings, 1 reply; 8+ messages in thread
From: Kumar, Janga Rahul @ 2023-10-06 9:31 UTC (permalink / raw)
To: Dandamudi, Priyanka, igt-dev@lists.freedesktop.org
> -----Original Message-----
> From: Dandamudi, Priyanka <priyanka.dandamudi@intel.com>
> Sent: Friday, October 6, 2023 10:45 AM
> To: Kumar, Janga Rahul <janga.rahul.kumar@intel.com>; igt-
> dev@lists.freedesktop.org; Dandamudi, Priyanka
> <priyanka.dandamudi@intel.com>
> Subject: [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
>
> From: Venkata Ramana Nayana <venkata.ramana.nayana@intel.com>
>
> There are set of engine group busyness counters provided by HW which are
> exposed via PMU events. Adding a basic unit tests to read those counters.
>
> v2: Added idle condition checks while reading the counters. (Rahul)
>
> v3: Moved test from tests/xe/ location to tests/intel.
> Modified code to work for xe_exec_queue_create xe_spin_init changes.
>
> Cc: Janga Rahul Kumar <janga.rahul.kumar@intel.com>
> Signed-off-by: Venkata Ramana Nayana
> <venkata.ramana.nayana@intel.com>
> Signed-off-by: Priyanka Dandamudi <priyanka.dandamudi@intel.com>
Reviewed-by: Janga Rahul Kumar<janga.rahul.kumar@intel.com>
> ---
> include/drm-uapi/xe_drm.h | 22 +++
> lib/igt_perf.c | 36 +++++
> lib/igt_perf.h | 5 +
> tests/intel/xe_perf_pmu.c | 331
> ++++++++++++++++++++++++++++++++++++++
> tests/meson.build | 1 +
> 5 files changed, 395 insertions(+)
> create mode 100644 tests/intel/xe_perf_pmu.c
>
> diff --git a/include/drm-uapi/xe_drm.h b/include/drm-uapi/xe_drm.h index
> 804c02270..425b7d2b8 100644
> --- a/include/drm-uapi/xe_drm.h
> +++ b/include/drm-uapi/xe_drm.h
> @@ -783,6 +783,28 @@ struct drm_xe_exec_queue_create {
> __u64 reserved[2];
> };
>
> +/**
> + * DOC: perf_events exposed by xe through
> +/sys/bus/event_sources/drivers/xe
> + *
> + */
> +
> +
> +/* PMU event config IDs */
> +
> +/*
> + * Top 4 bits of every counter are GT id.
> + */
> +#define __XE_PMU_GT_SHIFT (60)
> +
> +#define ___XE_PMU_OTHER(gt, x) \
> + (((__u64)(x)) | ((__u64)(gt) << __XE_PMU_GT_SHIFT))
> +
> +#define XE_PMU_INTERRUPTS(gt)
> ___XE_PMU_OTHER(gt, 0)
> +#define XE_PMU_RENDER_GROUP_BUSY(gt)
> ___XE_PMU_OTHER(gt, 1)
> +#define XE_PMU_COPY_GROUP_BUSY(gt)
> ___XE_PMU_OTHER(gt, 2)
> +#define XE_PMU_MEDIA_GROUP_BUSY(gt)
> ___XE_PMU_OTHER(gt, 3)
> +#define XE_PMU_ANY_ENGINE_GROUP_BUSY(gt)
> ___XE_PMU_OTHER(gt, 4)
> +
> struct drm_xe_exec_queue_get_property {
> /** @extensions: Pointer to the first extension struct, if any */
> __u64 extensions;
> diff --git a/lib/igt_perf.c b/lib/igt_perf.c index ffe078adc..3866c6d77 100644
> --- a/lib/igt_perf.c
> +++ b/lib/igt_perf.c
> @@ -69,6 +69,36 @@ const char *i915_perf_device(int i915, char *buf, int
> buflen)
> return buf;
> }
>
> +const char *xe_perf_device(int xe, char *buf, int buflen) {
> + char *s;
> + char pref[] = "xe_";
> + int len = strlen(pref);
> +
> +
> + if (!buf || buflen < len)
> + return "xe";
> +
> + memcpy(buf, pref, len);
> +
> + if (!bus_address(xe, buf + len, buflen - len))
> + buf[len - 1] = '\0';
> +
> + /* Convert all colons in the address to '_', thanks perf! */
> + for (s = buf; *s; s++)
> + if (*s == ':')
> + *s = '_';
> +
> + return buf;
> +}
> +
> +uint64_t xe_perf_type_id(int xe)
> +{
> + char buf[80];
> +
> + return igt_perf_type_id(xe_perf_device(xe, buf, sizeof(buf))); }
> +
> uint64_t i915_perf_type_id(int i915)
> {
> char buf[80];
> @@ -147,6 +177,12 @@ int perf_igfx_open_group(uint64_t config, int group)
> PERF_FORMAT_TOTAL_TIME_ENABLED |
> PERF_FORMAT_GROUP); }
>
> +int perf_xe_open(int xe, uint64_t config) {
> + return _perf_open(xe_perf_type_id(xe), config, -1,
> + PERF_FORMAT_TOTAL_TIME_ENABLED);
> +}
> +
> int perf_i915_open(int i915, uint64_t config) {
> return _perf_open(i915_perf_type_id(i915), config, -1, diff --git
> a/lib/igt_perf.h b/lib/igt_perf.h index 4d86e31ae..3d9ba2917 100644
> --- a/lib/igt_perf.h
> +++ b/lib/igt_perf.h
> @@ -61,10 +61,15 @@ int igt_perf_open_group(uint64_t type, uint64_t
> config, int group); const char *i915_perf_device(int i915, char *buf, int
> buflen); uint64_t i915_perf_type_id(int i915);
>
> +const char *xe_perf_device(int xe, char *buf, int buflen); uint64_t
> +xe_perf_type_id(int);
> +
> int perf_igfx_open(uint64_t config);
> int perf_igfx_open_group(uint64_t config, int group);
>
> int perf_i915_open(int i915, uint64_t config); int perf_i915_open_group(int
> i915, uint64_t config, int group);
>
> +int perf_xe_open(int xe, uint64_t config);
> +
> #endif /* I915_PERF_H */
> diff --git a/tests/intel/xe_perf_pmu.c b/tests/intel/xe_perf_pmu.c new file
> mode 100644 index 000000000..dc825f7f8
> --- /dev/null
> +++ b/tests/intel/xe_perf_pmu.c
> @@ -0,0 +1,331 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +
> +/**
> + * TEST: Basic tests for verify pmu perf interface
> + * Category: Hardware building block
> + * Sub-category: pmu interface
> + * Functionality: pmu
> + * Test category: functionality test
> + */
> +
> +#include <fcntl.h>
> +#include <string.h>
> +
> +#include "igt.h"
> +#include "lib/igt_syncobj.h"
> +#include "lib/intel_reg.h"
> +#include "lib/igt_perf.h"
> +#include "xe_drm.h"
> +#include "xe/xe_ioctl.h"
> +#include "xe/xe_query.h"
> +#include "xe/xe_spin.h"
> +
> +#define MAX_INSTANCE 9
> +
> +static uint64_t pmu_read(int fd)
> +{
> + uint64_t data[2];
> +
> + igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data));
> +
> + return data[0];
> +}
> +
> +static int open_pmu(int fd, uint64_t config) {
> + int perf_fd;
> +
> + perf_fd = perf_xe_open(fd, config);
> + igt_skip_on(perf_fd < 0 && errno == ENODEV);
> + igt_assert(perf_fd >= 0);
> +
> + return perf_fd;
> +}
> +
> +static uint64_t engine_group_get_config(int gt, int class) {
> + uint64_t config;
> +
> + switch (class) {
> + case DRM_XE_ENGINE_CLASS_COPY:
> + config = XE_PMU_COPY_GROUP_BUSY(gt);
> + break;
> + case DRM_XE_ENGINE_CLASS_RENDER:
> + case DRM_XE_ENGINE_CLASS_COMPUTE:
> + config = XE_PMU_RENDER_GROUP_BUSY(gt);
> + break;
> + case DRM_XE_ENGINE_CLASS_VIDEO_DECODE:
> + case DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE:
> + config = XE_PMU_MEDIA_GROUP_BUSY(gt);
> + break;
> + }
> +
> + return config;
> +}
> +
> +/**
> + * Test: Basic test for measure the active time when engine of any
> +class active
> + *
> + * SUBTEST: any-engine-group-busy
> + * Description:
> + * Run a test to measure the global activity time by submitting
> + * the WL to all existing engines.
> + * Run type: FULL
> + *
> + */
> +static void test_any_engine_busyness(int fd, struct
> +drm_xe_engine_class_instance *eci) {
> + uint32_t vm;
> + uint64_t addr = 0x1a0000;
> + struct drm_xe_sync sync[2] = {
> + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
> },
> + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
> },
> + };
> + struct drm_xe_exec exec = {
> + .num_batch_buffer = 1,
> + .num_syncs = 2,
> + .syncs = to_user_pointer(sync),
> + };
> + uint32_t exec_queue;
> + uint32_t syncobj;
> + size_t bo_size;
> + uint32_t bo = 0;
> + struct xe_spin *spin;
> + struct xe_spin_opts spin_opts = { .addr = addr, .preempt = false };
> + uint32_t pmu_fd;
> + uint64_t count, idle;
> +
> + vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
> + bo_size = sizeof(*spin);
> + bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd),
> + xe_get_default_alignment(fd));
> +
> + bo = xe_bo_create(fd, eci->gt_id, vm, bo_size);
> + spin = xe_bo_map(fd, bo, bo_size);
> +
> + exec_queue = xe_exec_queue_create(fd, vm, eci, 0);
> + syncobj = syncobj_create(fd, 0);
> +
> + sync[0].handle = syncobj_create(fd, 0);
> + xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
> +
> + pmu_fd = open_pmu(fd, XE_PMU_ANY_ENGINE_GROUP_BUSY(eci-
> >gt_id));
> + idle = pmu_read(pmu_fd);
> + igt_assert(!idle);
> +
> + xe_spin_init(spin, &spin_opts);
> +
> + sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
> + sync[1].flags |= DRM_XE_SYNC_SIGNAL;
> + sync[1].handle = syncobj;
> +
> + exec.exec_queue_id = exec_queue;
> + exec.address = addr;
> + xe_exec(fd, &exec);
> +
> + xe_spin_wait_started(spin);
> + usleep(50000);
> +
> + igt_assert(!syncobj_wait(fd, &syncobj, 1, 1, 0, NULL));
> + xe_spin_end(spin);
> +
> + igt_assert(syncobj_wait(fd, &syncobj, 1, INT64_MAX, 0, NULL));
> + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> + sync[0].flags |= DRM_XE_SYNC_SIGNAL;
> + xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
> + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> + syncobj_destroy(fd, sync[0].handle);
> + syncobj_destroy(fd, syncobj);
> +
> + count = pmu_read(pmu_fd);
> + igt_assert_lt_u64(idle, count);
> + igt_debug("Incrementing counter all-busy-group %ld ns\n", count);
> +
> + xe_exec_queue_destroy(fd, exec_queue);
> + munmap(spin, bo_size);
> + gem_close(fd, bo);
> + xe_vm_destroy(fd, vm);
> + close(pmu_fd);
> +}
> +
> +/**
> + * Test: Basic test for measure the active time across engine class
> + *
> + * SUBTEST: render-busy
> + * Description:
> + * Run a test to measure the active engine class time by submitting the
> + * WL to all instances of a class
> + * Run type: FULL
> + *
> + * SUBTEST: compute-busy
> + * Description: Run copy-group-busy test
> + * Run type: FULL
> + *
> + * SUBTEST: copy-busy
> + * Description: Run copy-group-busy test
> + * Run type: FULL
> + *
> + * SUBTEST: vcs-busy
> + * Description: Run copy-group-busy test
> + * Run type: FULL
> + *
> + * SUBTEST: vecs-busy
> + * Description: Run copy-group-busy test
> + * Run type: FULL
> + *
> + */
> +
> +static void test_engine_group_busyness(int fd, int gt, int class, const
> +char *name) {
> + uint32_t vm;
> + uint64_t addr = 0x1a0000;
> + struct drm_xe_sync sync[2] = {
> + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
> },
> + { .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
> },
> + };
> + struct drm_xe_exec exec = {
> + .num_batch_buffer = 1,
> + .num_syncs = 2,
> + .syncs = to_user_pointer(sync),
> + };
> + uint32_t exec_queues[MAX_INSTANCE];
> + uint32_t syncobjs[MAX_INSTANCE];
> + int pmu_fd;
> + size_t bo_size;
> + uint32_t bo = 0, i = 0;
> + struct {
> + struct xe_spin spin;
> + } *data;
> + struct xe_spin_opts spin_opts = { .addr = addr, .preempt = false };
> + struct drm_xe_engine_class_instance *hwe;
> + struct drm_xe_engine_class_instance eci[MAX_INSTANCE];
> + int num_placements = 0;
> + uint64_t config, count, idle;
> +
> + config = engine_group_get_config(gt, class);
> +
> + xe_for_each_hw_engine(fd, hwe) {
> + if (hwe->engine_class != class || hwe->gt_id != gt)
> + continue;
> +
> + eci[num_placements++] = *hwe;
> + }
> +
> + igt_skip_on_f(!num_placements, "Engine class:%d gt:%d not enabled
> on this platform\n",
> + class, gt);
> +
> + vm = xe_vm_create(fd, DRM_XE_VM_CREATE_ASYNC_BIND_OPS, 0);
> + bo_size = sizeof(*data) * num_placements;
> + bo_size = ALIGN(bo_size + xe_cs_prefetch_size(fd),
> +xe_get_default_alignment(fd));
> +
> + bo = xe_bo_create(fd, gt, vm, bo_size);
> + data = xe_bo_map(fd, bo, bo_size);
> +
> + for (i = 0; i < num_placements; i++) {
> + struct drm_xe_exec_queue_create create = {
> + .vm_id = vm,
> + .width = 1,
> + .num_placements = num_placements,
> + .instances = to_user_pointer(eci),
> + };
> +
> + igt_assert_eq(igt_ioctl(fd,
> DRM_IOCTL_XE_EXEC_QUEUE_CREATE,
> + &create), 0);
> + exec_queues[i] = create.exec_queue_id;
> + syncobjs[i] = syncobj_create(fd, 0);
> + };
> +
> + sync[0].handle = syncobj_create(fd, 0);
> + xe_vm_bind_async(fd, vm, 0, bo, 0, addr, bo_size, sync, 1);
> +
> + pmu_fd = open_pmu(fd, config);
> + idle = pmu_read(pmu_fd);
> + igt_assert(!idle);
> +
> + for (i = 0; i < num_placements; i++) {
> + spin_opts.addr = addr + (char *)&data[i].spin - (char *)data;
> + xe_spin_init(&data[i].spin, &spin_opts);
> + sync[0].flags &= ~DRM_XE_SYNC_SIGNAL;
> + sync[1].flags |= DRM_XE_SYNC_SIGNAL;
> + sync[1].handle = syncobjs[i];
> +
> + exec.exec_queue_id = exec_queues[i];
> + exec.address = spin_opts.addr;
> + xe_exec(fd, &exec);
> + xe_spin_wait_started(&data[i].spin);
> + }
> +
> + for (i = 0; i < num_placements; i++) {
> + xe_spin_end(&data[i].spin);
> + igt_assert(syncobj_wait(fd, &syncobjs[i], 1, INT64_MAX, 0,
> + NULL));
> + }
> +
> + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> + sync[0].flags |= DRM_XE_SYNC_SIGNAL;
> + xe_vm_unbind_async(fd, vm, 0, 0, addr, bo_size, sync, 1);
> + igt_assert(syncobj_wait(fd, &sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> +
> + syncobj_destroy(fd, sync[0].handle);
> + for (i = 0; i < num_placements; i++) {
> + syncobj_destroy(fd, syncobjs[i]);
> + xe_exec_queue_destroy(fd, exec_queues[i]);
> + }
> +
> + count = pmu_read(pmu_fd);
> + igt_assert_lt_u64(idle, count);
> + igt_debug("Incrementing counter %s-gt-%d %ld ns\n", name, gt,
> count);
> +
> + munmap(data, bo_size);
> + gem_close(fd, bo);
> + xe_vm_destroy(fd, vm);
> + close(pmu_fd);
> +}
> +
> +igt_main
> +{
> + struct drm_xe_engine_class_instance *hwe;
> + const struct section {
> + const char *name;
> + int class;
> + } sections[] = {
> + { "render-busy", DRM_XE_ENGINE_CLASS_RENDER },
> + { "compute-busy", DRM_XE_ENGINE_CLASS_COMPUTE },
> + { "copy-busy", DRM_XE_ENGINE_CLASS_COPY },
> + { "vcs-busy", DRM_XE_ENGINE_CLASS_VIDEO_DECODE },
> + { "vecs-busy", DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE },
> + { NULL },
> + };
> + int gt;
> + int class;
> + int fd;
> +
> + igt_fixture {
> + fd = drm_open_driver(DRIVER_XE);
> + xe_device_get(fd);
> + }
> +
> + for (const struct section *s = sections; s->name; s++) {
> + igt_subtest_f("%s", s->name)
> + xe_for_each_gt(fd, gt)
> + xe_for_each_hw_engine_class(class)
> + if (class == s->class)
> +
> test_engine_group_busyness(fd, gt, class, s->name);
> + }
> +
> + igt_subtest("any-engine-group-busy")
> + xe_for_each_hw_engine(fd, hwe)
> + test_any_engine_busyness(fd, hwe);
> +
> + igt_fixture {
> + xe_device_put(fd);
> + close(fd);
> + }
> +}
> diff --git a/tests/meson.build b/tests/meson.build index
> 974cb433b..51773e9fa 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -299,6 +299,7 @@ intel_xe_progs = [
> 'xe_pm',
> 'xe_pm_residency',
> 'xe_prime_self_import',
> + 'xe_perf_pmu',
> 'xe_query',
> 'xe_sysfs_tile',
> 'xe_uevent',
> --
> 2.25.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
2023-10-06 9:31 ` [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface Kumar, Janga Rahul
@ 2023-10-07 1:15 ` Dixit, Ashutosh
0 siblings, 0 replies; 8+ messages in thread
From: Dixit, Ashutosh @ 2023-10-07 1:15 UTC (permalink / raw)
To: Kumar, Janga Rahul; +Cc: igt-dev@lists.freedesktop.org, venkata.ramana.nayana
On Fri, 06 Oct 2023 02:31:19 -0700, Kumar, Janga Rahul wrote:
>
Hi Priyanka,
> > From: Dandamudi, Priyanka <priyanka.dandamudi@intel.com>
> > Sent: Friday, October 6, 2023 10:45 AM
> > To: Kumar, Janga Rahul <janga.rahul.kumar@intel.com>; igt-
> > dev@lists.freedesktop.org; Dandamudi, Priyanka
> > <priyanka.dandamudi@intel.com>
> > Subject: [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface
> >
> > From: Venkata Ramana Nayana <venkata.ramana.nayana@intel.com>
> >
> > There are set of engine group busyness counters provided by HW which are
> > exposed via PMU events. Adding a basic unit tests to read those counters.
> >
> > v2: Added idle condition checks while reading the counters. (Rahul)
> >
> > v3: Moved test from tests/xe/ location to tests/intel.
> > Modified code to work for xe_exec_queue_create xe_spin_init changes.
> >
> > Cc: Janga Rahul Kumar <janga.rahul.kumar@intel.com>
> > Signed-off-by: Venkata Ramana Nayana
> > <venkata.ramana.nayana@intel.com>
> > Signed-off-by: Priyanka Dandamudi <priyanka.dandamudi@intel.com>
>
> Reviewed-by: Janga Rahul Kumar<janga.rahul.kumar@intel.com>
OK good that the original patch is reverted (though it should not have been
merged in the first place) so at least it fixed part the
drm_xe_exec_queue_get_property.
However this patch is still incorrect because you should do a 'make
headers_install' from the latest drm-xe-next kernel branch and then send
/that/ patch.
Ashutosh
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2023-10-07 1:15 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-06 5:15 [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface priyanka.dandamudi
2023-10-06 7:30 ` [igt-dev] ✗ Fi.CI.BAT: failure for tests/xe/perf_pmu: Tests for the XE pmu interface (rev3) Patchwork
2023-10-06 7:31 ` [igt-dev] ✓ CI.xeBAT: success " Patchwork
2023-10-06 9:31 ` [igt-dev] [PATCH] tests/xe/perf_pmu: Tests for the XE pmu interface Kumar, Janga Rahul
2023-10-07 1:15 ` Dixit, Ashutosh
-- strict thread matches above, loose matches on Subject: below --
2023-06-27 16:31 Venkata Ramana Nayana
2023-06-28 12:05 ` Kumar, Janga Rahul
2023-07-04 9:59 ` Nayana, Venkata Ramana
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox