[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