From nobody Mon Dec 1 23:05:19 2025 Received: from mail-ej1-f74.google.com (mail-ej1-f74.google.com [209.85.218.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 85F6F32AAA0 for ; Fri, 28 Nov 2025 14:14:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764339273; cv=none; b=S0k1QGOTROF10IDVFJIfEIg2Qm9qNaFTLcYQkJDC0B6ID3HKNWg/iA7UGI0GLanKWj7W2NFq64ONSyHcmbGG6CAGrlUFfQAHj0dnA1oaarmIrNZwlFZ6awH1sdlYD+VLJOnl1jDZ54/tlUPCwOmkZjfDu6A9+OmFyd8QqZesL6U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764339273; c=relaxed/simple; bh=/qKUIi+SwxvR/KkB19A6xZJZbmkfrsHAi66WdDyKSDI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=VUMZCGH2OJw6S5s3lHLQgZjSMLYG0yiu5/XWrFwmBSwVK3F1wrXdRhXzREmShV9/VR9tp5vapS3gqU36pIJvZDjrxLE0vRMtSI+W17W8bZlkBuraUPzNBbanjm0NPCPxBwasna5ePNIgYdE31ya3gWMWHJB4Wwm8IeAHuFNISJs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=xvhaLQFd; arc=none smtp.client-ip=209.85.218.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="xvhaLQFd" Received: by mail-ej1-f74.google.com with SMTP id a640c23a62f3a-b72a8546d73so218929666b.2 for ; Fri, 28 Nov 2025 06:14:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1764339270; x=1764944070; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=xWtS0oeZw0euolNA6rQ3aMYIpi9puV6Ez/UA7Z1Lta8=; b=xvhaLQFdE3/YD+ita5keY8uMuAPAUvjLm1FGn/4gftgVs/aKjnjjzYyNkNULetNumD dP03koFswaD7wp4R4y2nsfaP7VtdJEvvmRS6LEX0xiKyBhPiB91wQ9FhVqXlWTMpJPlj zofSnPOMAk4InT/81HEh4xWRl5ZFd0N40EsQf5vz1lcXCrujVTXF/w47b+WzCtdy5kK5 TQjjI5ESI++9LoPUqS9JV/ad0RCQXDUUl5aLnFOLE6QF89EIlDEP68HTDHJJx3PyqpQA YjO95i+7kK0xSlyC62fH1P7g0EvzwLb+ED4vmJJNJrF9PkOlcxb8E1gjiP6NPPcTheJN tR2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764339270; x=1764944070; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=xWtS0oeZw0euolNA6rQ3aMYIpi9puV6Ez/UA7Z1Lta8=; b=LUOie30ZylOwO4QHtg/jCaVrvbjoxfbN9hWHy6IMb0m/WjjGWiV7I1h+OZ9S1tR2XE oahqlg0zOIf2zn592DJwJ4zzeuAxHtD+Jp1rdcXay+txp7YIRV1cXwWY/tvwTdooR1Wv +gsCm0eGdE/mL9iQVbGRUXBXiY6iFfKVtX3jJci4Nic5PG+jDCQaYeWe364W+zPG3JK6 N4MDRF1EYOt8DfZNilXrcP0sWFz0RJC72adS6DiajkUs49gwxKgArMtXiFw0g11AzbgA MYCM/Mcqxct2ijFRGoKq8xD0QW9xIuNA5t1czZ+fNC6pMAlpF/QMKGaCrTv4e1RAmllo dqcA== X-Forwarded-Encrypted: i=1; AJvYcCV8RqIeP+4ILGtGOESfOdMLew6sFEORecBAUwc/2S1EIoVZQ9L6Tf7wm7007hY37p0ONi5pg++wqr5XCsQ=@vger.kernel.org X-Gm-Message-State: AOJu0YxPgD96Uqo4WzYEOyqi+ezqsb6ZDBLy8eqZVkyJHWf3Aph4WVhs oPrN4mxBp48r7gChE/Cl0mpd3w/S+vVpFz46XwHvN7iqoxIpCFDFpOK824C0bLFbwhSBE0x8N3C nRK8eUqi0NguBmqyi3g== X-Google-Smtp-Source: AGHT+IGQaJ2kOmy5nOC4YD7a97BtA5EiRqES+TvuM8s7S+WqX8zQuzMJ2k3tkR7bnBDkFNa0dTcDwtixlZ7umdo= X-Received: from ejcvx12.prod.google.com ([2002:a17:907:a78c:b0:b73:8115:9bc0]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a17:907:3e86:b0:b73:926e:ddc6 with SMTP id a640c23a62f3a-b76716844c4mr3146435366b.10.1764339269785; Fri, 28 Nov 2025 06:14:29 -0800 (PST) Date: Fri, 28 Nov 2025 14:14:15 +0000 In-Reply-To: <20251128-gpuvm-rust-v1-0-ebf66bf234e0@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20251128-gpuvm-rust-v1-0-ebf66bf234e0@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5831; i=aliceryhl@google.com; h=from:subject:message-id; bh=/qKUIi+SwxvR/KkB19A6xZJZbmkfrsHAi66WdDyKSDI=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBpKa5C3uoY59uKQmVsr8tyT1tCEHUEqwTTsBb9S b5vlFkI0SGJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCaSmuQgAKCRAEWL7uWMY5 RjwLD/9ShES7XKjmh35DZrFV+Fc0z4KMMPJ1JI0Xlzpm9qtAoEKOXw7zgph3m7PfAHtwS5AHPQ5 3r8W+kUOxuw+CD0lhpbFLA8Fx/msauv85WyPkF+YZ+9HR1XAAE5GkAzLyfP0i5kMGVdjOCCe1AI bPuG9iA7pke+Bsfmp6vG7pUpnXbhFzvAQK30KyowCPBdFVrNcVXw0k+t56KpR4rKJRmNFU6F3f9 +ZXane3mLzMGMKIVyR8oRq0QxM2ddQ0BPJLnsobQv1HTyyqR2g/5pOLiDDnvwS+z2i0s6KOSXGh WSusVN9/vKUQkyC9m5+jb7aNRhGclk6KVrM5/445UugiLuD2XpIGDPqjHF2VsIKYqmWOd6PBTX3 V0eAWXixt1Wkgs+jIvSbfftAwV/PD6NdaTlJ1wX2Z6bCMvobI9qw0uxWiUNn2ccJrYE3Y3N839N 492nTEJubXIjfvs7pdcP+XwZANY3nCLLLufUGYVBlJy3wPeSK8p2SrOji0/Ds+VNQkjBZYmbzmK se/FxIy2Kzo8qYRIQ2m5aYl+VKOwVRWGKTUwNZsZyuSpT8bn0eHaK7r1iLSxejhw6BXdscHUkEC WSv0lEHS4sqcRY3gsKZCczzW/gAmw6rYvqvYSzNuPNZx1aDNJ7VHaTnNwvbeNsmn03XTo4bmbEG qZF5uHItgA1JDLg== X-Mailer: b4 0.14.2 Message-ID: <20251128-gpuvm-rust-v1-1-ebf66bf234e0@google.com> Subject: [PATCH 1/4] drm/gpuvm: take GEM lock inside drm_gpuvm_bo_obtain_prealloc() From: Alice Ryhl To: Danilo Krummrich , Daniel Almeida Cc: Matthew Brost , "=?utf-8?q?Thomas_Hellstr=C3=B6m?=" , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Boris Brezillon , Steven Price , Liviu Dudau , Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Trevor Gross , Frank Binns , Matt Coster , Rob Clark , Dmitry Baryshkov , Abhinav Kumar , Jessica Zhang , Sean Paul , Marijn Suijten , Lyude Paul , Lucas De Marchi , Rodrigo Vivi , Sumit Semwal , "=?utf-8?q?Christian_K=C3=B6nig?=" , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org, nouveau@lists.freedesktop.org, intel-xe@lists.freedesktop.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, Alice Ryhl Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable When calling drm_gpuvm_bo_obtain_prealloc() and using immediate mode, this may result in a call to ops->vm_bo_free(vm_bo) while holding the GEMs gpuva mutex. This is a problem if ops->vm_bo_free(vm_bo) performs any operations that are not safe in the fence signalling critical path, and it turns out that Panthor (the only current user of the method) calls drm_gem_shmem_unpin() which takes a resv lock internally. This constitutes both a violation of signalling safety and lock inversion. To fix this, we modify the method to internally take the GEMs gpuva mutex so that the mutex can be unlocked before freeing the preallocated vm_bo. Note that this modification introduces a requirement that the driver uses immediate mode to call drm_gpuvm_bo_obtain_prealloc() as it would otherwise take the wrong lock. Signed-off-by: Alice Ryhl Reviewed-by: Boris Brezillon --- drivers/gpu/drm/drm_gpuvm.c | 58 ++++++++++++++++++++++---------= ---- drivers/gpu/drm/panthor/panthor_mmu.c | 10 ------ 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c index 936e6c1a60c16ed5a6898546bf99e23a74f6b58b..f08a5cc1d611f971862c1272987= e5ecd6d97c163 100644 --- a/drivers/gpu/drm/drm_gpuvm.c +++ b/drivers/gpu/drm/drm_gpuvm.c @@ -1601,14 +1601,37 @@ drm_gpuvm_bo_create(struct drm_gpuvm *gpuvm, } EXPORT_SYMBOL_GPL(drm_gpuvm_bo_create); =20 +static void +drm_gpuvm_bo_destroy_not_in_lists(struct drm_gpuvm_bo *vm_bo) +{ + struct drm_gpuvm *gpuvm =3D vm_bo->vm; + const struct drm_gpuvm_ops *ops =3D gpuvm->ops; + struct drm_gem_object *obj =3D vm_bo->obj; + + if (ops && ops->vm_bo_free) + ops->vm_bo_free(vm_bo); + else + kfree(vm_bo); + + drm_gpuvm_put(gpuvm); + drm_gem_object_put(obj); +} + +static void +drm_gpuvm_bo_destroy_not_in_lists_kref(struct kref *kref) +{ + struct drm_gpuvm_bo *vm_bo =3D container_of(kref, struct drm_gpuvm_bo, + kref); + + drm_gpuvm_bo_destroy_not_in_lists(vm_bo); +} + static void drm_gpuvm_bo_destroy(struct kref *kref) { struct drm_gpuvm_bo *vm_bo =3D container_of(kref, struct drm_gpuvm_bo, kref); struct drm_gpuvm *gpuvm =3D vm_bo->vm; - const struct drm_gpuvm_ops *ops =3D gpuvm->ops; - struct drm_gem_object *obj =3D vm_bo->obj; bool lock =3D !drm_gpuvm_resv_protected(gpuvm); =20 if (!lock) @@ -1617,16 +1640,10 @@ drm_gpuvm_bo_destroy(struct kref *kref) drm_gpuvm_bo_list_del(vm_bo, extobj, lock); drm_gpuvm_bo_list_del(vm_bo, evict, lock); =20 - drm_gem_gpuva_assert_lock_held(gpuvm, obj); + drm_gem_gpuva_assert_lock_held(gpuvm, vm_bo->obj); list_del(&vm_bo->list.entry.gem); =20 - if (ops && ops->vm_bo_free) - ops->vm_bo_free(vm_bo); - else - kfree(vm_bo); - - drm_gpuvm_put(gpuvm); - drm_gem_object_put(obj); + drm_gpuvm_bo_destroy_not_in_lists(vm_bo); } =20 /** @@ -1744,9 +1761,7 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put_deferred); void drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm) { - const struct drm_gpuvm_ops *ops =3D gpuvm->ops; struct drm_gpuvm_bo *vm_bo; - struct drm_gem_object *obj; struct llist_node *bo_defer; =20 bo_defer =3D llist_del_all(&gpuvm->bo_defer); @@ -1765,14 +1780,7 @@ drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuv= m) while (bo_defer) { vm_bo =3D llist_entry(bo_defer, struct drm_gpuvm_bo, list.entry.bo_defer= ); bo_defer =3D bo_defer->next; - obj =3D vm_bo->obj; - if (ops && ops->vm_bo_free) - ops->vm_bo_free(vm_bo); - else - kfree(vm_bo); - - drm_gpuvm_put(gpuvm); - drm_gem_object_put(obj); + drm_gpuvm_bo_destroy_not_in_lists(vm_bo); } } EXPORT_SYMBOL_GPL(drm_gpuvm_bo_deferred_cleanup); @@ -1860,6 +1868,9 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain); * count is decreased. If not found @__vm_bo is returned without further * increase of the reference count. * + * The provided @__vm_bo must not already be in the gpuva, evict, or extobj + * lists prior to calling this method. + * * A new &drm_gpuvm_bo is added to the GEMs gpuva list. * * Returns: a pointer to the found &drm_gpuvm_bo or @__vm_bo if no existing @@ -1872,14 +1883,19 @@ drm_gpuvm_bo_obtain_prealloc(struct drm_gpuvm_bo *_= _vm_bo) struct drm_gem_object *obj =3D __vm_bo->obj; struct drm_gpuvm_bo *vm_bo; =20 + drm_WARN_ON(gpuvm->drm, !drm_gpuvm_immediate_mode(gpuvm)); + + mutex_lock(&obj->gpuva.lock); vm_bo =3D drm_gpuvm_bo_find(gpuvm, obj); if (vm_bo) { - drm_gpuvm_bo_put(__vm_bo); + mutex_unlock(&obj->gpuva.lock); + kref_put(&__vm_bo->kref, drm_gpuvm_bo_destroy_not_in_lists_kref); return vm_bo; } =20 drm_gem_gpuva_assert_lock_held(gpuvm, obj); list_add_tail(&__vm_bo->list.entry.gem, &obj->gpuva.list); + mutex_unlock(&obj->gpuva.lock); =20 return __vm_bo; } diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/pantho= r/panthor_mmu.c index 9f5f4ddf291024121f3fd5644f2fdeba354fa67c..be8811a70e1a3adec87ca4a85ca= d7c838f54bebf 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -1224,17 +1224,7 @@ static int panthor_vm_prepare_map_op_ctx(struct pant= hor_vm_op_ctx *op_ctx, goto err_cleanup; } =20 - /* drm_gpuvm_bo_obtain_prealloc() will call drm_gpuvm_bo_put() on our - * pre-allocated BO if the association exists. Given we - * only have one ref on preallocated_vm_bo, drm_gpuvm_bo_destroy() will - * be called immediately, and we have to hold the VM resv lock when - * calling this function. - */ - dma_resv_lock(panthor_vm_resv(vm), NULL); - mutex_lock(&bo->base.base.gpuva.lock); op_ctx->map.vm_bo =3D drm_gpuvm_bo_obtain_prealloc(preallocated_vm_bo); - mutex_unlock(&bo->base.base.gpuva.lock); - dma_resv_unlock(panthor_vm_resv(vm)); =20 op_ctx->map.bo_offset =3D offset; =20 --=20 2.52.0.487.g5c8c507ade-goog