]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/xe: Make dma-fences compliant with the safe access rules
authorTvrtko Ursulin <tvrtko.ursulin@igalia.com>
Tue, 10 Jun 2025 16:42:26 +0000 (17:42 +0100)
committerTvrtko Ursulin <tursulin@ursulin.net>
Fri, 13 Jun 2025 07:28:22 +0000 (08:28 +0100)
Xe can free some of the data pointed to by the dma-fences it exports. Most
notably the timeline name can get freed if userspace closes the associated
submit queue. At the same time the fence could have been exported to a
third party (for example a sync_fence fd) which will then cause an use-
after-free on subsequent access.

To make this safe we need to make the driver compliant with the newly
documented dma-fence rules. Driver has to ensure a RCU grace period
between signalling a fence and freeing any data pointed to by said fence.

For the timeline name we simply make the queue be freed via kfree_rcu and
for the shared lock associated with multiple queues we add a RCU grace
period before freeing the per GT structure holding the lock.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Acked-by: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
Link: https://lore.kernel.org/r/20250610164226.10817-5-tvrtko.ursulin@igalia.com
drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
drivers/gpu/drm/xe/xe_guc_submit.c
drivers/gpu/drm/xe/xe_hw_fence.c

index 4c39f01e4f52864f38f73717c74c016b832e9356..a3f421e2adc03befbf08d149cb4962f010796f01 100644 (file)
@@ -20,6 +20,8 @@ struct xe_exec_queue;
 struct xe_guc_exec_queue {
        /** @q: Backpointer to parent xe_exec_queue */
        struct xe_exec_queue *q;
+       /** @rcu: For safe freeing of exported dma fences */
+       struct rcu_head rcu;
        /** @sched: GPU scheduler for this xe_exec_queue */
        struct xe_gpu_scheduler sched;
        /** @entity: Scheduler entity for this xe_exec_queue */
index 6d84a52b660acfa1eeb33ecc9b7021dac5fc280f..4a9ada5edbca4facfbd3ba82082dc9c3af4fc191 100644 (file)
@@ -1285,7 +1285,11 @@ static void __guc_exec_queue_fini_async(struct work_struct *w)
        xe_sched_entity_fini(&ge->entity);
        xe_sched_fini(&ge->sched);
 
-       kfree(ge);
+       /*
+        * RCU free due sched being exported via DRM scheduler fences
+        * (timeline name).
+        */
+       kfree_rcu(ge, rcu);
        xe_exec_queue_fini(q);
        xe_pm_runtime_put(guc_to_xe(guc));
 }
@@ -1468,6 +1472,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 
        q->guc = ge;
        ge->q = q;
+       init_rcu_head(&ge->rcu);
        init_waitqueue_head(&ge->suspend_wait);
 
        for (i = 0; i < MAX_STATIC_MSG_TYPE; ++i)
index 03eb8c6d16169668f15cdec32440ce3880fc63d7..b2a0c46dfcd4200cf1b444de24c29a3897e22c9a 100644 (file)
@@ -100,6 +100,9 @@ void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq)
                spin_unlock_irqrestore(&irq->lock, flags);
                dma_fence_end_signalling(tmp);
        }
+
+       /* Safe release of the irq->lock used in dma_fence_init. */
+       synchronize_rcu();
 }
 
 void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq)