Skip to content

Commit a309c71

Browse files
committed
drm/vmwgfx: Remove rcu locks from user resources
User resource lookups used rcu to avoid two extra atomics. Unfortunately the rcu paths were buggy and it was easy to make the driver crash by submitting command buffers from two different threads. Because the lookups never show up in performance profiles replace them with a regular spin lock which fixes the races in accesses to those shared resources. Fixes kernel oops'es in IGT's vmwgfx execution_buffer stress test and seen crashes with apps using shared resources. Fixes: e14c02e ("drm/vmwgfx: Look up objects without taking a reference") Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: Martin Krastev <[email protected]> Reviewed-by: Maaz Mombasawala <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 5253125 commit a309c71

File tree

6 files changed

+87
-233
lines changed

6 files changed

+87
-233
lines changed

drivers/gpu/drm/vmwgfx/ttm_object.c

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -254,56 +254,23 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
254254
kref_put(&base->refcount, ttm_release_base);
255255
}
256256

257-
/**
258-
* ttm_base_object_noref_lookup - look up a base object without reference
259-
* @tfile: The struct ttm_object_file the object is registered with.
260-
* @key: The object handle.
261-
*
262-
* This function looks up a ttm base object and returns a pointer to it
263-
* without refcounting the pointer. The returned pointer is only valid
264-
* until ttm_base_object_noref_release() is called, and the object
265-
* pointed to by the returned pointer may be doomed. Any persistent usage
266-
* of the object requires a refcount to be taken using kref_get_unless_zero().
267-
* Iff this function returns successfully it needs to be paired with
268-
* ttm_base_object_noref_release() and no sleeping- or scheduling functions
269-
* may be called inbetween these function callse.
270-
*
271-
* Return: A pointer to the object if successful or NULL otherwise.
272-
*/
273-
struct ttm_base_object *
274-
ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key)
275-
{
276-
struct vmwgfx_hash_item *hash;
277-
int ret;
278-
279-
rcu_read_lock();
280-
ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
281-
if (ret) {
282-
rcu_read_unlock();
283-
return NULL;
284-
}
285-
286-
__release(RCU);
287-
return hlist_entry(hash, struct ttm_ref_object, hash)->obj;
288-
}
289-
EXPORT_SYMBOL(ttm_base_object_noref_lookup);
290-
291257
struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
292258
uint64_t key)
293259
{
294260
struct ttm_base_object *base = NULL;
295261
struct vmwgfx_hash_item *hash;
296262
int ret;
297263

298-
rcu_read_lock();
299-
ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
264+
spin_lock(&tfile->lock);
265+
ret = ttm_tfile_find_ref(tfile, key, &hash);
300266

301267
if (likely(ret == 0)) {
302268
base = hlist_entry(hash, struct ttm_ref_object, hash)->obj;
303269
if (!kref_get_unless_zero(&base->refcount))
304270
base = NULL;
305271
}
306-
rcu_read_unlock();
272+
spin_unlock(&tfile->lock);
273+
307274

308275
return base;
309276
}

drivers/gpu/drm/vmwgfx/ttm_object.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -307,18 +307,4 @@ extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
307307
#define ttm_prime_object_kfree(__obj, __prime) \
308308
kfree_rcu(__obj, __prime.base.rhead)
309309

310-
struct ttm_base_object *
311-
ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key);
312-
313-
/**
314-
* ttm_base_object_noref_release - release a base object pointer looked up
315-
* without reference
316-
*
317-
* Releases a base object pointer looked up with ttm_base_object_noref_lookup().
318-
*/
319-
static inline void ttm_base_object_noref_release(void)
320-
{
321-
__acquire(RCU);
322-
rcu_read_unlock();
323-
}
324310
#endif

drivers/gpu/drm/vmwgfx/vmwgfx_bo.c

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -715,44 +715,6 @@ int vmw_user_bo_lookup(struct drm_file *filp,
715715
return 0;
716716
}
717717

718-
/**
719-
* vmw_user_bo_noref_lookup - Look up a vmw user buffer object without reference
720-
* @filp: The TTM object file the handle is registered with.
721-
* @handle: The user buffer object handle.
722-
*
723-
* This function looks up a struct vmw_bo and returns a pointer to the
724-
* struct vmw_buffer_object it derives from without refcounting the pointer.
725-
* The returned pointer is only valid until vmw_user_bo_noref_release() is
726-
* called, and the object pointed to by the returned pointer may be doomed.
727-
* Any persistent usage of the object requires a refcount to be taken using
728-
* ttm_bo_reference_unless_doomed(). Iff this function returns successfully it
729-
* needs to be paired with vmw_user_bo_noref_release() and no sleeping-
730-
* or scheduling functions may be called in between these function calls.
731-
*
732-
* Return: A struct vmw_buffer_object pointer if successful or negative
733-
* error pointer on failure.
734-
*/
735-
struct vmw_buffer_object *
736-
vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle)
737-
{
738-
struct vmw_buffer_object *vmw_bo;
739-
struct ttm_buffer_object *bo;
740-
struct drm_gem_object *gobj = drm_gem_object_lookup(filp, handle);
741-
742-
if (!gobj) {
743-
DRM_ERROR("Invalid buffer object handle 0x%08lx.\n",
744-
(unsigned long)handle);
745-
return ERR_PTR(-ESRCH);
746-
}
747-
vmw_bo = gem_to_vmw_bo(gobj);
748-
bo = ttm_bo_get_unless_zero(&vmw_bo->base);
749-
vmw_bo = vmw_buffer_object(bo);
750-
drm_gem_object_put(gobj);
751-
752-
return vmw_bo;
753-
}
754-
755-
756718
/**
757719
* vmw_bo_fence_single - Utility function to fence a single TTM buffer
758720
* object without unreserving it.

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -830,12 +830,7 @@ extern int vmw_user_resource_lookup_handle(
830830
uint32_t handle,
831831
const struct vmw_user_resource_conv *converter,
832832
struct vmw_resource **p_res);
833-
extern struct vmw_resource *
834-
vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
835-
struct ttm_object_file *tfile,
836-
uint32_t handle,
837-
const struct vmw_user_resource_conv *
838-
converter);
833+
839834
extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
840835
struct drm_file *file_priv);
841836
extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -874,15 +869,6 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res)
874869
return !RB_EMPTY_NODE(&res->mob_node);
875870
}
876871

877-
/**
878-
* vmw_user_resource_noref_release - release a user resource pointer looked up
879-
* without reference
880-
*/
881-
static inline void vmw_user_resource_noref_release(void)
882-
{
883-
ttm_base_object_noref_release();
884-
}
885-
886872
/**
887873
* Buffer object helper functions - vmwgfx_bo.c
888874
*/
@@ -934,8 +920,6 @@ extern void vmw_bo_unmap(struct vmw_buffer_object *vbo);
934920
extern void vmw_bo_move_notify(struct ttm_buffer_object *bo,
935921
struct ttm_resource *mem);
936922
extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo);
937-
extern struct vmw_buffer_object *
938-
vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle);
939923

940924
/**
941925
* vmw_bo_adjust_prio - Adjust the buffer object eviction priority

0 commit comments

Comments
 (0)