[PATCH] drm/amdgpu: Fix Circular Locking Dependency in AMDGPU GFX Isolation
Alex Deucher
alexdeucher at gmail.com
Wed Jan 8 17:29:44 UTC 2025
On Sat, Jan 4, 2025 at 1:02 AM Srinivasan Shanmugam
<srinivasan.shanmugam at amd.com> wrote:
>
> This commit addresses a circular locking dependency issue within the GFX
> isolation mechanism. The problem was identified by a warning indicating
> a potential deadlock due to inconsistent lock acquisition order.
>
> - The `amdgpu_gfx_enforce_isolation_ring_begin_use` and
> `amdgpu_gfx_enforce_isolation_ring_end_use` functions previously
> acquired `enforce_isolation_mutex` and called `amdgpu_gfx_kfd_sch_ctrl`,
> leading to potential deadlocks. ie., If `amdgpu_gfx_kfd_sch_ctrl` is
> called while `enforce_isolation_mutex` is held, and
> `amdgpu_gfx_enforce_isolation_handler` is called while `kfd_sch_mutex` is
> held, it can create a circular dependency.
>
> Solution:
> - Removed the acquisition of `enforce_isolation_mutex` in
> `amdgpu_gfx_enforce_isolation_ring_begin_use` and
> `amdgpu_gfx_enforce_isolation_ring_end_use`.
> - This change ensures that locks are acquired in a consistent order,
> preventing the circular dependency and potential deadlock.
>
> By ensuring consistent lock usage, this fix resolves the issue:
>
> [ 606.297333] ======================================================
> [ 606.297343] WARNING: possible circular locking dependency detected
> [ 606.297353] 6.10.0-amd-mlkd-610-311224-lof #19 Tainted: G OE
> [ 606.297365] ------------------------------------------------------
> [ 606.297375] kworker/u96:3/3825 is trying to acquire lock:
> [ 606.297385] ffff9aa64e431cb8 ((work_completion)(&(&adev->gfx.enforce_isolation[i].work)->work)){+.+.}-{0:0}, at: __flush_work+0x232/0x610
> [ 606.297413]
> but task is already holding lock:
> [ 606.297423] ffff9aa64e432338 (&adev->gfx.kfd_sch_mutex){+.+.}-{3:3}, at: amdgpu_gfx_kfd_sch_ctrl+0x51/0x4d0 [amdgpu]
> [ 606.297725]
> which lock already depends on the new lock.
>
> [ 606.297738]
> the existing dependency chain (in reverse order) is:
> [ 606.297749]
> -> #2 (&adev->gfx.kfd_sch_mutex){+.+.}-{3:3}:
> [ 606.297765] __mutex_lock+0x85/0x930
> [ 606.297776] mutex_lock_nested+0x1b/0x30
> [ 606.297786] amdgpu_gfx_kfd_sch_ctrl+0x51/0x4d0 [amdgpu]
> [ 606.298007] amdgpu_gfx_enforce_isolation_ring_begin_use+0x2a4/0x5d0 [amdgpu]
> [ 606.298225] amdgpu_ring_alloc+0x48/0x70 [amdgpu]
> [ 606.298412] amdgpu_ib_schedule+0x176/0x8a0 [amdgpu]
> [ 606.298603] amdgpu_job_run+0xac/0x1e0 [amdgpu]
> [ 606.298866] drm_sched_run_job_work+0x24f/0x430 [gpu_sched]
> [ 606.298880] process_one_work+0x21e/0x680
> [ 606.298890] worker_thread+0x190/0x350
> [ 606.298899] kthread+0xe7/0x120
> [ 606.298908] ret_from_fork+0x3c/0x60
> [ 606.298919] ret_from_fork_asm+0x1a/0x30
> [ 606.298929]
> -> #1 (&adev->enforce_isolation_mutex){+.+.}-{3:3}:
> [ 606.298947] __mutex_lock+0x85/0x930
> [ 606.298956] mutex_lock_nested+0x1b/0x30
> [ 606.298966] amdgpu_gfx_enforce_isolation_handler+0x87/0x370 [amdgpu]
> [ 606.299190] process_one_work+0x21e/0x680
> [ 606.299199] worker_thread+0x190/0x350
> [ 606.299208] kthread+0xe7/0x120
> [ 606.299217] ret_from_fork+0x3c/0x60
> [ 606.299227] ret_from_fork_asm+0x1a/0x30
> [ 606.299236]
> -> #0 ((work_completion)(&(&adev->gfx.enforce_isolation[i].work)->work)){+.+.}-{0:0}:
> [ 606.299257] __lock_acquire+0x16f9/0x2810
> [ 606.299267] lock_acquire+0xd1/0x300
> [ 606.299276] __flush_work+0x250/0x610
> [ 606.299286] cancel_delayed_work_sync+0x71/0x80
> [ 606.299296] amdgpu_gfx_kfd_sch_ctrl+0x287/0x4d0 [amdgpu]
> [ 606.299509] amdgpu_gfx_enforce_isolation_ring_begin_use+0x2a4/0x5d0 [amdgpu]
> [ 606.299723] amdgpu_ring_alloc+0x48/0x70 [amdgpu]
> [ 606.299909] amdgpu_ib_schedule+0x176/0x8a0 [amdgpu]
> [ 606.300101] amdgpu_job_run+0xac/0x1e0 [amdgpu]
> [ 606.300355] drm_sched_run_job_work+0x24f/0x430 [gpu_sched]
> [ 606.300369] process_one_work+0x21e/0x680
> [ 606.300378] worker_thread+0x190/0x350
> [ 606.300387] kthread+0xe7/0x120
> [ 606.300396] ret_from_fork+0x3c/0x60
> [ 606.300406] ret_from_fork_asm+0x1a/0x30
> [ 606.300416]
> other info that might help us debug this:
>
> [ 606.300428] Chain exists of:
> (work_completion)(&(&adev->gfx.enforce_isolation[i].work)->work) --> &adev->enforce_isolation_mutex --> &adev->gfx.kfd_sch_mutex
>
> [ 606.300458] Possible unsafe locking scenario:
>
> [ 606.300468] CPU0 CPU1
> [ 606.300476] ---- ----
> [ 606.300484] lock(&adev->gfx.kfd_sch_mutex);
> [ 606.300494] lock(&adev->enforce_isolation_mutex);
> [ 606.300508] lock(&adev->gfx.kfd_sch_mutex);
> [ 606.300521] lock((work_completion)(&(&adev->gfx.enforce_isolation[i].work)->work));
> [ 606.300536]
> *** DEADLOCK ***
>
> [ 606.300546] 5 locks held by kworker/u96:3/3825:
> [ 606.300555] #0: ffff9aa5aa1f5d58 ((wq_completion)comp_1.1.0){+.+.}-{0:0}, at: process_one_work+0x3f5/0x680
> [ 606.300577] #1: ffffaa53c3c97e40 ((work_completion)(&sched->work_run_job)){+.+.}-{0:0}, at: process_one_work+0x1d6/0x680
> [ 606.300600] #2: ffff9aa64e463c98 (&adev->enforce_isolation_mutex){+.+.}-{3:3}, at: amdgpu_gfx_enforce_isolation_ring_begin_use+0x1c3/0x5d0 [amdgpu]
> [ 606.300837] #3: ffff9aa64e432338 (&adev->gfx.kfd_sch_mutex){+.+.}-{3:3}, at: amdgpu_gfx_kfd_sch_ctrl+0x51/0x4d0 [amdgpu]
> [ 606.301062] #4: ffffffff8c1a5660 (rcu_read_lock){....}-{1:2}, at: __flush_work+0x70/0x610
> [ 606.301083]
> stack backtrace:
> [ 606.301092] CPU: 14 PID: 3825 Comm: kworker/u96:3 Tainted: G OE 6.10.0-amd-mlkd-610-311224-lof #19
> [ 606.301109] Hardware name: Gigabyte Technology Co., Ltd. X570S GAMING X/X570S GAMING X, BIOS F7 03/22/2024
> [ 606.301124] Workqueue: comp_1.1.0 drm_sched_run_job_work [gpu_sched]
> [ 606.301140] Call Trace:
> [ 606.301146] <TASK>
> [ 606.301154] dump_stack_lvl+0x9b/0xf0
> [ 606.301166] dump_stack+0x10/0x20
> [ 606.301175] print_circular_bug+0x26c/0x340
> [ 606.301187] check_noncircular+0x157/0x170
> [ 606.301197] ? register_lock_class+0x48/0x490
> [ 606.301213] __lock_acquire+0x16f9/0x2810
> [ 606.301230] lock_acquire+0xd1/0x300
> [ 606.301239] ? __flush_work+0x232/0x610
> [ 606.301250] ? srso_alias_return_thunk+0x5/0xfbef5
> [ 606.301261] ? mark_held_locks+0x54/0x90
> [ 606.301274] ? __flush_work+0x232/0x610
> [ 606.301284] __flush_work+0x250/0x610
> [ 606.301293] ? __flush_work+0x232/0x610
> [ 606.301305] ? __pfx_wq_barrier_func+0x10/0x10
> [ 606.301318] ? mark_held_locks+0x54/0x90
> [ 606.301331] ? srso_alias_return_thunk+0x5/0xfbef5
> [ 606.301345] cancel_delayed_work_sync+0x71/0x80
> [ 606.301356] amdgpu_gfx_kfd_sch_ctrl+0x287/0x4d0 [amdgpu]
> [ 606.301661] amdgpu_gfx_enforce_isolation_ring_begin_use+0x2a4/0x5d0 [amdgpu]
> [ 606.302050] ? srso_alias_return_thunk+0x5/0xfbef5
> [ 606.302069] amdgpu_ring_alloc+0x48/0x70 [amdgpu]
> [ 606.302452] amdgpu_ib_schedule+0x176/0x8a0 [amdgpu]
> [ 606.302862] ? drm_sched_entity_error+0x82/0x190 [gpu_sched]
> [ 606.302890] amdgpu_job_run+0xac/0x1e0 [amdgpu]
> [ 606.303366] drm_sched_run_job_work+0x24f/0x430 [gpu_sched]
> [ 606.303388] process_one_work+0x21e/0x680
> [ 606.303409] worker_thread+0x190/0x350
> [ 606.303424] ? __pfx_worker_thread+0x10/0x10
> [ 606.303437] kthread+0xe7/0x120
> [ 606.303449] ? __pfx_kthread+0x10/0x10
> [ 606.303463] ret_from_fork+0x3c/0x60
> [ 606.303476] ? __pfx_kthread+0x10/0x10
> [ 606.303489] ret_from_fork_asm+0x1a/0x30
> [ 606.303512] </TASK>
>
> Fixes: afefd6f24502 ("drm/amdgpu: Implement Enforce Isolation Handler for KGD/KFD serialization")
> Cc: Christian König <christian.koenig at amd.com>
> Cc: Alex Deucher <alexander.deucher at amd.com>
> Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam at amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 4 ----
> 1 file changed, 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> index 6d5d81f0dc4e..89f7c89d1392 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> @@ -2069,12 +2069,10 @@ void amdgpu_gfx_enforce_isolation_ring_begin_use(struct amdgpu_ring *ring)
> /* Don't submit more work until KFD has had some time */
> amdgpu_gfx_enforce_isolation_wait_for_kfd(adev, idx);
>
> - mutex_lock(&adev->enforce_isolation_mutex);
> if (adev->enforce_isolation[idx]) {
> if (adev->kfd.init_complete)
> amdgpu_gfx_kfd_sch_ctrl(adev, idx, false);
> }
> - mutex_unlock(&adev->enforce_isolation_mutex);
I think the proper solution is something like this:
bool sched_work = false;
...
mutex_lock(&adev->enforce_isolation_mutex);
if (adev->enforce_isolation[idx]) {
if (adev->kfd.init_complete)
sched_work = true;
}
mutex_unlock(&adev->enforce_isolation_mutex);
if (sched_work)
amdgpu_gfx_kfd_sch_ctrl(adev, idx, false);
> }
>
> /**
> @@ -2102,12 +2100,10 @@ void amdgpu_gfx_enforce_isolation_ring_end_use(struct amdgpu_ring *ring)
> if (idx >= MAX_XCP)
> return;
>
> - mutex_lock(&adev->enforce_isolation_mutex);
> if (adev->enforce_isolation[idx]) {
> if (adev->kfd.init_complete)
> amdgpu_gfx_kfd_sch_ctrl(adev, idx, true);
> }
> - mutex_unlock(&adev->enforce_isolation_mutex);
Same thing here.
Alex
> }
>
> /*
> --
> 2.34.1
>
More information about the amd-gfx
mailing list