[PATCH] drm/amd/display: Skip fast cursor updates for fb changes

Wentland, Harry Harry.Wentland at amd.com
Fri Dec 14 19:47:32 UTC 2018


On 2018-12-14 12:26 p.m., Nicholas Kazlauskas wrote:
> [Why]
> The behavior of drm_atomic_helper_cleanup_planes differs depending on
> whether the commit was asynchronous or not. When it's called from
> amdgpu_dm_atomic_commit_tail during a typical atomic commit the
> plane state has been swapped so it calls cleanup_fb on the old plane
> state.
> 
> However, in the asynchronous commit codepath the call to
> drm_atomic_helper_commit also calls dm_plane_helper_cleanup_fb after
> atomic_async_update has been called. Since the plane state is updated
> in place and has not been swapped the cleanup_fb call affects the new
> plane state.
> 
> This results in a use after free for the given sequence:
> 
> - Fast update, fb1 pin/ref, fb1 unpin/unref
> - Fast update, fb2 pin/ref, fb2 unpin/unref
> - Slow update, fb1 pin/ref, fb2 unpin/unref
> - Fast update, fb2 pin/ref -> use after free. bug
> 
> [How]
> Disallow framebuffer changes in the fast path. Since this includes
> a NULL framebuffer, this means that only framebuffers that have
> been previously pin+ref at least once will be used, preventing a
> use after free.
> 
> This has a significant throughput reduction for cursor updates where
> the framebuffer changes. For most desktop usage this isn't a problem,
> but it does introduce performance regressions for two specific IGT
> tests:
> 
> - cursor-vs-flip-toggle
> - cursor-vs-flip-varying-size
> 
> Cc: Leo Li <sunpeng.li at amd.com>
> Cc: Harry Wentland <harry.wentland at amd.com>
> Cc: Michel Dänzer <michel at daenzer.net>
> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>

Reviewed-by: Harry Wentland <harry.wentland at amd.com>

Harry

> ---
>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index d01315965af0..dc1eb9ec2c38 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -3628,10 +3628,20 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
>  static int dm_plane_atomic_async_check(struct drm_plane *plane,
>  				       struct drm_plane_state *new_plane_state)
>  {
> +	struct drm_plane_state *old_plane_state =
> +		drm_atomic_get_old_plane_state(new_plane_state->state, plane);
> +
>  	/* Only support async updates on cursor planes. */
>  	if (plane->type != DRM_PLANE_TYPE_CURSOR)
>  		return -EINVAL;
>  
> +	/*
> +	 * DRM calls prepare_fb and cleanup_fb on new_plane_state for
> +	 * async commits so don't allow fb changes.
> +	 */
> +	if (old_plane_state->fb != new_plane_state->fb)
> +		return -EINVAL;
> +
>  	return 0;
>  }
>  
> 


More information about the amd-gfx mailing list