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
