All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
To: Sean Paul <sean@poorly.run>, Rob Clark <robdclark@gmail.com>
Cc: dri-devel <dri-devel@lists.freedesktop.org>,
	Sean Paul <seanpaul@chromium.org>,
	Rob Clark <robdclark@chromium.org>,
	Maxime Ripard <mripard@kernel.org>,
	David Airlie <airlied@linux.ie>, Daniel Vetter <daniel@ffwll.ch>,
	open list <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference
Date: Mon, 4 Nov 2019 10:29:21 +0100	[thread overview]
Message-ID: <3a67eed5-8be7-df5b-84fa-61b133e1fea2@linux.intel.com> (raw)
In-Reply-To: <CAMavQKKMjge6MwH=-DS5Ngs8ZE5G_x_Vncy+YoqYrC0s0AfX=Q@mail.gmail.com>

Op 01-11-2019 om 21:06 schreef Sean Paul:
> On Fri, Nov 1, 2019 at 2:09 PM Rob Clark <robdclark@gmail.com> wrote:
>> From: Rob Clark <robdclark@chromium.org>
>>
>> drm_self_refresh_helper_update_avg_times() was incorrectly accessing the
>> new incoming state after drm_atomic_helper_commit_hw_done().  But this
>> state might have already been superceeded by an !nonblock atomic update
>> resulting in dereferencing an already free'd crtc_state.
>>
>> Fixes: d4da4e33341c ("drm: Measure Self Refresh Entry/Exit times to avoid thrashing")
>> Cc: Sean Paul <seanpaul@chromium.org>
>> Signed-off-by: Rob Clark <robdclark@chromium.org>
>> ---
>> TODO I *think* this will more or less do the right thing.. althought I'm
>> not 100% sure if, for example, we enter psr in a nonblock commit, and
>> then leave psr in a !nonblock commit that overtakes the completion of
>> the nonblock commit.  Not sure if this sort of scenario can happen in
>> practice.  But not crashing is better than crashing, so I guess we
>> should either take this patch or rever the self-refresh helpers until
>> Sean can figure out a better solution.
>>
>>  drivers/gpu/drm/drm_atomic_helper.c       |  2 ++
>>  drivers/gpu/drm/drm_self_refresh_helper.c | 11 ++++++-----
>>  include/drm/drm_atomic.h                  |  8 ++++++++
>>  3 files changed, 16 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
>> index 3ef2ac52ce94..732bd0ce9241 100644
>> --- a/drivers/gpu/drm/drm_atomic_helper.c
>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
>> @@ -2240,6 +2240,8 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
>>         int i;
>>
>>         for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
>> +               old_state->crtcs[i].new_self_refresh_active = new_crtc_state->self_refresh_active;
>> +
>>                 commit = new_crtc_state->commit;
>>                 if (!commit)
>>                         continue;
>> diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c
>> index 68f4765a5896..77b9079fa578 100644
>> --- a/drivers/gpu/drm/drm_self_refresh_helper.c
>> +++ b/drivers/gpu/drm/drm_self_refresh_helper.c
>> @@ -143,19 +143,20 @@ void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
>>                                               unsigned int commit_time_ms)
>>  {
>>         struct drm_crtc *crtc;
>> -       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>> +       struct drm_crtc_state *old_crtc_state;
>>         int i;
>>
>> -       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
>> -                                     new_crtc_state, i) {
>> +       for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
>> +               bool new_self_refresh_active =
>> +                               state->crtcs[i].new_self_refresh_active;
>>                 struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
>>                 struct ewma_psr_time *time;
>>
>>                 if (old_crtc_state->self_refresh_active ==
>> -                   new_crtc_state->self_refresh_active)
>> +                   new_self_refresh_active)
>>                         continue;
>>
>> -               if (new_crtc_state->self_refresh_active)
>> +               if (new_self_refresh_active)
>>                         time = &sr_data->entry_avg_ms;
>>                 else
>>                         time = &sr_data->exit_avg_ms;
>> diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
>> index 927e1205d7aa..86baf2b38bb3 100644
>> --- a/include/drm/drm_atomic.h
>> +++ b/include/drm/drm_atomic.h
>> @@ -155,6 +155,14 @@ struct __drm_crtcs_state {
>>         struct drm_crtc *ptr;
>>         struct drm_crtc_state *state, *old_state, *new_state;
>>
>> +       /**
>> +        * @new_self_refresh_active:
>> +        *
>> +        * drm_atomic_helper_commit_hw_done() stashes new_crtc_state->self_refresh_active
>> +        * so that it can be accessed late in drm_self_refresh_helper_update_avg_times().
>> +        */
>> +       bool new_self_refresh_active;
>> +
> Instead of stashing this in crtc, we could generate a bitmask local to
> commit_tail and pass that to calc_avg_times? That way we don't have to
> worry about someone using this when they shouldn't

Yeah would make sense to have a bitmask, instead of making the property special. :)

Current solution seems a bit ugly.

WARNING: multiple messages have this Message-ID (diff)
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
To: Sean Paul <sean@poorly.run>, Rob Clark <robdclark@gmail.com>
Cc: Rob Clark <robdclark@chromium.org>,
	David Airlie <airlied@linux.ie>,
	open list <linux-kernel@vger.kernel.org>,
	Sean Paul <seanpaul@chromium.org>,
	dri-devel <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference
Date: Mon, 4 Nov 2019 10:29:21 +0100	[thread overview]
Message-ID: <3a67eed5-8be7-df5b-84fa-61b133e1fea2@linux.intel.com> (raw)
Message-ID: <20191104092921.EhAzQzT_vYjabonk9EvGQie4fQR3wwSCCW8Cq45BgS0@z> (raw)
In-Reply-To: <CAMavQKKMjge6MwH=-DS5Ngs8ZE5G_x_Vncy+YoqYrC0s0AfX=Q@mail.gmail.com>

Op 01-11-2019 om 21:06 schreef Sean Paul:
> On Fri, Nov 1, 2019 at 2:09 PM Rob Clark <robdclark@gmail.com> wrote:
>> From: Rob Clark <robdclark@chromium.org>
>>
>> drm_self_refresh_helper_update_avg_times() was incorrectly accessing the
>> new incoming state after drm_atomic_helper_commit_hw_done().  But this
>> state might have already been superceeded by an !nonblock atomic update
>> resulting in dereferencing an already free'd crtc_state.
>>
>> Fixes: d4da4e33341c ("drm: Measure Self Refresh Entry/Exit times to avoid thrashing")
>> Cc: Sean Paul <seanpaul@chromium.org>
>> Signed-off-by: Rob Clark <robdclark@chromium.org>
>> ---
>> TODO I *think* this will more or less do the right thing.. althought I'm
>> not 100% sure if, for example, we enter psr in a nonblock commit, and
>> then leave psr in a !nonblock commit that overtakes the completion of
>> the nonblock commit.  Not sure if this sort of scenario can happen in
>> practice.  But not crashing is better than crashing, so I guess we
>> should either take this patch or rever the self-refresh helpers until
>> Sean can figure out a better solution.
>>
>>  drivers/gpu/drm/drm_atomic_helper.c       |  2 ++
>>  drivers/gpu/drm/drm_self_refresh_helper.c | 11 ++++++-----
>>  include/drm/drm_atomic.h                  |  8 ++++++++
>>  3 files changed, 16 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
>> index 3ef2ac52ce94..732bd0ce9241 100644
>> --- a/drivers/gpu/drm/drm_atomic_helper.c
>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
>> @@ -2240,6 +2240,8 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
>>         int i;
>>
>>         for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
>> +               old_state->crtcs[i].new_self_refresh_active = new_crtc_state->self_refresh_active;
>> +
>>                 commit = new_crtc_state->commit;
>>                 if (!commit)
>>                         continue;
>> diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c
>> index 68f4765a5896..77b9079fa578 100644
>> --- a/drivers/gpu/drm/drm_self_refresh_helper.c
>> +++ b/drivers/gpu/drm/drm_self_refresh_helper.c
>> @@ -143,19 +143,20 @@ void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
>>                                               unsigned int commit_time_ms)
>>  {
>>         struct drm_crtc *crtc;
>> -       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>> +       struct drm_crtc_state *old_crtc_state;
>>         int i;
>>
>> -       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
>> -                                     new_crtc_state, i) {
>> +       for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
>> +               bool new_self_refresh_active =
>> +                               state->crtcs[i].new_self_refresh_active;
>>                 struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
>>                 struct ewma_psr_time *time;
>>
>>                 if (old_crtc_state->self_refresh_active ==
>> -                   new_crtc_state->self_refresh_active)
>> +                   new_self_refresh_active)
>>                         continue;
>>
>> -               if (new_crtc_state->self_refresh_active)
>> +               if (new_self_refresh_active)
>>                         time = &sr_data->entry_avg_ms;
>>                 else
>>                         time = &sr_data->exit_avg_ms;
>> diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
>> index 927e1205d7aa..86baf2b38bb3 100644
>> --- a/include/drm/drm_atomic.h
>> +++ b/include/drm/drm_atomic.h
>> @@ -155,6 +155,14 @@ struct __drm_crtcs_state {
>>         struct drm_crtc *ptr;
>>         struct drm_crtc_state *state, *old_state, *new_state;
>>
>> +       /**
>> +        * @new_self_refresh_active:
>> +        *
>> +        * drm_atomic_helper_commit_hw_done() stashes new_crtc_state->self_refresh_active
>> +        * so that it can be accessed late in drm_self_refresh_helper_update_avg_times().
>> +        */
>> +       bool new_self_refresh_active;
>> +
> Instead of stashing this in crtc, we could generate a bitmask local to
> commit_tail and pass that to calc_avg_times? That way we don't have to
> worry about someone using this when they shouldn't

Yeah would make sense to have a bitmask, instead of making the property special. :)

Current solution seems a bit ugly.


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  reply	other threads:[~2019-11-04  9:29 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-01 18:07 [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference Rob Clark
2019-11-01 18:07 ` Rob Clark
2019-11-01 18:07 ` Rob Clark
2019-11-01 18:07 ` [PATCH 2/2] drm/atomic: clear new_state pointers at hw_done Rob Clark
2019-11-01 18:07   ` Rob Clark
2019-11-01 18:07   ` Rob Clark
2019-11-01 18:33   ` Maarten Lankhorst
2019-11-01 18:33     ` Maarten Lankhorst
2019-11-01 19:44     ` Rob Clark
2019-11-01 19:44       ` Rob Clark
2019-11-01 19:24   ` Ville Syrjälä
2019-11-01 19:24     ` Ville Syrjälä
2019-11-01 19:49     ` Rob Clark
2019-11-01 19:49       ` Rob Clark
2019-11-01 21:44       ` Ville Syrjälä
2019-11-01 21:44         ` Ville Syrjälä
2019-11-01 22:14         ` Rob Clark
2019-11-01 22:14           ` Rob Clark
2019-11-04 18:41           ` Ville Syrjälä
2019-11-04 18:41             ` Ville Syrjälä
2019-11-04 19:13             ` Rob Clark
2019-11-04 19:13               ` Rob Clark
2019-11-04 20:50               ` Ville Syrjälä
2019-11-04 20:50                 ` Ville Syrjälä
2019-11-04 21:11                 ` Rob Clark
2019-11-04 21:11                   ` Rob Clark
2019-11-06  2:58   ` [drm/atomic] 554231a5c5: BUG:kernel_NULL_pointer_dereference, address kernel test robot
2019-11-06  2:58     ` [drm/atomic] 554231a5c5: BUG:kernel_NULL_pointer_dereference,address kernel test robot
2019-11-06  2:58     ` kernel test robot
2019-11-01 20:06 ` [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference Sean Paul
2019-11-01 20:06   ` Sean Paul
2019-11-04  9:29   ` Maarten Lankhorst [this message]
2019-11-04  9:29     ` Maarten Lankhorst

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=3a67eed5-8be7-df5b-84fa-61b133e1fea2@linux.intel.com \
    --to=maarten.lankhorst@linux.intel.com \
    --cc=airlied@linux.ie \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mripard@kernel.org \
    --cc=robdclark@chromium.org \
    --cc=robdclark@gmail.com \
    --cc=sean@poorly.run \
    --cc=seanpaul@chromium.org \
    /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.