* [PATCH i-g-t v2 0/3] tests/panthor: Add more tests
@ 2025-11-28 9:38 Boris Brezillon
2025-11-28 9:38 ` [PATCH i-g-t v2 1/3] drm-uapi/panthor: Sync panthor uapi Boris Brezillon
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Boris Brezillon @ 2025-11-28 9:38 UTC (permalink / raw)
To: igt-dev, Petri Latvala, Arkadiusz Hiler, Kamil Konieczny,
Juha-Pekka Heikkila, Bhanuprakash Modem
Cc: Boris Brezillon, Steven Price, Liviu Dudau, Adrián Larumbe,
Daniel Almeida, kernel
Hello,
Here's a bunch of tests that were developped while fixing different
bugs in panthor. I'm posting them before I forget.
v2:
- Add some docs
- Fix commit message
Regards,
Boris
Boris Brezillon (3):
drm-uapi/panthor: Sync panthor uapi
tests/panthor: Add a test to make sure the buffer is zeroed at alloc
time
tests/panthor: Add scheduler tests
include/drm-uapi/panthor_drm.h | 213 +++++++++++++++++----
lib/igt_panthor.c | 71 +++++++
lib/igt_panthor.h | 76 ++++++++
tests/panthor/meson.build | 1 +
tests/panthor/panthor_gem.c | 11 ++
tests/panthor/panthor_sched.c | 338 +++++++++++++++++++++++++++++++++
6 files changed, 668 insertions(+), 42 deletions(-)
create mode 100644 tests/panthor/panthor_sched.c
--
2.51.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH i-g-t v2 1/3] drm-uapi/panthor: Sync panthor uapi
2025-11-28 9:38 [PATCH i-g-t v2 0/3] tests/panthor: Add more tests Boris Brezillon
@ 2025-11-28 9:38 ` Boris Brezillon
2025-11-28 9:38 ` [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time Boris Brezillon
2025-11-28 9:38 ` [PATCH i-g-t v2 3/3] tests/panthor: Add scheduler tests Boris Brezillon
2 siblings, 0 replies; 10+ messages in thread
From: Boris Brezillon @ 2025-11-28 9:38 UTC (permalink / raw)
To: igt-dev, Petri Latvala, Arkadiusz Hiler, Kamil Konieczny,
Juha-Pekka Heikkila, Bhanuprakash Modem
Cc: Boris Brezillon, Steven Price, Liviu Dudau, Adrián Larumbe,
Daniel Almeida, kernel
Align with kernel commit 3b1dc21d6d80 ("drm/panthor: Add support for
Mali-Gx15 family of GPUs"). Will be needed for the scheduler tests.
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Kamil Konieczny <kamil.konieczny@linux.intel.com>
---
include/drm-uapi/panthor_drm.h | 213 ++++++++++++++++++++++++++-------
1 file changed, 171 insertions(+), 42 deletions(-)
diff --git a/include/drm-uapi/panthor_drm.h b/include/drm-uapi/panthor_drm.h
index e23a7f9b0eac..467d365ed7ba 100644
--- a/include/drm-uapi/panthor_drm.h
+++ b/include/drm-uapi/panthor_drm.h
@@ -127,50 +127,25 @@ enum drm_panthor_ioctl_id {
/** @DRM_PANTHOR_TILER_HEAP_DESTROY: Destroy a tiler heap. */
DRM_PANTHOR_TILER_HEAP_DESTROY,
+
+ /** @DRM_PANTHOR_BO_SET_LABEL: Label a BO. */
+ DRM_PANTHOR_BO_SET_LABEL,
+
+ /**
+ * @DRM_PANTHOR_SET_USER_MMIO_OFFSET: Set the offset to use as the user MMIO offset.
+ *
+ * The default behavior is to pick the MMIO offset based on the size of the pgoff_t
+ * type seen by the process that manipulates the FD, such that a 32-bit process can
+ * always map the user MMIO ranges. But this approach doesn't work well for emulators
+ * like FEX, where the emulator is an 64-bit binary which might be executing 32-bit
+ * code. In that case, the kernel thinks it's the 64-bit process and assumes
+ * DRM_PANTHOR_USER_MMIO_OFFSET_64BIT is in use, but the UMD library expects
+ * DRM_PANTHOR_USER_MMIO_OFFSET_32BIT, because it can't mmap() anything above the
+ * pgoff_t size.
+ */
+ DRM_PANTHOR_SET_USER_MMIO_OFFSET,
};
-/**
- * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number
- * @__access: Access type. Must be R, W or RW.
- * @__id: One of the DRM_PANTHOR_xxx id.
- * @__type: Suffix of the type being passed to the IOCTL.
- *
- * Don't use this macro directly, use the DRM_IOCTL_PANTHOR_xxx
- * values instead.
- *
- * Return: An IOCTL number to be passed to ioctl() from userspace.
- */
-#define DRM_IOCTL_PANTHOR(__access, __id, __type) \
- DRM_IO ## __access(DRM_COMMAND_BASE + DRM_PANTHOR_ ## __id, \
- struct drm_panthor_ ## __type)
-
-#define DRM_IOCTL_PANTHOR_DEV_QUERY \
- DRM_IOCTL_PANTHOR(WR, DEV_QUERY, dev_query)
-#define DRM_IOCTL_PANTHOR_VM_CREATE \
- DRM_IOCTL_PANTHOR(WR, VM_CREATE, vm_create)
-#define DRM_IOCTL_PANTHOR_VM_DESTROY \
- DRM_IOCTL_PANTHOR(WR, VM_DESTROY, vm_destroy)
-#define DRM_IOCTL_PANTHOR_VM_BIND \
- DRM_IOCTL_PANTHOR(WR, VM_BIND, vm_bind)
-#define DRM_IOCTL_PANTHOR_VM_GET_STATE \
- DRM_IOCTL_PANTHOR(WR, VM_GET_STATE, vm_get_state)
-#define DRM_IOCTL_PANTHOR_BO_CREATE \
- DRM_IOCTL_PANTHOR(WR, BO_CREATE, bo_create)
-#define DRM_IOCTL_PANTHOR_BO_MMAP_OFFSET \
- DRM_IOCTL_PANTHOR(WR, BO_MMAP_OFFSET, bo_mmap_offset)
-#define DRM_IOCTL_PANTHOR_GROUP_CREATE \
- DRM_IOCTL_PANTHOR(WR, GROUP_CREATE, group_create)
-#define DRM_IOCTL_PANTHOR_GROUP_DESTROY \
- DRM_IOCTL_PANTHOR(WR, GROUP_DESTROY, group_destroy)
-#define DRM_IOCTL_PANTHOR_GROUP_SUBMIT \
- DRM_IOCTL_PANTHOR(WR, GROUP_SUBMIT, group_submit)
-#define DRM_IOCTL_PANTHOR_GROUP_GET_STATE \
- DRM_IOCTL_PANTHOR(WR, GROUP_GET_STATE, group_get_state)
-#define DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE \
- DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create)
-#define DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY \
- DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy)
-
/**
* DOC: IOCTL arguments
*/
@@ -260,6 +235,14 @@ enum drm_panthor_dev_query_type {
/** @DRM_PANTHOR_DEV_QUERY_CSIF_INFO: Query command-stream interface information. */
DRM_PANTHOR_DEV_QUERY_CSIF_INFO,
+
+ /** @DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO: Query timestamp information. */
+ DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO,
+
+ /**
+ * @DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO: Query allowed group priorities information.
+ */
+ DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO,
};
/**
@@ -327,6 +310,9 @@ struct drm_panthor_gpu_info {
/** @as_present: Bitmask encoding the number of address-space exposed by the MMU. */
__u32 as_present;
+ /** @pad0: MBZ. */
+ __u32 pad0;
+
/** @shader_present: Bitmask encoding the shader cores exposed by the GPU. */
__u64 shader_present;
@@ -341,6 +327,9 @@ struct drm_panthor_gpu_info {
/** @pad: MBZ. */
__u32 pad;
+
+ /** @gpu_features: Bitmask describing supported GPU-wide features */
+ __u64 gpu_features;
};
/**
@@ -377,6 +366,42 @@ struct drm_panthor_csif_info {
__u32 pad;
};
+/**
+ * struct drm_panthor_timestamp_info - Timestamp information
+ *
+ * Structure grouping all queryable information relating to the GPU timestamp.
+ */
+struct drm_panthor_timestamp_info {
+ /**
+ * @timestamp_frequency: The frequency of the timestamp timer or 0 if
+ * unknown.
+ */
+ __u64 timestamp_frequency;
+
+ /** @current_timestamp: The current timestamp. */
+ __u64 current_timestamp;
+
+ /** @timestamp_offset: The offset of the timestamp timer. */
+ __u64 timestamp_offset;
+};
+
+/**
+ * struct drm_panthor_group_priorities_info - Group priorities information
+ *
+ * Structure grouping all queryable information relating to the allowed group priorities.
+ */
+struct drm_panthor_group_priorities_info {
+ /**
+ * @allowed_mask: Bitmask of the allowed group priorities.
+ *
+ * Each bit represents a variant of the enum drm_panthor_group_priority.
+ */
+ __u8 allowed_mask;
+
+ /** @pad: Padding fields, MBZ. */
+ __u8 pad[3];
+};
+
/**
* struct drm_panthor_dev_query - Arguments passed to DRM_PANTHOR_IOCTL_DEV_QUERY
*/
@@ -698,6 +723,13 @@ enum drm_panthor_group_priority {
* Requires CAP_SYS_NICE or DRM_MASTER.
*/
PANTHOR_GROUP_PRIORITY_HIGH,
+
+ /**
+ * @PANTHOR_GROUP_PRIORITY_REALTIME: Realtime priority group.
+ *
+ * Requires CAP_SYS_NICE or DRM_MASTER.
+ */
+ PANTHOR_GROUP_PRIORITY_REALTIME,
};
/**
@@ -872,6 +904,15 @@ enum drm_panthor_group_state_flags {
* When a group ends up with this flag set, no jobs can be submitted to its queues.
*/
DRM_PANTHOR_GROUP_STATE_FATAL_FAULT = 1 << 1,
+
+ /**
+ * @DRM_PANTHOR_GROUP_STATE_INNOCENT: Group was killed during a reset caused by other
+ * groups.
+ *
+ * This flag can only be set if DRM_PANTHOR_GROUP_STATE_TIMEDOUT is set and
+ * DRM_PANTHOR_GROUP_STATE_FATAL_FAULT is not.
+ */
+ DRM_PANTHOR_GROUP_STATE_INNOCENT = 1 << 2,
};
/**
@@ -959,6 +1000,94 @@ struct drm_panthor_tiler_heap_destroy {
__u32 pad;
};
+/**
+ * struct drm_panthor_bo_set_label - Arguments passed to DRM_IOCTL_PANTHOR_BO_SET_LABEL
+ */
+struct drm_panthor_bo_set_label {
+ /** @handle: Handle of the buffer object to label. */
+ __u32 handle;
+
+ /** @pad: MBZ. */
+ __u32 pad;
+
+ /**
+ * @label: User pointer to a NUL-terminated string
+ *
+ * Length cannot be greater than 4096
+ */
+ __u64 label;
+};
+
+/**
+ * struct drm_panthor_set_user_mmio_offset - Arguments passed to
+ * DRM_IOCTL_PANTHOR_SET_USER_MMIO_OFFSET
+ *
+ * This ioctl is only really useful if you want to support userspace
+ * CPU emulation environments where the size of an unsigned long differs
+ * between the host and the guest architectures.
+ */
+struct drm_panthor_set_user_mmio_offset {
+ /**
+ * @offset: User MMIO offset to use.
+ *
+ * Must be either DRM_PANTHOR_USER_MMIO_OFFSET_32BIT or
+ * DRM_PANTHOR_USER_MMIO_OFFSET_64BIT.
+ *
+ * Use DRM_PANTHOR_USER_MMIO_OFFSET (which selects OFFSET_32BIT or
+ * OFFSET_64BIT based on the size of an unsigned long) unless you
+ * have a very good reason to overrule this decision.
+ */
+ __u64 offset;
+};
+
+/**
+ * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number
+ * @__access: Access type. Must be R, W or RW.
+ * @__id: One of the DRM_PANTHOR_xxx id.
+ * @__type: Suffix of the type being passed to the IOCTL.
+ *
+ * Don't use this macro directly, use the DRM_IOCTL_PANTHOR_xxx
+ * values instead.
+ *
+ * Return: An IOCTL number to be passed to ioctl() from userspace.
+ */
+#define DRM_IOCTL_PANTHOR(__access, __id, __type) \
+ DRM_IO ## __access(DRM_COMMAND_BASE + DRM_PANTHOR_ ## __id, \
+ struct drm_panthor_ ## __type)
+
+enum {
+ DRM_IOCTL_PANTHOR_DEV_QUERY =
+ DRM_IOCTL_PANTHOR(WR, DEV_QUERY, dev_query),
+ DRM_IOCTL_PANTHOR_VM_CREATE =
+ DRM_IOCTL_PANTHOR(WR, VM_CREATE, vm_create),
+ DRM_IOCTL_PANTHOR_VM_DESTROY =
+ DRM_IOCTL_PANTHOR(WR, VM_DESTROY, vm_destroy),
+ DRM_IOCTL_PANTHOR_VM_BIND =
+ DRM_IOCTL_PANTHOR(WR, VM_BIND, vm_bind),
+ DRM_IOCTL_PANTHOR_VM_GET_STATE =
+ DRM_IOCTL_PANTHOR(WR, VM_GET_STATE, vm_get_state),
+ DRM_IOCTL_PANTHOR_BO_CREATE =
+ DRM_IOCTL_PANTHOR(WR, BO_CREATE, bo_create),
+ DRM_IOCTL_PANTHOR_BO_MMAP_OFFSET =
+ DRM_IOCTL_PANTHOR(WR, BO_MMAP_OFFSET, bo_mmap_offset),
+ DRM_IOCTL_PANTHOR_GROUP_CREATE =
+ DRM_IOCTL_PANTHOR(WR, GROUP_CREATE, group_create),
+ DRM_IOCTL_PANTHOR_GROUP_DESTROY =
+ DRM_IOCTL_PANTHOR(WR, GROUP_DESTROY, group_destroy),
+ DRM_IOCTL_PANTHOR_GROUP_SUBMIT =
+ DRM_IOCTL_PANTHOR(WR, GROUP_SUBMIT, group_submit),
+ DRM_IOCTL_PANTHOR_GROUP_GET_STATE =
+ DRM_IOCTL_PANTHOR(WR, GROUP_GET_STATE, group_get_state),
+ DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE =
+ DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create),
+ DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY =
+ DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy),
+ DRM_IOCTL_PANTHOR_BO_SET_LABEL =
+ DRM_IOCTL_PANTHOR(WR, BO_SET_LABEL, bo_set_label),
+ DRM_IOCTL_PANTHOR_SET_USER_MMIO_OFFSET =
+ DRM_IOCTL_PANTHOR(WR, SET_USER_MMIO_OFFSET, set_user_mmio_offset),
+};
+
#if defined(__cplusplus)
}
#endif
--
2.51.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time
2025-11-28 9:38 [PATCH i-g-t v2 0/3] tests/panthor: Add more tests Boris Brezillon
2025-11-28 9:38 ` [PATCH i-g-t v2 1/3] drm-uapi/panthor: Sync panthor uapi Boris Brezillon
@ 2025-11-28 9:38 ` Boris Brezillon
2025-12-01 11:14 ` Kamil Konieczny
2025-11-28 9:38 ` [PATCH i-g-t v2 3/3] tests/panthor: Add scheduler tests Boris Brezillon
2 siblings, 1 reply; 10+ messages in thread
From: Boris Brezillon @ 2025-11-28 9:38 UTC (permalink / raw)
To: igt-dev, Petri Latvala, Arkadiusz Hiler, Kamil Konieczny,
Juha-Pekka Heikkila, Bhanuprakash Modem
Cc: Boris Brezillon, Steven Price, Liviu Dudau, Adrián Larumbe,
Daniel Almeida, kernel
This covering for this bug [1]. Add an IGT test to make sure we don't
hit that again.
[1]https://lore.kernel.org/20251107171214.1186299-1-boris.brezillon@collabora.com
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Kamil Konieczny <kamil.konieczny@linux.intel.com>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
---
tests/panthor/panthor_gem.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tests/panthor/panthor_gem.c b/tests/panthor/panthor_gem.c
index 57cd97e809fd..1566c713f876 100644
--- a/tests/panthor/panthor_gem.c
+++ b/tests/panthor/panthor_gem.c
@@ -66,6 +66,17 @@ igt_main {
igt_panthor_free_bo(fd, &bo);
}
+ igt_describe_f("Check zero-ing of buffer at creation time");
+ igt_subtest("bo_zeroed") {
+ struct panthor_bo bo;
+
+ igt_panthor_bo_create_mapped(fd, &bo, getpagesize(), 0, 0);
+ igt_assert(bo.map);
+ igt_assert_eq(*((uint32_t *)bo.map), 0);
+
+ igt_panthor_free_bo(fd, &bo);
+ }
+
igt_fixture {
drm_close_driver(fd);
}
--
2.51.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH i-g-t v2 3/3] tests/panthor: Add scheduler tests
2025-11-28 9:38 [PATCH i-g-t v2 0/3] tests/panthor: Add more tests Boris Brezillon
2025-11-28 9:38 ` [PATCH i-g-t v2 1/3] drm-uapi/panthor: Sync panthor uapi Boris Brezillon
2025-11-28 9:38 ` [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time Boris Brezillon
@ 2025-11-28 9:38 ` Boris Brezillon
2025-12-03 19:31 ` Daniel Almeida
2 siblings, 1 reply; 10+ messages in thread
From: Boris Brezillon @ 2025-11-28 9:38 UTC (permalink / raw)
To: igt-dev, Petri Latvala, Arkadiusz Hiler, Kamil Konieczny,
Juha-Pekka Heikkila, Bhanuprakash Modem
Cc: Boris Brezillon, Steven Price, Liviu Dudau, Adrián Larumbe,
Daniel Almeida, kernel
Tests developed while working on this set of fixes [1].
[1]https://lore.kernel.org/all/20251112115142.1270931-1-boris.brezillon@collabora.com/
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
lib/igt_panthor.c | 71 +++++++
lib/igt_panthor.h | 76 ++++++++
tests/panthor/meson.build | 1 +
tests/panthor/panthor_sched.c | 338 ++++++++++++++++++++++++++++++++++
4 files changed, 486 insertions(+)
create mode 100644 tests/panthor/panthor_sched.c
diff --git a/lib/igt_panthor.c b/lib/igt_panthor.c
index 73ada9c59bfc..802cb182753c 100644
--- a/lib/igt_panthor.c
+++ b/lib/igt_panthor.c
@@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd.
#include "drmtest.h"
+#include "igt_aux.h"
#include "igt_panthor.h"
#include "ioctl_wrappers.h"
#include "panthor_drm.h"
@@ -370,3 +371,73 @@ void igt_panthor_free_bo(int fd, struct panthor_bo *bo)
gem_close(fd, bo->handle);
}
+
+/**
+ * igt_panthor_ctx_create:
+ * @fd: panthor device file descriptor
+ * @ctx: context to initialize
+ *
+ * Creates base resources (VM and GPU info) needed for GPU job submission
+ */
+void igt_panthor_ctx_create(int fd, struct panthor_ctx *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ igt_panthor_query(fd, DRM_PANTHOR_DEV_QUERY_GPU_INFO,
+ &ctx->gpu_info, sizeof(ctx->gpu_info), 0);
+ igt_panthor_vm_create(fd, &ctx->vm, 0);
+}
+
+/**
+ * igt_panthor_ctx_destroy:
+ * @fd: panthor device file descriptor
+ * @ctx: context to cleanup
+ *
+ * Releases all the resources attached to a GPU context.
+ */
+void igt_panthor_ctx_destroy(int fd, struct panthor_ctx *ctx)
+{
+ for (uint32_t i = 0; i < ctx->group_count; i++) {
+ struct drm_panthor_group_destroy group_destroy = {
+ .group_handle = ctx->groups[i],
+ };
+
+ igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_PANTHOR_GROUP_DESTROY, &group_destroy), 0);
+ }
+
+ igt_panthor_vm_destroy(fd, ctx->vm, 0);
+}
+
+/**
+ * igt_panthor_ctx_add_group:
+ * @fd: panthor device file descriptor
+ * @ctx: context to add a group to
+ * @group_prio: group priority
+ * @queues: properties of queues attached to the group
+ * @queue_count: number of queues attached to the group
+ *
+ * Adds a group to a GPU context. Such groups will be released when
+ * the context is destroyed.
+ */
+void igt_panthor_ctx_add_group(int fd, struct panthor_ctx *ctx,
+ enum drm_panthor_group_priority group_prio,
+ const struct drm_panthor_queue_create *queues,
+ uint32_t queue_count)
+{
+ unsigned int shader_core_count = igt_hweight(ctx->gpu_info.shader_present);
+ struct drm_panthor_group_create group_create = {
+ .queues = DRM_PANTHOR_OBJ_ARRAY(queue_count, queues),
+ .max_compute_cores = shader_core_count,
+ .max_fragment_cores = shader_core_count,
+ .max_tiler_cores = 1,
+ .priority = group_prio,
+ .compute_core_mask = ctx->gpu_info.shader_present,
+ .fragment_core_mask = ctx->gpu_info.shader_present,
+ .tiler_core_mask = ctx->gpu_info.tiler_present,
+ .vm_id = ctx->vm,
+ };
+
+ igt_assert(ctx->group_count < ARRAY_SIZE(ctx->groups));
+ igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_PANTHOR_GROUP_CREATE, &group_create), 0);
+ igt_assert(group_create.group_handle > 0);
+ ctx->groups[ctx->group_count++] = group_create.group_handle;
+}
diff --git a/lib/igt_panthor.h b/lib/igt_panthor.h
index dc90033c0ad4..2a62eff37b2b 100644
--- a/lib/igt_panthor.h
+++ b/lib/igt_panthor.h
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
+
#include "panthor_drm.h"
struct panthor_bo {
@@ -16,7 +17,17 @@ struct panthor_bo {
void *map;
};
+#define MAX_GROUPS_PER_CTX 128
+
+struct panthor_ctx {
+ struct drm_panthor_gpu_info gpu_info;
+ uint32_t vm;
+ uint32_t group_count;
+ uint32_t groups[MAX_GROUPS_PER_CTX];
+};
+
void igt_panthor_query(int fd, int32_t type, void *data, size_t size, int err);
+
void igt_panthor_vm_create(int fd, uint32_t *vm_id, int err);
void igt_panthor_vm_destroy(int fd, uint32_t vm_id, int err);
void igt_panthor_vm_bind(int fd, uint32_t vm_id, uint32_t bo_handle, uint64_t va,
@@ -38,12 +49,21 @@ void igt_panthor_group_submit_simple(int fd, uint32_t group_handle,
int err);
uint64_t igt_panthor_get_first_core(uint64_t cores_present);
+void igt_panthor_ctx_create(int fd, struct panthor_ctx *ctx);
+void igt_panthor_ctx_destroy(int fd, struct panthor_ctx *ctx);
+void igt_panthor_ctx_add_group(int fd, struct panthor_ctx *ctx,
+ enum drm_panthor_group_priority group_prio,
+ const struct drm_panthor_queue_create *queues,
+ uint32_t queue_count);
+
enum cs_opcode {
CS_OPCODE_NOP = 0,
CS_OPCODE_MOVE48 = 1,
CS_OPCODE_MOVE32 = 2,
CS_OPCODE_WAIT = 3,
+ CS_OPCODE_ADD64 = 17,
CS_OPCODE_STM = 21,
+ CS_OPCODE_BRANCH = 22,
CS_OPCODE_FLUSH_CACHE = 36,
};
@@ -61,6 +81,16 @@ enum cs_flush_mode {
#error "big endian not supported"
#endif
+enum cs_branch_cond {
+ CS_BRANCH_COND_LE = 0,
+ CS_BRANCH_COND_GT = 1,
+ CS_BRANCH_COND_EQ = 2,
+ CS_BRANCH_COND_NE = 3,
+ CS_BRANCH_COND_LT = 4,
+ CS_BRANCH_COND_GE = 5,
+ CS_BRANCH_COND_ALWAYS = 6,
+};
+
struct cs_instr {
union {
struct {
@@ -89,6 +119,13 @@ struct cs_instr {
uint64_t unused1: 23;
uint64_t opcode: 8;
} wait;
+ struct {
+ uint64_t immediate: 32;
+ uint64_t unused0: 8;
+ uint64_t src: 8;
+ uint64_t dst: 8;
+ uint64_t opcode: 8;
+ } add64;
struct {
uint64_t offset: 16;
uint64_t mask: 16;
@@ -97,6 +134,15 @@ struct cs_instr {
uint64_t src: 8;
uint64_t opcode: 8;
} stm;
+ struct {
+ uint64_t offset: 16;
+ uint64_t unused0: 12;
+ uint64_t cond: 4;
+ uint64_t unused1: 8;
+ uint64_t src: 8;
+ uint64_t unused2: 8;
+ uint64_t opcode: 8;
+ } branch;
struct {
uint64_t l2_mode: 4;
uint64_t lsc_mode: 4;
@@ -167,6 +213,21 @@ cs_wait(uint16_t wait_mask, bool progress_inc)
return instr.raw;
}
+static inline uint64_t
+cs_add64(uint32_t imm, uint8_t src, uint8_t dst)
+{
+ struct cs_instr instr = {
+ .add64 = {
+ .immediate = imm,
+ .src = src,
+ .dst = dst,
+ .opcode = CS_OPCODE_ADD64,
+ },
+ };
+
+ return instr.raw;
+}
+
static inline uint64_t
cs_stm(uint8_t address, uint8_t src, uint16_t mask, int16_t offset)
{
@@ -195,6 +256,21 @@ cs_stm64(uint8_t address, uint8_t src, int16_t offset)
return cs_stm(address, src, 0x3, offset);
}
+static inline uint64_t
+cs_branch(int16_t offset, enum cs_branch_cond cond, uint8_t src)
+{
+ struct cs_instr instr = {
+ .branch = {
+ .offset = (uint16_t)offset,
+ .cond = cond,
+ .src = src,
+ .opcode = CS_OPCODE_BRANCH,
+ },
+ };
+
+ return instr.raw;
+}
+
static inline uint64_t
cs_flush(enum cs_flush_mode l2_mode,
enum cs_flush_mode lsc_mode,
diff --git a/tests/panthor/meson.build b/tests/panthor/meson.build
index 42a46e9934a9..8bd391596a97 100644
--- a/tests/panthor/meson.build
+++ b/tests/panthor/meson.build
@@ -2,6 +2,7 @@ panthor_progs = [
'panthor_gem',
'panthor_group',
'panthor_query',
+ 'panthor_sched',
'panthor_vm',
]
diff --git a/tests/panthor/panthor_sched.c b/tests/panthor/panthor_sched.c
new file mode 100644
index 000000000000..7cded16c0acd
--- /dev/null
+++ b/tests/panthor/panthor_sched.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd.
+
+#include <stdint.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "drm.h"
+#include "igt.h"
+#include "igt_core.h"
+#include "igt_panthor.h"
+#include "panthor_drm.h"
+
+static size_t
+infinite_incr_loop(uint64_t *cs, uint64_t counter_va)
+{
+ const uint8_t counter_va_reg = 68;
+ const uint8_t val_reg = 70;
+ uint64_t instrs[] = {
+ /* Load the source register ([r68; r69]) with the kernel address */
+ cs_mov48(counter_va_reg, counter_va),
+ /* Load a 0 into r70 */
+ cs_mov48(val_reg, 1),
+ /* STORE_MULTIPLE: Store the first register to the address pointed to by
+ * [r68; r69]
+ */
+ cs_stm64(counter_va_reg, val_reg, 0),
+ cs_wait(1, false),
+ cs_add64(1, val_reg, val_reg),
+ cs_branch(-4, CS_BRANCH_COND_ALWAYS, 0),
+ };
+
+ memcpy(cs, instrs, sizeof(instrs));
+ return sizeof(instrs);
+}
+
+struct panthor_sched_test_group_ctx {
+ uint32_t handle;
+ uint64_t *counter;
+ uint64_t cs_va;
+ uint32_t cs_size;
+};
+
+#define MAX_GROUPS 128
+
+struct panthor_sched_test_ctx {
+ struct panthor_ctx ctx;
+ struct panthor_bo cs_bo;
+ uint32_t cs_bo_offset;
+ struct panthor_bo counter_bo;
+ uint32_t counter_bo_offset;
+ uint32_t group_count;
+ struct panthor_sched_test_group_ctx groups[MAX_GROUPS];
+};
+
+#define CS_BO_VA 0x100000
+#define COUNTER_BO_VA 0x200000
+
+static void
+sched_test_ctx_create(int fd, struct panthor_sched_test_ctx *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ igt_panthor_ctx_create(fd, &ctx->ctx);
+ igt_panthor_bo_create_mapped(fd, &ctx->cs_bo, getpagesize(), 0, 0);
+ igt_panthor_vm_bind(fd, ctx->ctx.vm, ctx->cs_bo.handle, CS_BO_VA, ctx->cs_bo.size,
+ DRM_PANTHOR_VM_BIND_OP_MAP_READONLY |
+ DRM_PANTHOR_VM_BIND_OP_TYPE_MAP,
+ 0);
+ igt_panthor_bo_create_mapped(fd, &ctx->counter_bo, getpagesize(), 0, 0);
+ igt_panthor_vm_bind(fd, ctx->ctx.vm, ctx->counter_bo.handle, COUNTER_BO_VA,
+ ctx->counter_bo.size,
+ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED |
+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
+ DRM_PANTHOR_VM_BIND_OP_TYPE_MAP,
+ 0);
+}
+
+static void
+sched_test_ctx_destroy(int fd, struct panthor_sched_test_ctx *ctx)
+{
+ igt_panthor_ctx_destroy(fd, &ctx->ctx);
+}
+
+static void
+sched_test_ctx_add_group(int fd, struct panthor_sched_test_ctx *ctx,
+ enum drm_panthor_group_priority group_prio)
+{
+ struct drm_panthor_queue_create queue_create = {
+ .priority = 0,
+ .ringbuf_size = getpagesize(),
+ };
+ uint64_t *cs = (uint64_t *)((uint8_t *)ctx->cs_bo.map + ctx->cs_bo_offset);
+ uint64_t *counters = ctx->counter_bo.map;
+ unsigned int group_idx = ctx->group_count;
+ uint64_t counter_va = COUNTER_BO_VA + group_idx * sizeof(counters[0]);
+ unsigned int cs_size;
+
+ igt_assert_lt(ctx->group_count, ARRAY_SIZE(ctx->groups));
+
+ igt_panthor_ctx_add_group(fd, &ctx->ctx, group_prio, &queue_create, 1);
+ cs_size = infinite_incr_loop(cs, counter_va);
+ cs_size = ALIGN(cs_size, 64);
+ ctx->groups[ctx->group_count++] = (struct panthor_sched_test_group_ctx){
+ .handle = ctx->ctx.groups[group_idx],
+ .counter = &counters[group_idx],
+ .cs_va = CS_BO_VA + ctx->cs_bo_offset,
+ .cs_size = cs_size,
+ };
+
+ ctx->cs_bo_offset += cs_size;
+ igt_assert_lt(ctx->cs_bo_offset, ctx->cs_bo.size);
+}
+
+static void
+sched_test_ctx_submit_group(int fd, struct panthor_sched_test_ctx *ctx,
+ unsigned int group_idx)
+{
+ struct drm_panthor_queue_submit qsubmit = {
+ .queue_index = 0,
+ .stream_size = ctx->groups[group_idx].cs_size,
+ .stream_addr = ctx->groups[group_idx].cs_va,
+ .latest_flush = 0,
+ };
+ struct drm_panthor_group_submit gsubmit = {
+ .group_handle = ctx->groups[group_idx].handle,
+ .queue_submits = DRM_PANTHOR_OBJ_ARRAY(1, &qsubmit),
+ };
+
+ igt_assert_lt(group_idx, ctx->group_count);
+ igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_PANTHOR_GROUP_SUBMIT, &gsubmit), 0);
+}
+
+igt_main {
+ int fd;
+
+ igt_fixture {
+ fd = drm_open_driver(DRIVER_PANTHOR);
+ }
+
+ igt_describe("Schedule 8 groups with the same prio");
+ igt_subtest("sched_8_groups_same_prio") {
+ uint64_t min_cnt = UINT64_MAX, max_cnt = 0;
+ struct panthor_sched_test_ctx ctx;
+ const unsigned int group_cnt = 8;
+
+ sched_test_ctx_create(fd, &ctx);
+
+ for (unsigned int i = 0; i < group_cnt; i++)
+ sched_test_ctx_add_group(fd, &ctx, PANTHOR_GROUP_PRIORITY_MEDIUM);
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ sched_test_ctx_submit_group(fd, &ctx, i);
+
+ /* Add some delay, to make sure each group becomes
+ * active at a different time, and exercise the
+ * idle -> active transition that appeared to be
+ * broken at some point.
+ */
+ usleep(100000);
+ }
+
+ /* Jobs will timeout, because we've issued an infinte loop,
+ * but leave it some time before checking the counter
+ * values.
+ */
+ sleep(6);
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ min_cnt = min(min_cnt, *ctx.groups[i].counter);
+ max_cnt = max(max_cnt, *ctx.groups[i].counter);
+ }
+
+ igt_assert_lt(200000, min_cnt);
+ igt_assert_lte(min_cnt, max_cnt);
+
+ /* Allow a 20% difference max? */
+ igt_assert_lt((((max_cnt - min_cnt) * 100) / min_cnt), 20);
+
+ sched_test_ctx_destroy(fd, &ctx);
+ }
+
+ igt_describe("Schedule 16 groups with the same prio");
+ igt_subtest("sched_16_groups_same_prio") {
+ uint64_t min_cnt = UINT64_MAX, max_cnt = 0;
+ struct panthor_sched_test_ctx ctx;
+ const unsigned int group_cnt = 16;
+
+ sched_test_ctx_create(fd, &ctx);
+
+ for (unsigned int i = 0; i < group_cnt; i++)
+ sched_test_ctx_add_group(fd, &ctx, PANTHOR_GROUP_PRIORITY_MEDIUM);
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ sched_test_ctx_submit_group(fd, &ctx, i);
+
+ /* Add some delay, to make sure each group becomes
+ * active at a different time, and exercise the
+ * idle -> active transition that appeared to be
+ * broken at some point.
+ */
+ usleep(100000);
+ }
+
+ /* Jobs will timeout, because we've issued an infinte loop,
+ * but leave it some time before checking the counter
+ * values.
+ */
+ sleep(15);
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ min_cnt = min(min_cnt, *ctx.groups[i].counter);
+ max_cnt = max(max_cnt, *ctx.groups[i].counter);
+ }
+
+ igt_assert_lt(200000, min_cnt);
+ igt_assert_lte(min_cnt, max_cnt);
+
+ /* Allow a 20% difference max? */
+ igt_assert_lt((((max_cnt - min_cnt) * 100) / min_cnt), 20);
+
+ sched_test_ctx_destroy(fd, &ctx);
+ }
+
+ igt_describe("Schedule 15 groups with medium prio, one high");
+ igt_subtest("sched_15_groups_med_1_high") {
+ uint64_t min_cnt = UINT64_MAX, max_cnt = 0;
+ struct panthor_sched_test_ctx ctx;
+ const unsigned int group_cnt = 16;
+ const unsigned int group_high = group_cnt - 1;
+
+ sched_test_ctx_create(fd, &ctx);
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ sched_test_ctx_add_group(fd, &ctx,
+ i == group_high ?
+ PANTHOR_GROUP_PRIORITY_HIGH :
+ PANTHOR_GROUP_PRIORITY_MEDIUM);
+ }
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ sched_test_ctx_submit_group(fd, &ctx, i);
+
+ /* Add some delay, to make sure each group becomes
+ * active at a different time, and exercise the
+ * idle -> active transition that appeared to be
+ * broken at some point.
+ */
+ usleep(100000);
+ }
+
+ /* Jobs will timeout, because we've issued an infinte loop,
+ * but leave it some time before checking the counter
+ * values.
+ */
+ sleep(15);
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ if (i == group_high)
+ continue;
+
+ min_cnt = min(min_cnt, *ctx.groups[i].counter);
+ max_cnt = max(max_cnt, *ctx.groups[i].counter);
+ }
+
+ igt_assert_lt(200000, min_cnt);
+ igt_assert_lte(min_cnt, max_cnt);
+
+ /* Allow a 30% difference max on all med groups? */
+ igt_assert_lt((((max_cnt - min_cnt) * 100) / min_cnt), 30);
+
+ /* High group's counter must be at least 1.5x the other groups. */
+ igt_assert_lt((float)max_cnt * 1.5, (float)*ctx.groups[group_high].counter);
+
+ sched_test_ctx_destroy(fd, &ctx);
+ }
+
+ igt_describe("Schedule 4 groups with RT prio, one high");
+ igt_subtest("sched_4_groups_rt_1_high") {
+ uint64_t min_cnt = UINT64_MAX, max_cnt = 0;
+ struct panthor_sched_test_ctx ctx;
+ const unsigned int group_cnt = 5;
+ const unsigned int group_high = group_cnt - 1;
+ uint64_t group_high_counter;
+
+ sched_test_ctx_create(fd, &ctx);
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ sched_test_ctx_add_group(fd, &ctx,
+ i == group_high ?
+ PANTHOR_GROUP_PRIORITY_HIGH :
+ PANTHOR_GROUP_PRIORITY_REALTIME);
+ }
+
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ if (i == group_high)
+ continue;
+ sched_test_ctx_submit_group(fd, &ctx, i);
+ }
+
+ /* Leave it some time so the SW scheduler can make all RT groups
+ * active, and the high one really doesn't get a chance to run.
+ * Ideally the dequeueing of jobs would also take the group
+ * priority into account, but that's not the case.
+ */
+ usleep(200000);
+ sched_test_ctx_submit_group(fd, &ctx, group_high);
+
+ /* Make sure we wait less than the timeout, otherwise the group with
+ * high priority will be left a chance to run as soon as one of the RT
+ * group dies.
+ */
+ sleep(2);
+
+ group_high_counter = *ctx.groups[group_high].counter;
+ for (unsigned int i = 0; i < group_cnt; i++) {
+ if (i == group_high)
+ continue;
+
+ min_cnt = min(min_cnt, *ctx.groups[i].counter);
+ max_cnt = max(max_cnt, *ctx.groups[i].counter);
+ }
+
+ igt_assert_lt(200000, min_cnt);
+ igt_assert_lte(min_cnt, max_cnt);
+
+ /* Allow a 30% difference max on all med groups? */
+ igt_assert_lt((((max_cnt - min_cnt) * 100) / min_cnt), 30);
+
+ /* High group should never run. */
+ igt_assert_eq(group_high_counter, 0);
+
+ sched_test_ctx_destroy(fd, &ctx);
+ }
+
+ igt_fixture {
+ drm_close_driver(fd);
+ }
+}
--
2.51.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time
2025-11-28 9:38 ` [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time Boris Brezillon
@ 2025-12-01 11:14 ` Kamil Konieczny
2025-12-01 13:25 ` Daniel Almeida
0 siblings, 1 reply; 10+ messages in thread
From: Kamil Konieczny @ 2025-12-01 11:14 UTC (permalink / raw)
To: Boris Brezillon
Cc: igt-dev, Petri Latvala, Arkadiusz Hiler, Juha-Pekka Heikkila,
Bhanuprakash Modem, Steven Price, Liviu Dudau,
Adrián Larumbe, Daniel Almeida, kernel
Hi Boris,
On 2025-11-28 at 10:38:57 +0100, Boris Brezillon wrote:
> This covering for this bug [1]. Add an IGT test to make sure we don't
> hit that again.
>
> [1]https://lore.kernel.org/20251107171214.1186299-1-boris.brezillon@collabora.com
>
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> Reviewed-by: Kamil Konieczny <kamil.konieczny@linux.intel.com>
> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
I merged 1/3 and this one,
Regards,
Kamil
> ---
> tests/panthor/panthor_gem.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/tests/panthor/panthor_gem.c b/tests/panthor/panthor_gem.c
> index 57cd97e809fd..1566c713f876 100644
> --- a/tests/panthor/panthor_gem.c
> +++ b/tests/panthor/panthor_gem.c
> @@ -66,6 +66,17 @@ igt_main {
> igt_panthor_free_bo(fd, &bo);
> }
>
> + igt_describe_f("Check zero-ing of buffer at creation time");
> + igt_subtest("bo_zeroed") {
> + struct panthor_bo bo;
> +
> + igt_panthor_bo_create_mapped(fd, &bo, getpagesize(), 0, 0);
> + igt_assert(bo.map);
> + igt_assert_eq(*((uint32_t *)bo.map), 0);
> +
> + igt_panthor_free_bo(fd, &bo);
> + }
> +
> igt_fixture {
> drm_close_driver(fd);
> }
> --
> 2.51.1
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time
2025-12-01 11:14 ` Kamil Konieczny
@ 2025-12-01 13:25 ` Daniel Almeida
2025-12-01 15:19 ` Kamil Konieczny
0 siblings, 1 reply; 10+ messages in thread
From: Daniel Almeida @ 2025-12-01 13:25 UTC (permalink / raw)
To: Kamil Konieczny
Cc: Boris Brezillon, igt-dev, Petri Latvala, Arkadiusz Hiler,
Juha-Pekka Heikkila, Bhanuprakash Modem, Steven Price,
Liviu Dudau, Adrián Larumbe, kernel
Hi Kamil,
> On 1 Dec 2025, at 08:14, Kamil Konieczny <kamil.konieczny@linux.intel.com> wrote:
>
> Hi Boris,
> On 2025-11-28 at 10:38:57 +0100, Boris Brezillon wrote:
>> This covering for this bug [1]. Add an IGT test to make sure we don't
>> hit that again.
>>
>> [1]https://lore.kernel.org/20251107171214.1186299-1-boris.brezillon@collabora.com
>>
>> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
>> Reviewed-by: Kamil Konieczny <kamil.konieczny@linux.intel.com>
>> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
>
> I merged 1/3 and this one,
>
> Regards,
> Kamil
>
I’ll have a look on 2/3 today.
— Daniel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time
2025-12-01 13:25 ` Daniel Almeida
@ 2025-12-01 15:19 ` Kamil Konieczny
2025-12-01 15:21 ` Daniel Almeida
0 siblings, 1 reply; 10+ messages in thread
From: Kamil Konieczny @ 2025-12-01 15:19 UTC (permalink / raw)
To: Daniel Almeida
Cc: Boris Brezillon, igt-dev, Petri Latvala, Arkadiusz Hiler,
Juha-Pekka Heikkila, Bhanuprakash Modem, Steven Price,
Liviu Dudau, Adrián Larumbe, kernel
Hi Daniel,
On 2025-12-01 at 10:25:06 -0300, Daniel Almeida wrote:
> Hi Kamil,
>
> > On 1 Dec 2025, at 08:14, Kamil Konieczny <kamil.konieczny@linux.intel.com> wrote:
> >
> > Hi Boris,
> > On 2025-11-28 at 10:38:57 +0100, Boris Brezillon wrote:
> >> This covering for this bug [1]. Add an IGT test to make sure we don't
> >> hit that again.
> >>
> >> [1]https://lore.kernel.org/20251107171214.1186299-1-boris.brezillon@collabora.com
> >>
> >> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> >> Reviewed-by: Kamil Konieczny <kamil.konieczny@linux.intel.com>
> >> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
> >
> > I merged 1/3 and this one,
> >
> > Regards,
> > Kamil
> >
>
> I’ll have a look on 2/3 today.
I merged 1/3 and 2/3, did you mean last one 3/3?
Regards,
Kamil
>
> — Daniel
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time
2025-12-01 15:19 ` Kamil Konieczny
@ 2025-12-01 15:21 ` Daniel Almeida
0 siblings, 0 replies; 10+ messages in thread
From: Daniel Almeida @ 2025-12-01 15:21 UTC (permalink / raw)
To: Kamil Konieczny
Cc: Boris Brezillon, igt-dev, Petri Latvala, Arkadiusz Hiler,
Juha-Pekka Heikkila, Bhanuprakash Modem, Steven Price,
Liviu Dudau, Adrián Larumbe, kernel
> On 1 Dec 2025, at 12:19, Kamil Konieczny <kamil.konieczny@linux.intel.com> wrote:
>
> Hi Daniel,
> On 2025-12-01 at 10:25:06 -0300, Daniel Almeida wrote:
>> Hi Kamil,
>>
>>> On 1 Dec 2025, at 08:14, Kamil Konieczny <kamil.konieczny@linux.intel.com> wrote:
>>>
>>> Hi Boris,
>>> On 2025-11-28 at 10:38:57 +0100, Boris Brezillon wrote:
>>>> This covering for this bug [1]. Add an IGT test to make sure we don't
>>>> hit that again.
>>>>
>>>> [1]https://lore.kernel.org/20251107171214.1186299-1-boris.brezillon@collabora.com
>>>>
>>>> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
>>>> Reviewed-by: Kamil Konieczny <kamil.konieczny@linux.intel.com>
>>>> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
>>>
>>> I merged 1/3 and this one,
>>>
>>> Regards,
>>> Kamil
>>>
>>
>> I’ll have a look on 2/3 today.
>
> I merged 1/3 and 2/3, did you mean last one 3/3?
>
> Regards,
> Kamil
>
>>
>> — Daniel
Yes, the last one, sorry.
— Daniel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH i-g-t v2 3/3] tests/panthor: Add scheduler tests
2025-11-28 9:38 ` [PATCH i-g-t v2 3/3] tests/panthor: Add scheduler tests Boris Brezillon
@ 2025-12-03 19:31 ` Daniel Almeida
2025-12-17 15:38 ` Boris Brezillon
0 siblings, 1 reply; 10+ messages in thread
From: Daniel Almeida @ 2025-12-03 19:31 UTC (permalink / raw)
To: Boris Brezillon
Cc: igt-dev, Petri Latvala, Arkadiusz Hiler, Kamil Konieczny,
Juha-Pekka Heikkila, Bhanuprakash Modem, Steven Price,
Liviu Dudau, Adrián Larumbe, kernel
Hi Boris,
> On 28 Nov 2025, at 06:38, Boris Brezillon <boris.brezillon@collabora.com> wrote:
>
> Tests developed while working on this set of fixes [1].
>
> [1]https://lore.kernel.org/all/20251112115142.1270931-1-boris.brezillon@collabora.com/
>
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
> lib/igt_panthor.c | 71 +++++++
> lib/igt_panthor.h | 76 ++++++++
> tests/panthor/meson.build | 1 +
> tests/panthor/panthor_sched.c | 338 ++++++++++++++++++++++++++++++++++
> 4 files changed, 486 insertions(+)
> create mode 100644 tests/panthor/panthor_sched.c
>
> diff --git a/lib/igt_panthor.c b/lib/igt_panthor.c
> index 73ada9c59bfc..802cb182753c 100644
> --- a/lib/igt_panthor.c
> +++ b/lib/igt_panthor.c
> @@ -2,6 +2,7 @@
> // SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd.
>
> #include "drmtest.h"
> +#include "igt_aux.h"
> #include "igt_panthor.h"
> #include "ioctl_wrappers.h"
> #include "panthor_drm.h"
> @@ -370,3 +371,73 @@ void igt_panthor_free_bo(int fd, struct panthor_bo *bo)
>
> gem_close(fd, bo->handle);
> }
> +
> +/**
> + * igt_panthor_ctx_create:
> + * @fd: panthor device file descriptor
> + * @ctx: context to initialize
> + *
> + * Creates base resources (VM and GPU info) needed for GPU job submission
> + */
> +void igt_panthor_ctx_create(int fd, struct panthor_ctx *ctx)
> +{
> + memset(ctx, 0, sizeof(*ctx));
> + igt_panthor_query(fd, DRM_PANTHOR_DEV_QUERY_GPU_INFO,
> + &ctx->gpu_info, sizeof(ctx->gpu_info), 0);
> + igt_panthor_vm_create(fd, &ctx->vm, 0);
> +}
> +
> +/**
> + * igt_panthor_ctx_destroy:
> + * @fd: panthor device file descriptor
> + * @ctx: context to cleanup
> + *
> + * Releases all the resources attached to a GPU context.
> + */
> +void igt_panthor_ctx_destroy(int fd, struct panthor_ctx *ctx)
> +{
> + for (uint32_t i = 0; i < ctx->group_count; i++) {
> + struct drm_panthor_group_destroy group_destroy = {
> + .group_handle = ctx->groups[i],
> + };
> +
> + igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_PANTHOR_GROUP_DESTROY, &group_destroy), 0);
> + }
> +
> + igt_panthor_vm_destroy(fd, ctx->vm, 0);
> +}
> +
> +/**
> + * igt_panthor_ctx_add_group:
> + * @fd: panthor device file descriptor
> + * @ctx: context to add a group to
> + * @group_prio: group priority
> + * @queues: properties of queues attached to the group
> + * @queue_count: number of queues attached to the group
> + *
> + * Adds a group to a GPU context. Such groups will be released when
> + * the context is destroyed.
> + */
> +void igt_panthor_ctx_add_group(int fd, struct panthor_ctx *ctx,
> + enum drm_panthor_group_priority group_prio,
> + const struct drm_panthor_queue_create *queues,
> + uint32_t queue_count)
> +{
> + unsigned int shader_core_count = igt_hweight(ctx->gpu_info.shader_present);
> + struct drm_panthor_group_create group_create = {
> + .queues = DRM_PANTHOR_OBJ_ARRAY(queue_count, queues),
> + .max_compute_cores = shader_core_count,
> + .max_fragment_cores = shader_core_count,
> + .max_tiler_cores = 1,
> + .priority = group_prio,
> + .compute_core_mask = ctx->gpu_info.shader_present,
> + .fragment_core_mask = ctx->gpu_info.shader_present,
> + .tiler_core_mask = ctx->gpu_info.tiler_present,
> + .vm_id = ctx->vm,
> + };
> +
> + igt_assert(ctx->group_count < ARRAY_SIZE(ctx->groups));
> + igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_PANTHOR_GROUP_CREATE, &group_create), 0);
> + igt_assert(group_create.group_handle > 0);
> + ctx->groups[ctx->group_count++] = group_create.group_handle;
> +}
> diff --git a/lib/igt_panthor.h b/lib/igt_panthor.h
> index dc90033c0ad4..2a62eff37b2b 100644
> --- a/lib/igt_panthor.h
> +++ b/lib/igt_panthor.h
> @@ -7,6 +7,7 @@
> #include <stddef.h>
> #include <stdint.h>
> #include <stdbool.h>
> +
> #include "panthor_drm.h"
>
> struct panthor_bo {
> @@ -16,7 +17,17 @@ struct panthor_bo {
> void *map;
> };
>
> +#define MAX_GROUPS_PER_CTX 128
> +
> +struct panthor_ctx {
> + struct drm_panthor_gpu_info gpu_info;
> + uint32_t vm;
> + uint32_t group_count;
> + uint32_t groups[MAX_GROUPS_PER_CTX];
> +};
> +
> void igt_panthor_query(int fd, int32_t type, void *data, size_t size, int err);
> +
> void igt_panthor_vm_create(int fd, uint32_t *vm_id, int err);
> void igt_panthor_vm_destroy(int fd, uint32_t vm_id, int err);
> void igt_panthor_vm_bind(int fd, uint32_t vm_id, uint32_t bo_handle, uint64_t va,
> @@ -38,12 +49,21 @@ void igt_panthor_group_submit_simple(int fd, uint32_t group_handle,
> int err);
> uint64_t igt_panthor_get_first_core(uint64_t cores_present);
>
> +void igt_panthor_ctx_create(int fd, struct panthor_ctx *ctx);
> +void igt_panthor_ctx_destroy(int fd, struct panthor_ctx *ctx);
> +void igt_panthor_ctx_add_group(int fd, struct panthor_ctx *ctx,
> + enum drm_panthor_group_priority group_prio,
> + const struct drm_panthor_queue_create *queues,
> + uint32_t queue_count);
> +
> enum cs_opcode {
> CS_OPCODE_NOP = 0,
> CS_OPCODE_MOVE48 = 1,
> CS_OPCODE_MOVE32 = 2,
> CS_OPCODE_WAIT = 3,
> + CS_OPCODE_ADD64 = 17,
> CS_OPCODE_STM = 21,
> + CS_OPCODE_BRANCH = 22,
> CS_OPCODE_FLUSH_CACHE = 36,
> };
>
> @@ -61,6 +81,16 @@ enum cs_flush_mode {
> #error "big endian not supported"
> #endif
>
> +enum cs_branch_cond {
> + CS_BRANCH_COND_LE = 0,
> + CS_BRANCH_COND_GT = 1,
> + CS_BRANCH_COND_EQ = 2,
> + CS_BRANCH_COND_NE = 3,
> + CS_BRANCH_COND_LT = 4,
> + CS_BRANCH_COND_GE = 5,
> + CS_BRANCH_COND_ALWAYS = 6,
> +};
> +
> struct cs_instr {
> union {
> struct {
> @@ -89,6 +119,13 @@ struct cs_instr {
> uint64_t unused1: 23;
> uint64_t opcode: 8;
> } wait;
> + struct {
> + uint64_t immediate: 32;
> + uint64_t unused0: 8;
> + uint64_t src: 8;
> + uint64_t dst: 8;
> + uint64_t opcode: 8;
> + } add64;
> struct {
> uint64_t offset: 16;
> uint64_t mask: 16;
> @@ -97,6 +134,15 @@ struct cs_instr {
> uint64_t src: 8;
> uint64_t opcode: 8;
> } stm;
> + struct {
> + uint64_t offset: 16;
> + uint64_t unused0: 12;
> + uint64_t cond: 4;
> + uint64_t unused1: 8;
> + uint64_t src: 8;
> + uint64_t unused2: 8;
> + uint64_t opcode: 8;
> + } branch;
> struct {
> uint64_t l2_mode: 4;
> uint64_t lsc_mode: 4;
> @@ -167,6 +213,21 @@ cs_wait(uint16_t wait_mask, bool progress_inc)
> return instr.raw;
> }
>
> +static inline uint64_t
> +cs_add64(uint32_t imm, uint8_t src, uint8_t dst)
> +{
> + struct cs_instr instr = {
> + .add64 = {
> + .immediate = imm,
> + .src = src,
> + .dst = dst,
> + .opcode = CS_OPCODE_ADD64,
> + },
> + };
> +
> + return instr.raw;
> +}
> +
> static inline uint64_t
> cs_stm(uint8_t address, uint8_t src, uint16_t mask, int16_t offset)
> {
> @@ -195,6 +256,21 @@ cs_stm64(uint8_t address, uint8_t src, int16_t offset)
> return cs_stm(address, src, 0x3, offset);
> }
>
> +static inline uint64_t
> +cs_branch(int16_t offset, enum cs_branch_cond cond, uint8_t src)
> +{
> + struct cs_instr instr = {
> + .branch = {
> + .offset = (uint16_t)offset,
> + .cond = cond,
> + .src = src,
> + .opcode = CS_OPCODE_BRANCH,
> + },
> + };
> +
> + return instr.raw;
> +}
> +
> static inline uint64_t
> cs_flush(enum cs_flush_mode l2_mode,
> enum cs_flush_mode lsc_mode,
> diff --git a/tests/panthor/meson.build b/tests/panthor/meson.build
> index 42a46e9934a9..8bd391596a97 100644
> --- a/tests/panthor/meson.build
> +++ b/tests/panthor/meson.build
> @@ -2,6 +2,7 @@ panthor_progs = [
> 'panthor_gem',
> 'panthor_group',
> 'panthor_query',
> + 'panthor_sched',
> 'panthor_vm',
> ]
>
> diff --git a/tests/panthor/panthor_sched.c b/tests/panthor/panthor_sched.c
> new file mode 100644
> index 000000000000..7cded16c0acd
> --- /dev/null
> +++ b/tests/panthor/panthor_sched.c
> @@ -0,0 +1,338 @@
> +// SPDX-License-Identifier: MIT
> +// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd.
> +
> +#include <stdint.h>
> +#include <sys/mman.h>
> +#include <unistd.h>
> +
> +#include "drm.h"
> +#include "igt.h"
> +#include "igt_core.h"
> +#include "igt_panthor.h"
> +#include "panthor_drm.h"
> +
> +static size_t
> +infinite_incr_loop(uint64_t *cs, uint64_t counter_va)
> +{
> + const uint8_t counter_va_reg = 68;
> + const uint8_t val_reg = 70;
> + uint64_t instrs[] = {
> + /* Load the source register ([r68; r69]) with the kernel address */
> + cs_mov48(counter_va_reg, counter_va),
> + /* Load a 0 into r70 */
Load a 1
> + cs_mov48(val_reg, 1),
> + /* STORE_MULTIPLE: Store the first register to the address pointed to by
> + * [r68; r69]
> + */
> + cs_stm64(counter_va_reg, val_reg, 0),
> + cs_wait(1, false),
Wait for what? All of these seem to be synchronous instructions?
> + cs_add64(1, val_reg, val_reg),
> + cs_branch(-4, CS_BRANCH_COND_ALWAYS, 0),
> + };
> +
> + memcpy(cs, instrs, sizeof(instrs));
> + return sizeof(instrs);
> +}
> +
> +struct panthor_sched_test_group_ctx {
> + uint32_t handle;
> + uint64_t *counter;
> + uint64_t cs_va;
> + uint32_t cs_size;
> +};
> +
> +#define MAX_GROUPS 128
> +
> +struct panthor_sched_test_ctx {
> + struct panthor_ctx ctx;
> + struct panthor_bo cs_bo;
> + uint32_t cs_bo_offset;
> + struct panthor_bo counter_bo;
> + uint32_t counter_bo_offset;
> + uint32_t group_count;
> + struct panthor_sched_test_group_ctx groups[MAX_GROUPS];
> +};
> +
> +#define CS_BO_VA 0x100000
> +#define COUNTER_BO_VA 0x200000
> +
> +static void
> +sched_test_ctx_create(int fd, struct panthor_sched_test_ctx *ctx)
> +{
> + memset(ctx, 0, sizeof(*ctx));
> + igt_panthor_ctx_create(fd, &ctx->ctx);
> + igt_panthor_bo_create_mapped(fd, &ctx->cs_bo, getpagesize(), 0, 0);
> + igt_panthor_vm_bind(fd, ctx->ctx.vm, ctx->cs_bo.handle, CS_BO_VA, ctx->cs_bo.size,
> + DRM_PANTHOR_VM_BIND_OP_MAP_READONLY |
> + DRM_PANTHOR_VM_BIND_OP_TYPE_MAP,
> + 0);
> + igt_panthor_bo_create_mapped(fd, &ctx->counter_bo, getpagesize(), 0, 0);
> + igt_panthor_vm_bind(fd, ctx->ctx.vm, ctx->counter_bo.handle, COUNTER_BO_VA,
> + ctx->counter_bo.size,
> + DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED |
> + DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
> + DRM_PANTHOR_VM_BIND_OP_TYPE_MAP,
> + 0);
> +}
> +
> +static void
> +sched_test_ctx_destroy(int fd, struct panthor_sched_test_ctx *ctx)
> +{
> + igt_panthor_ctx_destroy(fd, &ctx->ctx);
> +}
> +
> +static void
> +sched_test_ctx_add_group(int fd, struct panthor_sched_test_ctx *ctx,
> + enum drm_panthor_group_priority group_prio)
> +{
> + struct drm_panthor_queue_create queue_create = {
> + .priority = 0,
> + .ringbuf_size = getpagesize(),
> + };
> + uint64_t *cs = (uint64_t *)((uint8_t *)ctx->cs_bo.map + ctx->cs_bo_offset);
> + uint64_t *counters = ctx->counter_bo.map;
> + unsigned int group_idx = ctx->group_count;
> + uint64_t counter_va = COUNTER_BO_VA + group_idx * sizeof(counters[0]);
> + unsigned int cs_size;
> +
> + igt_assert_lt(ctx->group_count, ARRAY_SIZE(ctx->groups));
> +
> + igt_panthor_ctx_add_group(fd, &ctx->ctx, group_prio, &queue_create, 1);
> + cs_size = infinite_incr_loop(cs, counter_va);
> + cs_size = ALIGN(cs_size, 64);
> + ctx->groups[ctx->group_count++] = (struct panthor_sched_test_group_ctx){
> + .handle = ctx->ctx.groups[group_idx],
> + .counter = &counters[group_idx],
> + .cs_va = CS_BO_VA + ctx->cs_bo_offset,
> + .cs_size = cs_size,
> + };
> +
> + ctx->cs_bo_offset += cs_size;
> + igt_assert_lt(ctx->cs_bo_offset, ctx->cs_bo.size);
> +}
> +
> +static void
> +sched_test_ctx_submit_group(int fd, struct panthor_sched_test_ctx *ctx,
> + unsigned int group_idx)
> +{
> + struct drm_panthor_queue_submit qsubmit = {
> + .queue_index = 0,
> + .stream_size = ctx->groups[group_idx].cs_size,
> + .stream_addr = ctx->groups[group_idx].cs_va,
> + .latest_flush = 0,
> + };
> + struct drm_panthor_group_submit gsubmit = {
> + .group_handle = ctx->groups[group_idx].handle,
> + .queue_submits = DRM_PANTHOR_OBJ_ARRAY(1, &qsubmit),
> + };
> +
> + igt_assert_lt(group_idx, ctx->group_count);
> + igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_PANTHOR_GROUP_SUBMIT, &gsubmit), 0);
> +}
> +
> +igt_main {
> + int fd;
> +
> + igt_fixture {
> + fd = drm_open_driver(DRIVER_PANTHOR);
> + }
> +
> + igt_describe("Schedule 8 groups with the same prio");
> + igt_subtest("sched_8_groups_same_prio") {
> + uint64_t min_cnt = UINT64_MAX, max_cnt = 0;
> + struct panthor_sched_test_ctx ctx;
> + const unsigned int group_cnt = 8;
> +
> + sched_test_ctx_create(fd, &ctx);
> +
> + for (unsigned int i = 0; i < group_cnt; i++)
> + sched_test_ctx_add_group(fd, &ctx, PANTHOR_GROUP_PRIORITY_MEDIUM);
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + sched_test_ctx_submit_group(fd, &ctx, i);
> +
> + /* Add some delay, to make sure each group becomes
> + * active at a different time, and exercise the
> + * idle -> active transition that appeared to be
> + * broken at some point.
> + */
> + usleep(100000);
> + }
> +
> + /* Jobs will timeout, because we've issued an infinte loop,
> + * but leave it some time before checking the counter
> + * values.
> + */
> + sleep(6);
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + min_cnt = min(min_cnt, *ctx.groups[i].counter);
> + max_cnt = max(max_cnt, *ctx.groups[i].counter);
> + }
> +
> + igt_assert_lt(200000, min_cnt);
> + igt_assert_lte(min_cnt, max_cnt);
> +
> + /* Allow a 20% difference max? */
> + igt_assert_lt((((max_cnt - min_cnt) * 100) / min_cnt), 20);
> +
> + sched_test_ctx_destroy(fd, &ctx);
> + }
> +
> + igt_describe("Schedule 16 groups with the same prio");
> + igt_subtest("sched_16_groups_same_prio") {
> + uint64_t min_cnt = UINT64_MAX, max_cnt = 0;
> + struct panthor_sched_test_ctx ctx;
> + const unsigned int group_cnt = 16;
> +
> + sched_test_ctx_create(fd, &ctx);
> +
> + for (unsigned int i = 0; i < group_cnt; i++)
> + sched_test_ctx_add_group(fd, &ctx, PANTHOR_GROUP_PRIORITY_MEDIUM);
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + sched_test_ctx_submit_group(fd, &ctx, i);
> +
> + /* Add some delay, to make sure each group becomes
> + * active at a different time, and exercise the
> + * idle -> active transition that appeared to be
> + * broken at some point.
> + */
> + usleep(100000);
> + }
> +
> + /* Jobs will timeout, because we've issued an infinte loop,
> + * but leave it some time before checking the counter
> + * values.
> + */
> + sleep(15);
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + min_cnt = min(min_cnt, *ctx.groups[i].counter);
> + max_cnt = max(max_cnt, *ctx.groups[i].counter);
> + }
> +
> + igt_assert_lt(200000, min_cnt);
> + igt_assert_lte(min_cnt, max_cnt);
> +
> + /* Allow a 20% difference max? */
> + igt_assert_lt((((max_cnt - min_cnt) * 100) / min_cnt), 20);
> +
> + sched_test_ctx_destroy(fd, &ctx);
> + }
> +
> + igt_describe("Schedule 15 groups with medium prio, one high");
> + igt_subtest("sched_15_groups_med_1_high") {
> + uint64_t min_cnt = UINT64_MAX, max_cnt = 0;
> + struct panthor_sched_test_ctx ctx;
> + const unsigned int group_cnt = 16;
> + const unsigned int group_high = group_cnt - 1;
> +
> + sched_test_ctx_create(fd, &ctx);
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + sched_test_ctx_add_group(fd, &ctx,
> + i == group_high ?
> + PANTHOR_GROUP_PRIORITY_HIGH :
> + PANTHOR_GROUP_PRIORITY_MEDIUM);
> + }
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + sched_test_ctx_submit_group(fd, &ctx, i);
> +
> + /* Add some delay, to make sure each group becomes
> + * active at a different time, and exercise the
> + * idle -> active transition that appeared to be
> + * broken at some point.
> + */
> + usleep(100000);
> + }
> +
> + /* Jobs will timeout, because we've issued an infinte loop,
> + * but leave it some time before checking the counter
> + * values.
> + */
> + sleep(15);
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + if (i == group_high)
> + continue;
> +
> + min_cnt = min(min_cnt, *ctx.groups[i].counter);
> + max_cnt = max(max_cnt, *ctx.groups[i].counter);
> + }
> +
> + igt_assert_lt(200000, min_cnt);
> + igt_assert_lte(min_cnt, max_cnt);
> +
> + /* Allow a 30% difference max on all med groups? */
> + igt_assert_lt((((max_cnt - min_cnt) * 100) / min_cnt), 30);
> +
> + /* High group's counter must be at least 1.5x the other groups. */
> + igt_assert_lt((float)max_cnt * 1.5, (float)*ctx.groups[group_high].counter);
> +
> + sched_test_ctx_destroy(fd, &ctx);
> + }
> +
> + igt_describe("Schedule 4 groups with RT prio, one high");
> + igt_subtest("sched_4_groups_rt_1_high") {
> + uint64_t min_cnt = UINT64_MAX, max_cnt = 0;
> + struct panthor_sched_test_ctx ctx;
> + const unsigned int group_cnt = 5;
> + const unsigned int group_high = group_cnt - 1;
> + uint64_t group_high_counter;
> +
> + sched_test_ctx_create(fd, &ctx);
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + sched_test_ctx_add_group(fd, &ctx,
> + i == group_high ?
> + PANTHOR_GROUP_PRIORITY_HIGH :
> + PANTHOR_GROUP_PRIORITY_REALTIME);
> + }
> +
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + if (i == group_high)
> + continue;
> + sched_test_ctx_submit_group(fd, &ctx, i);
> + }
> +
> + /* Leave it some time so the SW scheduler can make all RT groups
> + * active, and the high one really doesn't get a chance to run.
> + * Ideally the dequeueing of jobs would also take the group
> + * priority into account, but that's not the case.
> + */
> + usleep(200000);
> + sched_test_ctx_submit_group(fd, &ctx, group_high);
> +
> + /* Make sure we wait less than the timeout, otherwise the group with
> + * high priority will be left a chance to run as soon as one of the RT
> + * group dies.
> + */
> + sleep(2);
> +
> + group_high_counter = *ctx.groups[group_high].counter;
> + for (unsigned int i = 0; i < group_cnt; i++) {
> + if (i == group_high)
> + continue;
> +
> + min_cnt = min(min_cnt, *ctx.groups[i].counter);
> + max_cnt = max(max_cnt, *ctx.groups[i].counter);
> + }
> +
> + igt_assert_lt(200000, min_cnt);
> + igt_assert_lte(min_cnt, max_cnt);
> +
> + /* Allow a 30% difference max on all med groups? */
> + igt_assert_lt((((max_cnt - min_cnt) * 100) / min_cnt), 30);
> +
> + /* High group should never run. */
> + igt_assert_eq(group_high_counter, 0);
> +
> + sched_test_ctx_destroy(fd, &ctx);
> + }
> +
> + igt_fixture {
> + drm_close_driver(fd);
> + }
> +}
> --
> 2.51.1
>
This looks good, but I tried it and this is the result:
IGT-Version: 2.2-g6ba172359 (aarch64) (Linux: 6.18.0-rc4-hwe aarch64)
Using IGT_SRANDOM=1764789962 for randomisation
Opened device: /dev/dri/card0
Starting subtest: sched_8_groups_same_prio
[ 956.405832] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 956.406839] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 956.661846] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 956.662752] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 956.917917] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 956.918794] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 956.919620] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 957.173858] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
(panthor_sched:8051) CRITICAL: Test assertion failure function __igt_unique____real_main133, file ../tests/panthor/panthor_sched.c:177:
(panthor_sched:8051) CRITICAL: Failed assertion: (((max_cnt - min_cnt) * 100) / min_cnt) < 20
(panthor_sched:8051) CRITICAL: error: 1950 >= 20
Stack trace:
#0 ../lib/igt_core.c:2296 __igt_fail_assert()
#1 ../tests/panthor/panthor_sched.c:179 __igt_unique____real_main133()
#2 ../tests/panthor/panthor_sched.c:133 main()
#3 [<unknown>+0xb987229c]
#4 [__libc_start_main+0x9c]
Subtest sched_8_groups_same_prio failed.
**** DEBUG ****
(panthor_sched:8051) CRITICAL: Test assertion failure function __igt_unique____real_main133, file ../tests/panthor/panthor_sched.c:177:
(panthor_sched:8051) CRITICAL: Failed assertion: (((max_cnt - min_cnt) * 100) / min_cnt) < 20
(panthor_sched:8051) CRITICAL: error: 1950 >= 20
(panthor_sched:8051) igt_core-INFO: Stack trace:
(panthor_sched:8051) igt_core-INFO: #0 ../lib/igt_core.c:2296 __igt_fail_assert()
(panthor_sched:8051) igt_core-INFO: #1 ../tests/panthor/panthor_sched.c:179 __igt_unique____real_main133()
(panthor_sched:8051) igt_core-INFO: #2 ../tests/panthor/panthor_sched.c:133 main()
(panthor_sched:8051) igt_core-INFO: #3 [<unknown>+0xb987229c]
(panthor_sched:8051) igt_core-INFO: #4 [__libc_start_main+0x9c]
**** END ****
Subtest sched_8_groups_same_prio: FAIL (6.868s)
Starting subtest: sched_16_groups_same_prio
[ 966.658057] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 966.950047] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 967.286042] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 967.574037] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 967.862067] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 968.277970] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 968.342033] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 968.630049] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 968.694132] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 968.790115] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 968.886033] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 968.950019] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 968.982139] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 969.142087] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 972.278051] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 972.790126] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
(panthor_sched:8051) CRITICAL: Test assertion failure function __igt_unique____real_main133, file ../tests/panthor/panthor_sched.c:219:
(panthor_sched:8051) CRITICAL: Failed assertion: (((max_cnt - min_cnt) * 100) / min_cnt) < 20
(panthor_sched:8051) CRITICAL: error: 1729 >= 20
Stack trace:
#0 ../lib/igt_core.c:2296 __igt_fail_assert()
#1 ../tests/panthor/panthor_sched.c:221 __igt_unique____real_main133()
#2 ../tests/panthor/panthor_sched.c:133 main()
#3 [<unknown>+0xb987229c]
#4 [__libc_start_main+0x9c]
Subtest sched_16_groups_same_prio failed.
**** DEBUG ****
(panthor_sched:8051) CRITICAL: Test assertion failure function __igt_unique____real_main133, file ../tests/panthor/panthor_sched.c:219:
(panthor_sched:8051) CRITICAL: Failed assertion: (((max_cnt - min_cnt) * 100) / min_cnt) < 20
(panthor_sched:8051) CRITICAL: error: 1729 >= 20
(panthor_sched:8051) igt_core-INFO: Stack trace:
(panthor_sched:8051) igt_core-INFO: #0 ../lib/igt_core.c:2296 __igt_fail_assert()
(panthor_sched:8051) igt_core-INFO: #1 ../tests/panthor/panthor_sched.c:221 __igt_unique____real_main133()
(panthor_sched:8051) igt_core-INFO: #2 ../tests/panthor/panthor_sched.c:133 main()
(panthor_sched:8051) igt_core-INFO: #3 [<unknown>+0xb987229c]
(panthor_sched:8051) igt_core-INFO: #4 [__libc_start_main+0x9c]
**** END ****
Subtest sched_16_groups_same_prio: FAIL (16.619s)
Starting subtest: sched_15_groups_med_1_high
[ 981.494175] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 982.774389] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 983.542380] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 983.706258] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 984.022303] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 984.534323] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 984.758239] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 984.886290] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 984.894132] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 985.046324] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 985.078218] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 985.238128] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 985.398222] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 985.462335] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 985.558313] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
[ 989.686323] panthor fb000000.gpu: [drm] job timeout: pid=8051, comm=panthor_sched, seqno=1
(panthor_sched:8051) CRITICAL: Test assertion failure function __igt_unique____real_main133, file ../tests/panthor/panthor_sched.c:269:
(panthor_sched:8051) CRITICAL: Failed assertion: (((max_cnt - min_cnt) * 100) / min_cnt) < 30
(panthor_sched:8051) CRITICAL: error: 444 >= 30
Stack trace:
#0 ../lib/igt_core.c:2296 __igt_fail_assert()
#1 ../tests/panthor/panthor_sched.c:272 __igt_unique____real_main133()
#2 ../tests/panthor/panthor_sched.c:133 main()
#3 [<unknown>+0xb987229c]
#4 [__libc_start_main+0x9c]
Subtest sched_15_groups_med_1_high failed.
**** DEBUG ****
(panthor_sched:8051) CRITICAL: Test assertion failure function __igt_unique____real_main133, file ../tests/panthor/panthor_sched.c:269:
(panthor_sched:8051) CRITICAL: Failed assertion: (((max_cnt - min_cnt) * 100) / min_cnt) < 30
(panthor_sched:8051) CRITICAL: error: 444 >= 30
(panthor_sched:8051) igt_core-INFO: Stack trace:
(panthor_sched:8051) igt_core-INFO: #0 ../lib/igt_core.c:2296 __igt_fail_assert()
(panthor_sched:8051) igt_core-INFO: #1 ../tests/panthor/panthor_sched.c:272 __igt_unique____real_main133()
(panthor_sched:8051) igt_core-INFO: #2 ../tests/panthor/panthor_sched.c:133 main()
(panthor_sched:8051) igt_core-INFO: #3 [<unknown>+0xb987229c]
(panthor_sched:8051) igt_core-INFO: #4 [__libc_start_main+0x9c]
**** END ****
Subtest sched_15_groups_med_1_high: FAIL (16.617s)
Starting subtest: sched_4_groups_rt_1_high
Subtest sched_4_groups_rt_1_high: SUCCESS (2.205s)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH i-g-t v2 3/3] tests/panthor: Add scheduler tests
2025-12-03 19:31 ` Daniel Almeida
@ 2025-12-17 15:38 ` Boris Brezillon
0 siblings, 0 replies; 10+ messages in thread
From: Boris Brezillon @ 2025-12-17 15:38 UTC (permalink / raw)
To: Daniel Almeida
Cc: igt-dev, Petri Latvala, Arkadiusz Hiler, Kamil Konieczny,
Juha-Pekka Heikkila, Bhanuprakash Modem, Steven Price,
Liviu Dudau, Adrián Larumbe, kernel
On Wed, 3 Dec 2025 16:31:59 -0300
Daniel Almeida <daniel.almeida@collabora.com> wrote:
[...]
> > diff --git a/tests/panthor/panthor_sched.c b/tests/panthor/panthor_sched.c
> > new file mode 100644
> > index 000000000000..7cded16c0acd
> > --- /dev/null
> > +++ b/tests/panthor/panthor_sched.c
> > @@ -0,0 +1,338 @@
> > +// SPDX-License-Identifier: MIT
> > +// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd.
> > +
> > +#include <stdint.h>
> > +#include <sys/mman.h>
> > +#include <unistd.h>
> > +
> > +#include "drm.h"
> > +#include "igt.h"
> > +#include "igt_core.h"
> > +#include "igt_panthor.h"
> > +#include "panthor_drm.h"
> > +
> > +static size_t
> > +infinite_incr_loop(uint64_t *cs, uint64_t counter_va)
> > +{
> > + const uint8_t counter_va_reg = 68;
> > + const uint8_t val_reg = 70;
> > + uint64_t instrs[] = {
> > + /* Load the source register ([r68; r69]) with the kernel address */
> > + cs_mov48(counter_va_reg, counter_va),
> > + /* Load a 0 into r70 */
>
> Load a 1
Oops, will fix the comment.
>
> > + cs_mov48(val_reg, 1),
> > + /* STORE_MULTIPLE: Store the first register to the address pointed to by
> > + * [r68; r69]
> > + */
> > + cs_stm64(counter_va_reg, val_reg, 0),
> > + cs_wait(1, false),
>
> Wait for what? All of these seem to be synchronous instructions?
Nope, load/store instructions are asynchronous, you need to wait for
the SB assigned to "other-asynchronous-ops" (defaults to zero) for the
mem operation to be effective.
>
> > + cs_add64(1, val_reg, val_reg),
> > + cs_branch(-4, CS_BRANCH_COND_ALWAYS, 0),
> > + };
>
> This looks good, but I tried it and this is the result:
If you're not testing with drm-misc-next, that's normal. Those tests
are added to make sure we don't regress those scheduling cases again.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-12-17 15:38 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-28 9:38 [PATCH i-g-t v2 0/3] tests/panthor: Add more tests Boris Brezillon
2025-11-28 9:38 ` [PATCH i-g-t v2 1/3] drm-uapi/panthor: Sync panthor uapi Boris Brezillon
2025-11-28 9:38 ` [PATCH i-g-t v2 2/3] tests/panthor: Add a test to make sure the buffer is zeroed at alloc time Boris Brezillon
2025-12-01 11:14 ` Kamil Konieczny
2025-12-01 13:25 ` Daniel Almeida
2025-12-01 15:19 ` Kamil Konieczny
2025-12-01 15:21 ` Daniel Almeida
2025-11-28 9:38 ` [PATCH i-g-t v2 3/3] tests/panthor: Add scheduler tests Boris Brezillon
2025-12-03 19:31 ` Daniel Almeida
2025-12-17 15:38 ` Boris Brezillon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox