Skip to content

Commit c6e97e1

Browse files
zackrkerneltoast
authored andcommitted
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 <zackr@vmware.com> Reviewed-by: Martin Krastev <krastevm@vmware.com> Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/20221207172907.959037-1-zack@kde.org
1 parent b7f4256 commit c6e97e1

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
@@ -253,56 +253,23 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
253253
kref_put(&base->refcount, ttm_release_base);
254254
}
255255

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

297-
rcu_read_lock();
298-
ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
263+
spin_lock(&tfile->lock);
264+
ret = ttm_tfile_find_ref(tfile, key, &hash);
299265

300266
if (likely(ret == 0)) {
301267
base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
302268
if (!kref_get_unless_zero(&base->refcount))
303269
base = NULL;
304270
}
305-
rcu_read_unlock();
271+
spin_unlock(&tfile->lock);
272+
306273

307274
return base;
308275
}

drivers/gpu/drm/vmwgfx/ttm_object.h

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

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

drivers/gpu/drm/vmwgfx/vmwgfx_bo.c

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

720-
/**
721-
* vmw_user_bo_noref_lookup - Look up a vmw user buffer object without reference
722-
* @filp: The TTM object file the handle is registered with.
723-
* @handle: The user buffer object handle.
724-
*
725-
* This function looks up a struct vmw_bo and returns a pointer to the
726-
* struct vmw_buffer_object it derives from without refcounting the pointer.
727-
* The returned pointer is only valid until vmw_user_bo_noref_release() is
728-
* called, and the object pointed to by the returned pointer may be doomed.
729-
* Any persistent usage of the object requires a refcount to be taken using
730-
* ttm_bo_reference_unless_doomed(). Iff this function returns successfully it
731-
* needs to be paired with vmw_user_bo_noref_release() and no sleeping-
732-
* or scheduling functions may be called in between these function calls.
733-
*
734-
* Return: A struct vmw_buffer_object pointer if successful or negative
735-
* error pointer on failure.
736-
*/
737-
struct vmw_buffer_object *
738-
vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle)
739-
{
740-
struct vmw_buffer_object *vmw_bo;
741-
struct ttm_buffer_object *bo;
742-
struct drm_gem_object *gobj = drm_gem_object_lookup(filp, handle);
743-
744-
if (!gobj) {
745-
DRM_ERROR("Invalid buffer object handle 0x%08lx.\n",
746-
(unsigned long)handle);
747-
return ERR_PTR(-ESRCH);
748-
}
749-
vmw_bo = gem_to_vmw_bo(gobj);
750-
bo = ttm_bo_get_unless_zero(&vmw_bo->base);
751-
vmw_bo = vmw_buffer_object(bo);
752-
drm_gem_object_put(gobj);
753-
754-
return vmw_bo;
755-
}
756-
757-
758720
/**
759721
* vmw_bo_fence_single - Utility function to fence a single TTM buffer
760722
* 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
@@ -821,12 +821,7 @@ extern int vmw_user_resource_lookup_handle(
821821
uint32_t handle,
822822
const struct vmw_user_resource_conv *converter,
823823
struct vmw_resource **p_res);
824-
extern struct vmw_resource *
825-
vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
826-
struct ttm_object_file *tfile,
827-
uint32_t handle,
828-
const struct vmw_user_resource_conv *
829-
converter);
824+
830825
extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
831826
struct drm_file *file_priv);
832827
extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -865,15 +860,6 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res)
865860
return !RB_EMPTY_NODE(&res->mob_node);
866861
}
867862

868-
/**
869-
* vmw_user_resource_noref_release - release a user resource pointer looked up
870-
* without reference
871-
*/
872-
static inline void vmw_user_resource_noref_release(void)
873-
{
874-
ttm_base_object_noref_release();
875-
}
876-
877863
/**
878864
* Buffer object helper functions - vmwgfx_bo.c
879865
*/
@@ -925,8 +911,6 @@ extern void vmw_bo_unmap(struct vmw_buffer_object *vbo);
925911
extern void vmw_bo_move_notify(struct ttm_buffer_object *bo,
926912
struct ttm_resource *mem);
927913
extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo);
928-
extern struct vmw_buffer_object *
929-
vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle);
930914

931915
/**
932916
* vmw_bo_adjust_prio - Adjust the buffer object eviction priority

0 commit comments

Comments
 (0)