[igt-dev] [PATCH i-g-t] tests/panfrost: Add infinite job test

Steven Price steven.price at arm.com
Fri Sep 13 10:23:33 UTC 2019


Construct a loop of three job descriptors that will execute
continuously. Then free the BO backing the job descriptors (before the
timeout) causing a page fault on the GPU. The GPU fault will race with
the destruction of the BO.

Signed-off-by: Steven Price <steven.price at arm.com>
---
This is a test for the bug fixed by "Prevent race when handling page
fault"[1]

[1] https://lore.kernel.org/lkml/20190905121141.42820-1-steven.price@arm.com/

 lib/igt_panfrost.c      | 50 +++++++++++++++++++++++++++++++++++++++++
 lib/igt_panfrost.h      |  1 +
 lib/panfrost-job.h      |  6 ++++-
 tests/panfrost_submit.c | 14 ++++++++++++
 4 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/lib/igt_panfrost.c b/lib/igt_panfrost.c
index 8b0c2b77..04dac3d7 100644
--- a/lib/igt_panfrost.c
+++ b/lib/igt_panfrost.c
@@ -72,6 +72,8 @@ igt_panfrost_gem_new(int fd, size_t size)
 void
 igt_panfrost_free_bo(int fd, struct panfrost_bo *bo)
 {
+        if (!bo)
+                return;
         if (bo->map)
                 munmap(bo->map, bo->size);
         gem_close(fd, bo->handle);
@@ -127,6 +129,54 @@ void igt_panfrost_bo_mmap(int fd, struct panfrost_bo *bo)
         igt_assert(bo->map);
 }
 
+struct panfrost_submit *igt_panfrost_infinite_job(int fd)
+{
+        struct panfrost_submit *submit;
+        struct mali_job_descriptor_header header = {
+                .job_type = JOB_TYPE_SET_VALUE,
+                .job_descriptor_size = MALI_JOB_64
+        };
+        struct mali_payload_set_value payload = {
+                .value_descriptor = MALI_SET_VALUE_ZERO,
+                .immediate = JOB_NOT_STARTED
+        };
+        int i;
+        int size = ALIGN(sizeof(header) + sizeof(payload), 64);
+        uint32_t *bos;
+
+        submit = calloc(1, sizeof(*submit));
+
+        submit->submit_bo = igt_panfrost_gem_new(fd, size * 3);
+        igt_panfrost_bo_mmap(fd, submit->submit_bo);
+
+        for(i = 0; i < 3; i++) {
+                int offset = i * size;
+                int next_offset = (i == 2) ? 0 : (offset + size);
+                int prev_offset = (i == 0) ? size * 2 : (offset - size);
+
+                header.next_job_64 = submit->submit_bo->offset + next_offset;
+                payload.out = submit->submit_bo->offset + prev_offset;
+
+                memcpy(submit->submit_bo->map + offset, &header,
+                                sizeof(header));
+                memcpy(submit->submit_bo->map + offset + sizeof(header),
+                                &payload, sizeof(payload));
+        }
+
+        bos = malloc(sizeof(*bos));
+        bos[0] = submit->submit_bo->handle;
+
+        submit->args = calloc(1, sizeof(*submit->args));
+        submit->args->jc = submit->submit_bo->offset;
+        submit->args->requirements = 0;
+        submit->args->bo_handles = to_user_pointer(bos);
+        submit->args->bo_handle_count = 1;
+
+        igt_assert_eq(drmSyncobjCreate(fd, DRM_SYNCOBJ_CREATE_SIGNALED, &submit->args->out_sync), 0);
+
+        return submit;
+}
+
 struct panfrost_submit *igt_panfrost_trivial_job(int fd, bool do_crash, int width, int height, uint32_t color)
 {
         struct panfrost_submit *submit;
diff --git a/lib/igt_panfrost.h b/lib/igt_panfrost.h
index cc7998dc..5e7c8c86 100644
--- a/lib/igt_panfrost.h
+++ b/lib/igt_panfrost.h
@@ -47,6 +47,7 @@ struct panfrost_submit {
 struct panfrost_bo *igt_panfrost_gem_new(int fd, size_t size);
 void igt_panfrost_free_bo(int fd, struct panfrost_bo *bo);
 
+struct panfrost_submit *igt_panfrost_infinite_job(int fd);
 struct panfrost_submit *igt_panfrost_trivial_job(int fd, bool do_crash, int width, int height, uint32_t color);
 void igt_panfrost_free_job(int fd, struct panfrost_submit *submit);
 
diff --git a/lib/panfrost-job.h b/lib/panfrost-job.h
index 85ef02d0..206f9d44 100644
--- a/lib/panfrost-job.h
+++ b/lib/panfrost-job.h
@@ -613,9 +613,13 @@ struct mali_job_descriptor_header {
         };
 } __attribute__((packed));
 
+#define MALI_SET_VALUE_ZERO      3
+
 struct mali_payload_set_value {
         u64 out;
-        u64 unknown;
+        u32 value_descriptor;
+        u32 reserved;
+        u64 immediate;
 } __attribute__((packed));
 
 /* Special attributes have a fixed index */
diff --git a/tests/panfrost_submit.c b/tests/panfrost_submit.c
index 13ce85b7..b0b37fbd 100644
--- a/tests/panfrost_submit.c
+++ b/tests/panfrost_submit.c
@@ -175,6 +175,20 @@ igt_main
                 igt_panfrost_free_job(fd, submit);
         }
 
+        igt_subtest("pan-infinite") {
+                struct panfrost_submit *submit;
+
+                submit = igt_panfrost_infinite_job(fd);
+                do_ioctl(fd, DRM_IOCTL_PANFROST_SUBMIT, submit->args);
+                /* Expect for this job to timeout */
+                igt_assert(!syncobj_wait(fd, &submit->args->out_sync, 1,
+                                         abs_timeout(SHORT_TIME_NSEC), 0, NULL));
+                /* This will unmap the job while it is still executing causing
+                 * a page fault
+                 */
+                igt_panfrost_free_job(fd, submit);
+        }
+
         igt_fixture {
                 close(fd);
         }
-- 
2.20.1



More information about the igt-dev mailing list