From: "Christian König" <ckoenig.leichtzumerken@gmail.com>
To: thomas.hellstrom@linux.intel.com, dakr@kernel.org,
ecourtney@nvidia.com, matthew.brost@intel.com,
nat@pixelcluster.dev, dri-devel@lists.freedesktop.org,
intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org,
amd-gfx@lists.freedesktop.org
Subject: [PATCH 04/11] drm/gem: Add helper for drm_gem_object resv assignment v2
Date: Thu, 3 Sep 2026 15:27:59 +0200 [thread overview]
Message-ID: <20260903134408.105317-5-christian.koenig@amd.com> (raw)
In-Reply-To: <20260903134408.105317-1-christian.koenig@amd.com>
Introduce drm_gem_object_set_resv() to safely assign reservation objects
to GEM objects with proper reference counting. This helper replaces all
direct assignments to drm_gem_object.resv throughout the DRM subsystem.
The function:
- Acquires a reference to the new resv via dma_resv_get()
- Assigns it to obj->resv
- Releases the old resv reference via dma_resv_put()
This ensures proper reference counting when sharing reservation objects
between GEM objects or when importing dma-bufs, preventing reference
leaks and use-after-free bugs.
Update all drivers to use the new helper:
- drm_prime: dma-buf import path
- drm_gem_shmem_helper: shmem prime import
- i915: dmabuf import
- msm: MSM_BO_NO_SHARE case
- panthor: exclusive_vm case
- virtio: dma-buf import
- xe: dummy object creation
- ttm: external resv assignment
- ttm/tests: test cases
v2: fix cases Sonnet has missed in amdxdna_gem_prime_import(),
qaic_gem_prime_import(), intel_gtt/alloc_pt_lmem() and shmem.rs.
add missing dma_resv_put() into i915_gem_object_fini().
fix error handling in virtgpu_gem_prime_import().
Signed-off-by: Christian König <christian.koenig@amd.com>
Assisted-by: Claude:Sonnet 4
---
drivers/accel/amdxdna/amdxdna_gem.c | 2 +-
drivers/accel/qaic/qaic_data.c | 2 +-
drivers/gpu/drm/drm_gem.c | 31 ++++++++++++++++++-
drivers/gpu/drm/drm_gem_shmem_helper.c | 2 +-
drivers/gpu/drm/drm_prime.c | 2 +-
drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 2 +-
drivers/gpu/drm/i915/gem/i915_gem_object.c | 1 +
drivers/gpu/drm/i915/gt/intel_gtt.c | 2 +-
drivers/gpu/drm/msm/msm_gem.c | 2 +-
drivers/gpu/drm/panthor/panthor_gem.c | 2 +-
drivers/gpu/drm/ttm/tests/ttm_bo_test.c | 2 +-
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c | 2 +-
drivers/gpu/drm/ttm/ttm_bo.c | 7 ++---
drivers/gpu/drm/ttm/ttm_bo_util.c | 1 +
drivers/gpu/drm/virtio/virtgpu_prime.c | 2 +-
drivers/gpu/drm/xe/xe_dma_buf.c | 2 +-
include/drm/drm_gem.h | 2 ++
rust/kernel/drm/gem/shmem.rs | 9 ++++--
18 files changed, 55 insertions(+), 20 deletions(-)
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index 1f190b319bb6..a3e8da88683f 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -886,7 +886,7 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
abo->attach = attach;
abo->dma_buf = dma_buf;
abo->type = AMDXDNA_BO_SHARE;
- gobj->resv = dma_buf->resv;
+ drm_gem_object_set_resv(gobj, dma_buf->resv);
return gobj;
diff --git a/drivers/accel/qaic/qaic_data.c b/drivers/accel/qaic/qaic_data.c
index 4d55531bf1c9..26c23b70c13a 100644
--- a/drivers/accel/qaic/qaic_data.c
+++ b/drivers/accel/qaic/qaic_data.c
@@ -876,7 +876,7 @@ struct drm_gem_object *qaic_gem_prime_import(struct drm_device *dev, struct dma_
obj->funcs = &qaic_gem_funcs;
obj->import_attach = attach;
- obj->resv = dma_buf->resv;
+ drm_gem_object_set_resv(obj, dma_buf->resv);
return obj;
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 48176a11d552..bbcbd25f014f 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -230,7 +230,7 @@ void drm_gem_private_object_init(struct drm_device *dev,
mutex_init(&obj->gpuva.lock);
dma_resv_init(&obj->_resv);
if (!obj->resv)
- obj->resv = &obj->_resv;
+ obj->resv = dma_resv_get(&obj->_resv);
drm_gem_gpuva_init(obj);
@@ -249,11 +249,40 @@ void drm_gem_private_object_fini(struct drm_gem_object *obj)
{
WARN_ON(obj->dma_buf);
+ dma_resv_put(obj->resv);
dma_resv_put(&obj->_resv);
mutex_destroy(&obj->gpuva.lock);
}
EXPORT_SYMBOL(drm_gem_private_object_fini);
+/**
+ * drm_gem_object_set_resv - Set the reservation object for a GEM object
+ * @obj: GEM object
+ * @resv: reservation object to assign
+ *
+ * This function safely assigns a new reservation object to a GEM object.
+ * It releases the old reservation object reference (if any) and acquires
+ * a reference to the new one.
+ *
+ * This should be used when changing the reservation object of an already
+ * initialized GEM object, for example when importing a dma-buf or sharing
+ * a reservation object with another object.
+ *
+ * Returns:
+ * The new reservation object pointer for convenience.
+ */
+struct dma_resv *drm_gem_object_set_resv(struct drm_gem_object *obj,
+ struct dma_resv *resv)
+{
+ struct dma_resv *old_resv = obj->resv;
+
+ obj->resv = dma_resv_get(resv);
+ dma_resv_put(old_resv);
+
+ return obj->resv;
+}
+EXPORT_SYMBOL(drm_gem_object_set_resv);
+
static void drm_gem_object_handle_get(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 22ec52e2ffb8..76a8d7f252e0 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -977,7 +977,7 @@ struct drm_gem_object *drm_gem_shmem_prime_import_no_map(struct drm_device *dev,
drm_dbg_prime(dev, "size = %zu\n", size);
shmem->base.import_attach = attach;
- shmem->base.resv = dma_buf->resv;
+ drm_gem_object_set_resv(&shmem->base, dma_buf->resv);
return &shmem->base;
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 9b44c78cd77f..6cfeca347faf 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -1006,7 +1006,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
}
obj->import_attach = attach;
- obj->resv = dma_buf->resv;
+ drm_gem_object_set_resv(obj, dma_buf->resv);
return obj;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index b43d34c7d641..c824606497d2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -320,7 +320,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
i915_gem_object_init(obj, &i915_gem_object_dmabuf_ops, &lock_class,
I915_BO_ALLOC_USER);
obj->base.import_attach = attach;
- obj->base.resv = dma_buf->resv;
+ drm_gem_object_set_resv(&obj->base, dma_buf->resv);
/* We use GTT as shorthand for a coherent domain, one that is
* neither in the GPU cache nor in the CPU cache, where all
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 1340e8898a86..3f37b0cbb70f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -89,6 +89,7 @@ struct drm_i915_gem_object *i915_gem_object_alloc(void)
void i915_gem_object_free(struct drm_i915_gem_object *obj)
{
+ dma_resv_put(obj->base.resv);
dma_resv_put(&obj->base._resv);
return kmem_cache_free(slab_objects, obj);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c
index 7b1bdb121c88..161e4b73b3df 100644
--- a/drivers/gpu/drm/i915/gt/intel_gtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gtt.c
@@ -62,7 +62,7 @@ struct drm_i915_gem_object *alloc_pt_lmem(struct i915_address_space *vm, int sz)
* them all at once.
*/
if (!IS_ERR(obj)) {
- obj->base.resv = i915_vm_resv_get(vm);
+ drm_gem_object_set_resv(&obj->base, i915_vm_resv_get(vm));
obj->shares_resv_from = vm;
if (vm->fpriv)
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index efd3d3c9a449..81ebb1e1094c 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -1151,7 +1151,7 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
drm_gem_object_get(r_obj);
- obj->resv = r_obj->resv;
+ drm_gem_object_set_resv(obj, r_obj->resv);
}
ret = drm_gem_handle_create(file, obj, handle);
diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
index 9855df738194..2de24f1b6018 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.c
+++ b/drivers/gpu/drm/panthor/panthor_gem.c
@@ -1024,7 +1024,7 @@ panthor_gem_create(struct drm_device *dev, size_t size, uint32_t flags,
if (exclusive_vm) {
bo->exclusive_vm_root_gem = panthor_vm_root_gem(exclusive_vm);
drm_gem_object_get(bo->exclusive_vm_root_gem);
- bo->base.resv = bo->exclusive_vm_root_gem->resv;
+ drm_gem_object_set_resv(&bo->base, bo->exclusive_vm_root_gem->resv);
}
panthor_gem_debugfs_set_usage_flags(bo, usage_flags);
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
index 49b0b48c6c2a..3aff1c427cd1 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
@@ -461,7 +461,7 @@ static void ttm_bo_fini_shared_resv(struct kunit *test)
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
bo->type = ttm_bo_type_device;
- bo->base.resv = external_resv;
+ drm_gem_object_set_resv(&bo->base, external_resv);
ttm_bo_fini(bo);
}
diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
index 5cfe8f3f80d7..1146cc9ae522 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
@@ -181,7 +181,7 @@ struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
bo->base = gem_obj;
if (obj)
- bo->base.resv = obj;
+ drm_gem_object_set_resv(&bo->base, obj);
err = drm_gem_object_init(devs->drm, &bo->base, size);
KUNIT_ASSERT_EQ(test, err, 0);
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 1b9477381a1d..999c24251fb7 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -209,7 +209,7 @@ static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo)
* the resv object while holding the lru_lock.
*/
spin_lock(&bo->bdev->lru_lock);
- bo->base.resv = &bo->base._resv;
+ drm_gem_object_set_resv(&bo->base, &bo->base._resv);
spin_unlock(&bo->bdev->lru_lock);
}
@@ -1197,10 +1197,7 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo,
bo->pin_count = 0;
bo->sg = sg;
bo->bulk_move = NULL;
- if (resv)
- bo->base.resv = resv;
- else
- bo->base.resv = &bo->base._resv;
+ drm_gem_object_set_resv(&bo->base, resv ?: &bo->base._resv);
atomic_inc(&ttm_glob.bo_count);
/*
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index af5732f9e489..e080ce60933e 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -207,6 +207,7 @@ static void ttm_transfered_destroy(struct ttm_buffer_object *bo)
struct ttm_transfer_obj *fbo;
fbo = container_of(bo, struct ttm_transfer_obj, base);
+ dma_resv_put(fbo->base.base.resv);
dma_resv_put(&fbo->base.base._resv);
ttm_bo_put(fbo->bo);
kfree(fbo);
diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c
index 216c77cd0d21..79964b436243 100644
--- a/drivers/gpu/drm/virtio/virtgpu_prime.c
+++ b/drivers/gpu/drm/virtio/virtgpu_prime.c
@@ -361,7 +361,7 @@ struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev,
INIT_LIST_HEAD(&bo->restore_node);
obj = &bo->base.base;
- obj->resv = buf->resv;
+ drm_gem_object_set_resv(obj, buf->resv);
obj->funcs = &virtgpu_gem_dma_buf_funcs;
drm_gem_private_object_init(dev, obj, buf->size);
diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c
index 8a920e58245c..33bebf85ac62 100644
--- a/drivers/gpu/drm/xe/xe_dma_buf.c
+++ b/drivers/gpu/drm/xe/xe_dma_buf.c
@@ -293,7 +293,7 @@ xe_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
if (!dummy_obj)
return ERR_PTR(-ENOMEM);
- dummy_obj->resv = resv;
+ drm_gem_object_set_resv(dummy_obj, resv);
xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {}, ret) {
ret = drm_exec_lock_obj(&exec, dummy_obj);
drm_exec_retry_on_contention(&exec);
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 885244e375d3..09f5ec28218a 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -529,6 +529,8 @@ int drm_gem_object_init(struct drm_device *dev,
void drm_gem_private_object_init(struct drm_device *dev,
struct drm_gem_object *obj, size_t size);
void drm_gem_private_object_fini(struct drm_gem_object *obj);
+struct dma_resv *drm_gem_object_set_resv(struct drm_gem_object *obj,
+ struct dma_resv *resv);
void drm_gem_vm_open(struct vm_area_struct *vma);
void drm_gem_vm_close(struct vm_area_struct *vma);
int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
index 34af402899a0..19a1459a8aca 100644
--- a/rust/kernel/drm/gem/shmem.rs
+++ b/rust/kernel/drm/gem/shmem.rs
@@ -146,8 +146,13 @@ pub fn new(
// Start filling out values from `config`
if let Some(parent_resv) = config.parent_resv_obj {
// SAFETY: We have yet to expose the new gem object outside of this function, so it is
- // safe to modify this field.
- unsafe { (*obj.obj.get()).base.resv = parent_resv.raw_dma_resv() };
+ // safe to call this function to update the resv reference.
+ unsafe {
+ bindings::drm_gem_object_set_resv(
+ &mut (*obj.obj.get()).base,
+ parent_resv.raw_dma_resv(),
+ )
+ };
}
// SAFETY: We have yet to expose this object outside of this function, so we're guaranteed
--
2.43.0
next prev parent reply other threads:[~2026-09-03 13:44 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 13:27 Refcounting dma_resv v3 Christian König
2026-09-03 13:27 ` [PATCH 01/11] drm/i915: fix incorrect RCU teardown order Christian König
2026-09-03 13:27 ` [PATCH 02/11] dma-buf: Add reference counting to dma_resv v2 Christian König
2026-09-03 13:27 ` [PATCH 03/11] dma-buf/tests: Convert st-dma-resv tests to use dma_resv_alloc v2 Christian König
2026-09-03 13:27 ` Christian König [this message]
2026-09-03 13:28 ` [PATCH 05/11] drm/gem: Convert drm_gem_private_object_init to return error code v2 Christian König
2026-09-03 13:28 ` [PATCH 06/11] drm/mode_config: Use dma_resv_alloc for lockdep annotation Christian König
2026-09-03 13:28 ` [PATCH 07/11] drm/xe: " Christian König
2026-09-10 2:22 ` Matthew Brost
2026-09-03 13:28 ` [PATCH 08/11] drm/i915/gt: Use dma_resv_alloc for VM reservation objects v2 Christian König
2026-09-03 13:28 ` [PATCH 09/11] drm/ttm/tests: Use dma_resv_alloc in test files Christian König
2026-09-03 13:28 ` [PATCH 10/11] drm/gem: Use dynamic allocation for GEM object dma_resv Christian König
2026-09-10 3:02 ` Matthew Brost
2026-09-03 13:28 ` [PATCH 11/11] dma-buf: Inline dma_resv_init and remove allocated flag Christian König
2026-09-10 3:23 ` Matthew Brost
2026-09-03 15:10 ` ✗ Fi.CI.BUILD: failure for series starting with [01/11] drm/i915: fix incorrect RCU teardown order Patchwork
2026-09-03 19:38 ` Refcounting dma_resv v3 Matthew Brost
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903134408.105317-5-christian.koenig@amd.com \
--to=ckoenig.leichtzumerken@gmail.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=christian.koenig@amd.com \
--cc=dakr@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=ecourtney@nvidia.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=matthew.brost@intel.com \
--cc=nat@pixelcluster.dev \
--cc=thomas.hellstrom@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.