[PATCH 3/3] drm/amdkfd: disable debug before retiring MES process context on teardown

Alex Deucher <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Alex Sierra <[email protected]>

On process teardown, kfd_process_notifier_release_internal() called
kfd_process_dequeue_from_all_devices() (which issues the MES
SET_SHADER_DEBUGGER process_ctx_flush=1 that retires the process context)
before kfd_dbg_trap_disable(). For a process under a debugger, the debug
teardown path (kfd_dbg_trap_disable -> kfd_dbg_trap_deactivate) then issues
several SET_SHADER_DEBUGGER process_ctx_flush=0 packets (reset wave launch
mode, clear debug flags, reset MES debug mode). Because those packets carry
the process_context_addr, MES re-adds the process to its scheduler list
after the flush had retired it.

Teardown then frees proc_ctx_bo, and a later MES scheduling pass dereferences
the freed process context, producing a GPUVM page fault (vmid 0, GC_UTCL2)
on the freed page. This is intermittent because it depends on an MES pass
landing on the process before its GART page is reused. It is specific to the
debugger path, where queues are added with skip_process_ctx_clear=1 so the
last REMOVE_QUEUE does not clear the context and delisting relies on the
flush.

Reorder teardown so debug is disabled first, and the process context is
flushed/retired last, so nothing re-adds the process after it is retired.
kfd_dbg_trap_disable() now runs while queues still exist, which matches the
normal live debug-disable ordering.

Signed-off-by: Alex Sierra <[email protected]>
Reviewed-by: Felix Kuehling <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdkfd/kfd_process.c | 44 +++++++++++++++---------
 1 file changed, 28 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 0a7c1900da959..dd938788bdd9a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -1408,23 +1408,16 @@ void kfd_process_notifier_release_internal(struct kfd_process *p)
 		kfd_unref_process(p);
 
 	/*
-	 * Dequeue and destroy user queues, it is not safe for GPU to access
-	 * system memory after mmu release notifier callback returns because
-	 * exit_mmap free process memory afterwards.
+	 * Disable debug BEFORE dequeuing/flushing the MES process context.
+	 *
+	 * kfd_dbg_trap_disable() -> kfd_dbg_trap_deactivate() issues
+	 * SET_SHADER_DEBUGGER (process_ctx_flush=0) packets that re-add the
+	 * process to the MES scheduler list. kfd_process_dequeue_from_all_devices()
+	 * sends the process_ctx_flush=1 that retires the context. If debug
+	 * teardown ran after the dequeue, those packets would put the process
+	 * back on the MES list and, once proc_ctx_bo is freed, MES would fault
+	 * on the freed process context. Retiring the context last avoids this.
 	 */
-	kfd_process_dequeue_from_all_devices(p);
-	pqm_uninit(&p->pqm);
-
-	for (i = 0; i < p->n_pdds; i++) {
-		struct kfd_process_device *pdd = p->pdds[i];
-
-		/* re-enable GFX OFF since runtime enable with ttmp setup disabled it. */
-		if (!kfd_dbg_is_rlc_restore_supported(pdd->dev) && p->runtime_info.ttmp_setup)
-			amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
-	}
-
-	/* Indicate to other users that MM is no longer valid */
-	p->mm = NULL;
 	kfd_dbg_trap_disable(p);
 
 	if (atomic_read(&p->debugged_process_count) > 0) {
@@ -1445,6 +1438,25 @@ void kfd_process_notifier_release_internal(struct kfd_process *p)
 		srcu_read_unlock(&kfd_processes_srcu, idx);
 	}
 
+	/*
+	 * Dequeue and destroy user queues, it is not safe for GPU to access
+	 * system memory after mmu release notifier callback returns because
+	 * exit_mmap free process memory afterwards.
+	 */
+	kfd_process_dequeue_from_all_devices(p);
+	pqm_uninit(&p->pqm);
+
+	for (i = 0; i < p->n_pdds; i++) {
+		struct kfd_process_device *pdd = p->pdds[i];
+
+		/* re-enable GFX OFF since runtime enable with ttmp setup disabled it. */
+		if (!kfd_dbg_is_rlc_restore_supported(pdd->dev) && p->runtime_info.ttmp_setup)
+			amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+	}
+
+	/* Indicate to other users that MM is no longer valid */
+	p->mm = NULL;
+
 	if (p->context_id == KFD_CONTEXT_ID_PRIMARY)
 		mmu_notifier_put(&p->mmu_notifier);
 }
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.