From: Marek Olšák <marek.ol...@amd.com>

Same algorithm, just applied to T2L.
(and using a 0-based address and surface.bo_size instead of buf->size)
---
 src/gallium/drivers/radeonsi/cik_sdma.c | 108 ++++++++++++++++----------------
 1 file changed, 55 insertions(+), 53 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/cik_sdma.c 
b/src/gallium/drivers/radeonsi/cik_sdma.c
index 17c3a83..cd7b0e6 100644
--- a/src/gallium/drivers/radeonsi/cik_sdma.c
+++ b/src/gallium/drivers/radeonsi/cik_sdma.c
@@ -239,6 +239,7 @@ static bool cik_sdma_copy_texture(struct si_context *sctx,
                struct r600_texture *tiled = src_mode >= RADEON_SURF_MODE_1D ? 
rsrc : rdst;
                struct r600_texture *linear = tiled == rsrc ? rdst : rsrc;
                unsigned tiled_level =  tiled   == rsrc ? src_level : dst_level;
+               unsigned linear_level = linear  == rsrc ? src_level : dst_level;
                unsigned tiled_x =      tiled   == rsrc ? srcx : dstx;
                unsigned linear_x =     linear  == rsrc ? srcx : dstx;
                unsigned tiled_y =      tiled   == rsrc ? srcy : dsty;
@@ -294,62 +295,63 @@ static bool cik_sdma_copy_texture(struct si_context *sctx,
                     tiled_y + copy_height == (1 << 14)))
                        return false;
 
-               /* The hw can read outside of the given linear buffer bounds.
-                * Out-of-bounds reads must be prevented.
+               /* The hw can read outside of the given linear buffer bounds,
+                * or access those pages but not touch the memory in case
+                * of writes. (it still causes a VM fault)
+                *
+                * Out-of-bounds memory access or page directory access must
+                * be prevented.
                 */
-               if (linear == rsrc) {
-                       uint64_t start_linear_address, end_linear_address;
-                       unsigned granularity;
-
-                       /* Deduce the size of reads from the linear surface. */
-                       switch (tiled_micro_mode) {
-                       case V_009910_ADDR_SURF_DISPLAY_MICRO_TILING:
-                               granularity = bpp == 1 ? 64 / (8*bpp) :
-                                                        128 / (8*bpp);
-                               break;
-                       case V_009910_ADDR_SURF_THIN_MICRO_TILING:
-                       case V_009910_ADDR_SURF_DEPTH_MICRO_TILING:
-                               if (0 /* TODO: THICK microtiling */)
-                                       granularity = bpp == 1 ? 32 / (8*bpp) :
-                                                     bpp == 2 ? 64 / (8*bpp) :
-                                                     bpp <= 8 ? 128 / (8*bpp) :
-                                                                256 / (8*bpp);
-                               else
-                                       granularity = bpp <= 2 ? 64 / (8*bpp) :
-                                                     bpp <= 8 ? 128 / (8*bpp) :
-                                                                256 / (8*bpp);
-                               break;
-                       default:
-                               return false;
-                       }
-
-                       /* The linear reads start at tiled_x & ~(granularity - 
1).
-                        * If linear_x == 0 && tiled_x % granularity != 0, the 
hw
-                        * starts reading from an address preceding 
linear_address!!!
-                        */
-                       start_linear_address =
-                               linear_address +
-                               bpp * (linear_z * src_slice_pitch +
-                                      linear_y * src_pitch +
-                                      linear_x -
-                                      tiled_x % granularity);
-
-                       end_linear_address =
-                               linear_address +
-                               bpp * ((linear_z + copy_depth - 1) * 
src_slice_pitch +
-                                      (linear_y + copy_height - 1) * src_pitch 
+
-                                      (linear_x + copy_width));
-
-                       if ((tiled_x + copy_width) % granularity)
-                               end_linear_address += granularity -
-                                                     (tiled_x + copy_width) % 
granularity;
-
-                       if (start_linear_address < linear->resource.gpu_address 
||
-                           end_linear_address > (linear->resource.gpu_address +
-                                                 linear->resource.buf->size))
-                               return false;
+               int64_t start_linear_address, end_linear_address;
+               unsigned granularity;
+
+               /* Deduce the size of reads from the linear surface. */
+               switch (tiled_micro_mode) {
+               case V_009910_ADDR_SURF_DISPLAY_MICRO_TILING:
+                       granularity = bpp == 1 ? 64 / (8*bpp) :
+                                                128 / (8*bpp);
+                       break;
+               case V_009910_ADDR_SURF_THIN_MICRO_TILING:
+               case V_009910_ADDR_SURF_DEPTH_MICRO_TILING:
+                       if (0 /* TODO: THICK microtiling */)
+                               granularity = bpp == 1 ? 32 / (8*bpp) :
+                                             bpp == 2 ? 64 / (8*bpp) :
+                                             bpp <= 8 ? 128 / (8*bpp) :
+                                                        256 / (8*bpp);
+                       else
+                               granularity = bpp <= 2 ? 64 / (8*bpp) :
+                                             bpp <= 8 ? 128 / (8*bpp) :
+                                                        256 / (8*bpp);
+                       break;
+               default:
+                       return false;
                }
 
+               /* The linear reads start at tiled_x & ~(granularity - 1).
+                * If linear_x == 0 && tiled_x % granularity != 0, the hw
+                * starts reading from an address preceding linear_address!!!
+                */
+               start_linear_address =
+                       linear->surface.level[linear_level].offset +
+                       bpp * (linear_z * linear_slice_pitch +
+                              linear_y * linear_pitch +
+                              linear_x);
+               start_linear_address -= (int)(bpp * (tiled_x % granularity));
+
+               end_linear_address =
+                       linear->surface.level[linear_level].offset +
+                       bpp * ((linear_z + copy_depth - 1) * linear_slice_pitch 
+
+                              (linear_y + copy_height - 1) * linear_pitch +
+                              (linear_x + copy_width));
+
+               if ((tiled_x + copy_width) % granularity)
+                       end_linear_address += granularity -
+                                             (tiled_x + copy_width) % 
granularity;
+
+               if (start_linear_address < 0 ||
+                   end_linear_address > linear->surface.bo_size)
+                       return false;
+
                /* Check requirements. */
                if (tiled_address % 256 == 0 &&
                    linear_address % 4 == 0 &&
-- 
2.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to