The cleaner shader sysfs path allocates a 16-dword (64 byte) IB but
incorrectly fills (align_mask + 1) dwords. On GFX rings align_mask is
0xff, so the loop wrote 256 dwords into a 64-byte buffer, causing a
kernel page fault.

The IB only needs to be a minimal NOP shell to schedule the job; the
cleaner shader itself is emitted on the ring via emit_cleaner_shader().
Fill 16 dwords to match the allocation.

v2: Use ib_size_variable (Lijo)

Fixes: d361ad5d2fc0 ("drm/amdgpu: Add sysfs interface for running cleaner 
shader")

Suggested-by: Lijo Lazar <[email protected]>
Signed-off-by: Asad Kamal <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index ff5a55f5f3c9..bce1acf197a9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -1689,12 +1689,13 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct 
amdgpu_ring *ring)
        struct amdgpu_device *adev = ring->adev;
        struct drm_gpu_scheduler *sched = &ring->sched;
        struct drm_sched_entity entity;
+       unsigned int ib_size_dw = 16;
        static atomic_t counter;
        struct dma_fence *f;
        struct amdgpu_job *job;
        struct amdgpu_ib *ib;
        void *owner;
-       int i, r;
+       int r;
 
        /* Initialize the scheduler entity */
        r = drm_sched_entity_init(&entity, DRM_SCHED_PRIORITY_NORMAL,
@@ -1712,7 +1713,7 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct 
amdgpu_ring *ring)
        owner = (void *)(unsigned long)atomic_inc_return(&counter);
 
        r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
-                                    64, 0, &job,
+                                    ib_size_dw * sizeof(uint32_t), 0, &job,
                                     AMDGPU_KERNEL_JOB_ID_CLEANER_SHADER);
        if (r)
                goto err;
@@ -1722,9 +1723,8 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct 
amdgpu_ring *ring)
        job->run_cleaner_shader = true;
 
        ib = &job->ibs[0];
-       for (i = 0; i <= ring->funcs->align_mask; ++i)
-               ib->ptr[i] = ring->funcs->nop;
-       ib->length_dw = ring->funcs->align_mask + 1;
+       memset32(ib->ptr, ring->funcs->nop, ib_size_dw);
+       ib->length_dw = ib_size_dw;
 
        f = amdgpu_job_submit(job);
 
-- 
2.46.0

Reply via email to