A user-requested GPU reset issued while several processes are using
the device can Oops the host during munmap():

  amdgpu: Faulty UTCL2 client ID: SDMA1 (0x101)
  amdgpu: RW: 0x1
  BUG: unable to handle page fault for address: 00000000000132e8
  RIP: 0010:free_swap_cache+0x5/0xb0
   free_pages_and_swap_cache+0x3a/0x60
   tlb_batch_pages_flush+0x43/0x80
   zap_pte_range+0x80d/0xcd0
   unmap_page_range+0x2c6/0x4f0
   do_vmi_align_munmap+0x3e8/0x5b0
   __x64_sys_munmap+0x1b/0x30

amdgpu_device_gpu_recover() locks the reset domain before
amdgpu_device_halt_activities() reaches amdgpu_amdkfd_pre_reset().
amdgpu_device_lock_reset_domain() holds reset_domain->sem for write,
so the down_read_trylock() at the top of unmap_queues_cpsch() always
fails and it returns -EIO without ever sending the unmap packet.
stop_cpsch() still clears dqm->sched_running, so the driver believes
KFD scheduling has been stopped while the user queues are in fact
still on the hardware.

The application then takes its reset errors, exits, and munmap()
frees pages that an SDMA user queue is still writing into. That
corrupts the mm bookkeeping and faults on a bogus struct page.

Draining adev->sdma.instance[].ring does not cover this case. The
faulting engine runs in the process VMID and is fed by a user queue
that only the HWS can dequeue.

For a user-requested reset the GPU is still healthy and the queues
can be preempted normally, so quiesce KFD before the reset domain
lock is taken.

Only AMDGPU_RESET_SRC_USER is handled. A job timeout, an MES or HWS
failure and a frozen PCI link cannot preempt, so hang recovery is
left untouched rather than delayed. A RAS-triggered recovery can run
with the GPU still able to preempt; it is not covered here and needs
its own change.

Signed-off-by: William Palacek <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 472e96ae884e..2a1243a2e578 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5308,6 +5308,30 @@ static void amdgpu_device_recovery_prepare(struct 
amdgpu_device *adev,
        }
 }
 
+/*
+ * unmap_queues_cpsch() needs reset_domain->sem for read, so KFD must be
+ * quiesced before amdgpu_device_lock_reset_domain() takes it for write.
+ * Otherwise the preemption silently fails and SDMA user queues keep running
+ * while userspace tears its address space down.
+ *
+ * This is restricted to a user-requested reset, where the GPU is known to be
+ * healthy and the queues can still be dequeued. Other sources are left alone:
+ * a job timeout, an MES or HWS failure and a frozen PCI link cannot preempt,
+ * and adding a preemption attempt there would only delay recovery.
+ */
+static void amdgpu_device_kfd_quiesce_pre_reset_lock(
+                               struct amdgpu_reset_context *reset_context,
+                               struct list_head *device_list)
+{
+       struct amdgpu_device *kfd_adev;
+
+       if (!reset_context || reset_context->src != AMDGPU_RESET_SRC_USER)
+               return;
+
+       list_for_each_entry(kfd_adev, device_list, reset_list)
+               amdgpu_amdkfd_suspend(kfd_adev, false);
+}
+
 static void amdgpu_device_recovery_get_reset_lock(struct amdgpu_device *adev,
                                                  struct list_head *device_list)
 {
@@ -5613,6 +5637,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
        /* Cannot be called after locking reset domain */
        amdgpu_ras_pre_reset(adev, &device_list);
 
+       amdgpu_device_kfd_quiesce_pre_reset_lock(reset_context, &device_list);
+
        /* We need to lock reset domain only once both for XGMI and single 
device */
        amdgpu_device_recovery_get_reset_lock(adev, &device_list);
 
-- 
2.43.0

Reply via email to