[Mesa-dev] [PATCH 15/14] radeonsi: extend the SDMA L2T VM fault workaround to T2L

Marek Olšák maraeo at gmail.com
Sun May 8 12:10:01 UTC 2016


From: Marek Olšák <marek.olsak at 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



More information about the mesa-dev mailing list