[PATCH] drm/radeon: fix tiling and command stream checking on evergreen v3

Jerome Glisse j.glisse at gmail.com
Sat Jun 9 12:26:50 PDT 2012


On Sat, Jun 9, 2012 at 12:15 PM, Boszormenyi Zoltan <zboszor at pr.hu> wrote:
> 2012-06-09 16:57 keltezéssel, j.glisse at gmail.com írta:
>>
>> From: Jerome Glisse<jglisse at redhat.com>
>>
>> Fix regresson since the introduction of command stream checking on
>> evergreen (thread referenced below). Issue is cause by ddx allocating
>> bo with formula width*height*bpp while programming the GPU command
>> stream with ALIGN(height, 8). In some case (where page alignment does
>> not hide the extra size bo should be according to height alignment)
>> the kernel will reject the command stream.
>>
>> This patch reprogram the command stream to slice - 1 (slice is
>> a derivative value from height) which avoid rejecting the command
>> stream while keeping the value of command stream checking from a
>> security point of view.
>>
>> This patch also fix wrong computation of layer size for 2D tiled
>> surface. Which should fix issue when 2D color tiling is enabled.
>> This dump the radeon KMS_DRIVER_MINOR so userspace can know if
>> they are on a fixed kernel or not.
>>
>> https://lkml.org/lkml/2012/6/3/80
>> https://bugs.freedesktop.org/show_bug.cgi?id=50892
>> https://bugs.freedesktop.org/show_bug.cgi?id=50857
>>
>> !!! STABLE need a custom version of this patch for 3.4 !!!
>>
>> v2: actually bump the minor version and add comment about stable
>> v3: do compute the height the ddx was trying to use
>>
>> Signed-off-by: Jerome Glisse<jglisse at redhat.com>
>> ---
>>  drivers/gpu/drm/radeon/evergreen_cs.c |   50
>> ++++++++++++++++++++++++++++++---
>>  drivers/gpu/drm/radeon/radeon_drv.c   |    3 +-
>>  2 files changed, 48 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c
>> b/drivers/gpu/drm/radeon/evergreen_cs.c
>> index 4e7dd2b..29c43c6 100644
>> --- a/drivers/gpu/drm/radeon/evergreen_cs.c
>> +++ b/drivers/gpu/drm/radeon/evergreen_cs.c
>> @@ -52,6 +52,7 @@ struct evergreen_cs_track {
>>        u32                     cb_color_view[12];
>>        u32                     cb_color_pitch[12];
>>        u32                     cb_color_slice[12];
>> +       u32                     cb_color_slice_idx[12];
>>        u32                     cb_color_attrib[12];
>>        u32                     cb_color_cmask_slice[8];/* unused */
>>        u32                     cb_color_fmask_slice[8];/* unused */
>> @@ -127,12 +128,14 @@ static void evergreen_cs_track_init(struct
>> evergreen_cs_track *track)
>>                track->cb_color_info[i] = 0;
>>                track->cb_color_view[i] = 0xFFFFFFFF;
>>                track->cb_color_pitch[i] = 0;
>> -               track->cb_color_slice[i] = 0;
>> +               track->cb_color_slice[i] = 0xfffffff;
>> +               track->cb_color_slice_idx[i] = 0;
>>        }
>>        track->cb_target_mask = 0xFFFFFFFF;
>>        track->cb_shader_mask = 0xFFFFFFFF;
>>        track->cb_dirty = true;
>>
>> +       track->db_depth_slice = 0xffffffff;
>>        track->db_depth_view = 0xFFFFC000;
>>        track->db_depth_size = 0xFFFFFFFF;
>>        track->db_depth_control = 0xFFFFFFFF;
>> @@ -250,10 +253,9 @@ static int evergreen_surface_check_2d(struct
>> radeon_cs_parser *p,
>>  {
>>        struct evergreen_cs_track *track = p->track;
>>        unsigned palign, halign, tileb, slice_pt;
>> +       unsigned mtile_pr, mtile_ps, mtileb;
>>
>>        tileb = 64 * surf->bpe * surf->nsamples;
>> -       palign = track->group_size / (8 * surf->bpe * surf->nsamples);
>> -       palign = MAX(8, palign);
>>        slice_pt = 1;
>>        if (tileb>  surf->tsplit) {
>>                slice_pt = tileb / surf->tsplit;
>> @@ -262,7 +264,10 @@ static int evergreen_surface_check_2d(struct
>> radeon_cs_parser *p,
>>        /* macro tile width&  height */
>>
>>        palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
>>        halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
>> -       surf->layer_size = surf->nbx * surf->nby * surf->bpe * slice_pt;
>> +       mtileb = (palign / 8) * (halign / 8) * tileb;;
>> +       mtile_pr = surf->nbx / palign;
>> +       mtile_ps = (mtile_pr * surf->nby) / halign;
>> +       surf->layer_size = mtile_ps * mtileb * slice_pt;
>>        surf->base_align = (palign / 8) * (halign / 8) * tileb;
>>        surf->palign = palign;
>>        surf->halign = halign;
>> @@ -434,6 +439,39 @@ static int evergreen_cs_track_validate_cb(struct
>> radeon_cs_parser *p, unsigned i
>>
>>        offset += surf.layer_size * mslice;
>>        if (offset>  radeon_bo_size(track->cb_color_bo[id])) {
>> +               /* old ddx are broken they allocate bo with w*h*bpp but
>> +                * program slice with ALIGN(h, 8), catch this and patch
>> +                * command stream.
>> +                */
>> +               if (!surf.mode) {
>> +                       volatile u32 *ib = p->ib.ptr;
>> +                       unsigned long tmp, nby, bsize, size, min = 0;
>> +
>> +                       /* find the height the ddx wants */
>> +                       if (surf.nby>  8) {
>> +                               min = surf.nby - 8;
>> +                       }
>> +                       bsize = radeon_bo_size(track->cb_color_bo[id]);
>> +                       tmp = track->cb_color_bo_offset[id]<<  8;
>> +                       for (nby = surf.nby; nby>  min; nby--) {
>> +                               size = nby * surf.nbx * surf.bpe *
>> surf.nsamples;
>> +                               if ((tmp + size * mslice)<= bsize) {
>> +                                       break;
>> +                               }
>> +                       }
>> +                       if (nby>  min) {
>> +                               surf.nby = nby;
>> +                               slice = ((nby * surf.nbx) / 64) - 1;
>> +                               if (!evergreen_surface_check(p,&surf,
>> "cb")) {
>>
>> +                                       /* check if this one works */
>> +                                       tmp += surf.layer_size * mslice;
>> +                                       if (tmp<= bsize) {
>> +
>> ib[track->cb_color_slice_idx[id]] = slice;
>> +                                               goto old_ddx_ok;
>> +                                       }
>> +                               }
>> +                       }
>> +               }
>>                dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d,
>> "
>>                         "offset %d, max layer %d, bo size %ld, slice
>> %d)\n",
>>                         __func__, __LINE__, id, surf.layer_size,
>> @@ -446,6 +484,7 @@ static int evergreen_cs_track_validate_cb(struct
>> radeon_cs_parser *p, unsigned i
>>                        surf.tsplit, surf.mtilea);
>>                return -EINVAL;
>>        }
>> +old_ddx_ok:
>>
>>        return 0;
>>  }
>> @@ -646,6 +685,7 @@ static int evergreen_cs_track_validate_depth(struct
>> radeon_cs_parser *p)
>>                         track->db_depth_slice, track->db_z_info);
>>                return r;
>>        }
>> +DRM_INFO("%s %d surface nbx,y (%d %d) mode %d format %d surf.tsplit %d
>> banks (%d %d %d) tilea %d\n", __func__, __LINE__, surf.nbx, surf.nby,
>> surf.mode, surf.format, surf.tsplit, surf.nbanks, surf.bankw, surf.bankh,
>> surf.mtilea);
>
>
> This DRM_INFO() is very chatty.
>

This is a debug left over, final commited version don't have it.

Cheers,
Jerome


More information about the dri-devel mailing list