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