From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793211633; b=Z3bmQv8InVV5k4SvyMCw5Spbz3XPSpbShetUcv0LGx8U66axHF/YZ++WKb60+sQpcHEw 8B9vTarcxk6ErosyuMLp+JZ7LNTHgZfG56c50tPsa8HPXnv+q1RhSaHfS5y9Wb2FlW2Jg ipIsFNE1TduBO3wHjcTQwQ0lTWmUlaBOqnKExfjFa/j3UXCve4FLjKwU9Ig/hKd6ylYek jbG/u50kzgKu1du7fZTTDrYG1h+DQ85FToZ8xVHckMMShbTB1NfJVyF3YGCI/KFS0HW+o pEiZnSa8pjWav6IJMXmWMhLxxKW3819zKp2GGUQ5dJonBlMahIpyQjJrVxb9GPARFNA== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793211633; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Type:Content-Transfer-Encoding; bh=4pc852fczPqjKml7tfjnzOk4Z1QpaWq4OrgQ8VTM3f4=; b=GQGFfsHkMdP4xRkGjif6nIp0ZHCj8GQJ8yon7AHlGwycqV/z2gFXP+Xe5qOUaEor0Gc3 doMhF4yqBNKagJnTo6ieyACqbBbor0rOeXImHlN/MM5GklxkTUB5w1PlBxRbqF4k7INPH z1nRKeZm4shZDeqcpPZ024hSl3rPCis8BuIwbU6ijEncR4FJt+F3DO7yO7EbVzXaFyqp2 38EoYROKXjh7eS0JUG6TM6k9SzAaIcNcg/fkd907aAE0YEwOy9siMK7MJeiAUdL/oP0PL 4mygQJYlmSNZwCGOAl5AvLPu52OC2gPmHMVtnxNuMY45OucBNFNFiL7dnpG8aerUNYg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=OvQ0rA8l; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2FC3606A31A; Wed, 28 Oct 2026 18:20:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key, unprotected) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=OvQ0rA8l Received: by smtp.kernel.org (Postfix) with ESMTPSA id 077931F01825; Wed, 28 Oct 2026 18:20:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1793211632; bh=4pc852fczPqjKml7tfjnzOk4Z1QpaWq4OrgQ8VTM3f4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=OvQ0rA8lqvPgtTL5/saBN0UVqxqYyVdDB6VyBN6hek9oRJHfVDubfxIU9kDHE/6k7 mp2d3G3gu2Ruv1u5zv1RCweicHuX59IfA2csXM7/P96cNblxuInBoHcyjR2OPPH/pP aLYM4mPaQTev6TmH2C1nxqPaGnfHBq/IMBeqvqww= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, =?UTF-8?q?Christian=20K=C3=B6nig?= , Tom St Denis , Vitaly Prosyak , Mikhail Gavrilov , Alex Deucher , Sasha Levin Subject: [PATCH 5.15 445/571] drm/amdgpu: copy debugfs register data outside the GRBM/SRBM locks Date: Wed, 28 Oct 2026 17:59:52 +0100 Message-ID: <20261028170018.584897721@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261028170008.009143722@linuxfoundation.org> References: <20261028170008.009143722@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: patches@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 5.15-stable review patch. If anyone has any objections, please let me know. ------------------ From: Mikhail Gavrilov [ Upstream commit 16c64495859f13f75602f439588883f2a4a4d6a6 ] Reading or writing a register through the amdgpu_regs2 debugfs file with GRBM bank selection, which umr does for every banked access (a single "umr -b x x x -r " is enough, as is the wave dump with "-O halt_waves"), makes lockdep report a circular locking dependency, after which lockdep stays off until reboot: WARNING: possible circular locking dependency detected umr/63306 is trying to acquire lock: ffff8882cf4b8350 (&mm->mmap_lock){++++}-{4:4}, at: __might_fault+0x9b/0x140 but task is already holding lock: ffff8881aec010d0 (&amdgpu_grbm_lock_key){+.+.}-{4:4}, at: amdgpu_debugfs_regs2_op.isra.0+0x20d/0xd00 [amdgpu] ... Chain exists of: &mm->mmap_lock --> &amdgpu_srbm_lock_key --> &amdgpu_grbm_lock_key ... __might_fault+0xc5/0x140 amdgpu_debugfs_regs2_op.isra.0+0x441/0xd00 [amdgpu] full_proxy_write+0x10e/0x1d0 vfs_write+0x1d0/0xf50 ksys_write+0x116/0x250 amdgpu_debugfs_regs2_op() and amdgpu_debugfs_process_reg_op() call get_user()/put_user() for every dword while holding grbm_idx_mutex or srbm_mutex, and pm.mutex if requested, so a fault there takes mmap_lock inside those locks. The lock hierarchy in amdgpu_lockdep.c puts srbm_mutex and grbm_idx_mutex below notifier_lock, which amdgpu_cs_submit() takes with the BO reservations held, and dma_resv_lockdep() orders the reservations inside mmap_lock. So mmap_lock is outside grbm_idx_mutex and srbm_mutex, and these two debugfs paths nest it the other way round. The copies under the locks are as old as the bank selection in both files; commit 1d0f5838b126 ("drm/amdgpu: Add lockdep annotations for lock ordering validation") only made them visible to lockdep. Copy the user buffer in before any of the locks is taken and the result out after all of them are dropped, as amdgpu_debugfs_wave_read(), amdgpu_debugfs_gpr_read() and amdgpu_debugfs_gprwave_read() already do. The buffer is sized by the count passed to read() or write(), so an access larger than PAGE_SIZE is now rejected with -EINVAL; umr reads and writes one register at a time. A fault on the user buffer of a write now fails with -EFAULT before any register is written, instead of after a partial write. Fixes: 566281595037 ("drm/amd/amdgpu: Add bank selection for MMIO debugfs (v3)") Fixes: 37df9560cd3e ("drm/amd/amdgpu: New debugfs interface for MMIO registers (v5)") Acked-by: Christian König Acked-by: Tom St Denis Reviewed-by: Vitaly Prosyak Signed-off-by: Mikhail Gavrilov Signed-off-by: Alex Deucher (cherry picked from commit ccf9e35ed6811f2c25ba6368e7dc6481da17159d) Cc: stable@vger.kernel.org [ sashal: omitted changes to the absent amdgpu_debugfs_regs2_op() function. ] Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 39 ++++++++++++--------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 944ecf780781e..01320252e5e04 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -73,6 +73,7 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, int r; bool pm_pg_lock, use_bank, use_ring; unsigned instance_bank, sh_bank, se_bank, me, pipe, queue, vmid; + u32 *data __free(kfree) = NULL; pm_pg_lock = use_bank = use_ring = false; instance_bank = sh_bank = se_bank = me = pipe = queue = vmid = 0; @@ -110,6 +111,20 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, *pos &= (1UL << 22) - 1; + if (size > PAGE_SIZE) + return -EINVAL; + + /* + * Access the user buffer only while none of the locks below are held: + * a fault takes mmap_lock, and grbm_idx_mutex and srbm_mutex nest + * inside it. + */ + data = kmalloc(size, GFP_KERNEL); + if (!data) + return -ENOMEM; + if (!read && copy_from_user(data, buf, size)) + return -EFAULT; + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -142,28 +157,16 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, mutex_lock(&adev->pm.mutex); while (size) { - uint32_t value; - - if (read) { - value = RREG32(*pos >> 2); - r = put_user(value, (uint32_t *)buf); - } else { - r = get_user(value, (uint32_t *)buf); - if (!r) - amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value); - } - if (r) { - result = r; - goto end; - } + if (read) + data[result >> 2] = RREG32(*pos >> 2); + else + amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, data[result >> 2]); result += 4; - buf += 4; *pos += 4; size -= 4; } -end: if (use_bank) { amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); @@ -179,6 +182,10 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); + + if (read && copy_to_user(buf, data, result)) + return -EFAULT; + return result; } -- 2.53.0