[Mesa-dev] [PATCH 3/6] radeon: check VM faults from DMA flush

Nicolai Hähnle nhaehnle at gmail.com
Wed Jun 22 09:40:38 UTC 2016


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

---
 src/gallium/drivers/radeon/r600_pipe_common.c | 26 ++++++++++++++++--
 src/gallium/drivers/radeon/r600_pipe_common.h |  4 +++
 src/gallium/drivers/radeonsi/si_debug.c       | 39 +++++++++++++++++++++++++--
 src/gallium/drivers/radeonsi/si_hw_context.c  |  2 +-
 src/gallium/drivers/radeonsi/si_pipe.h        |  3 ++-
 5 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
index ee70a1a..063486c 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -295,11 +295,33 @@ static void r600_flush_dma_ring(void *ctx, unsigned flags,
 {
 	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
 	struct radeon_winsys_cs *cs = rctx->dma.cs;
+	struct radeon_saved_cs saved;
+	bool check_vm =
+		(rctx->screen->debug_flags & DBG_CHECK_VM) &&
+		rctx->check_vm_faults;
+
+	if (!radeon_emitted(cs, 0)) {
+		if (fence)
+			rctx->ws->fence_reference(fence, rctx->last_sdma_fence);
+		return;
+	}
 
-	if (radeon_emitted(cs, 0))
-		rctx->ws->cs_flush(cs, flags, &rctx->last_sdma_fence);
+	if (check_vm)
+		radeon_save_cs(rctx->ws, cs, &saved);
+
+	rctx->ws->cs_flush(cs, flags, &rctx->last_sdma_fence);
 	if (fence)
 		rctx->ws->fence_reference(fence, rctx->last_sdma_fence);
+
+	if (check_vm) {
+		/* Use conservative timeout 800ms, after which we won't wait any
+		 * longer and assume the GPU is hung.
+		 */
+		rctx->ws->fence_wait(rctx->ws, rctx->last_sdma_fence, 800*1000*1000);
+
+		rctx->check_vm_faults(rctx, &saved, RING_DMA);
+		radeon_clear_saved_cs(&saved);
+	}
 }
 
 /**
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index a83908d..1cb881c 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -579,6 +579,10 @@ struct r600_common_context {
 
 	void (*set_atom_dirty)(struct r600_common_context *ctx,
 			       struct r600_atom *atom, bool dirty);
+
+	void (*check_vm_faults)(struct r600_common_context *ctx,
+				struct radeon_saved_cs *saved,
+				enum ring_type ring);
 };
 
 /* r600_buffer.c */
diff --git a/src/gallium/drivers/radeonsi/si_debug.c b/src/gallium/drivers/radeonsi/si_debug.c
index 8e16e29..f3bcae9 100644
--- a/src/gallium/drivers/radeonsi/si_debug.c
+++ b/src/gallium/drivers/radeonsi/si_debug.c
@@ -690,6 +690,26 @@ static void si_dump_debug_state(struct pipe_context *ctx, FILE *f,
 	r600_resource_reference(&sctx->last_trace_buf, NULL);
 }
 
+static void si_dump_dma(struct si_context *sctx,
+			struct radeon_saved_cs *saved, FILE *f)
+{
+	static const char ib_name[] = "sDMA IB";
+	unsigned i;
+
+	si_dump_bo_list(sctx, saved, f);
+
+	fprintf(f, "------------------ %s begin ------------------\n", ib_name);
+
+	for (i = 0; i < saved->num_dw; ++i) {
+		fprintf(f, " %08x\n", saved->ib[i]);
+	}
+
+	fprintf(f, "------------------- %s end -------------------\n", ib_name);
+	fprintf(f, "\n");
+
+	fprintf(f, "SDMA Dump Done.\n");
+}
+
 static bool si_vm_fault_occured(struct si_context *sctx, uint32_t *out_addr)
 {
 	char line[2000];
@@ -768,8 +788,10 @@ static bool si_vm_fault_occured(struct si_context *sctx, uint32_t *out_addr)
 	return fault;
 }
 
-void si_check_vm_faults(struct si_context *sctx)
+void si_check_vm_faults(struct r600_common_context *ctx,
+			struct radeon_saved_cs *saved, enum ring_type ring)
 {
+	struct si_context *sctx = (struct si_context *)ctx;
 	struct pipe_screen *screen = sctx->b.b.screen;
 	FILE *f;
 	uint32_t addr;
@@ -787,7 +809,19 @@ void si_check_vm_faults(struct si_context *sctx)
 	fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
 	fprintf(f, "Failing VM page: 0x%08x\n\n", addr);
 
-	si_dump_debug_state(&sctx->b.b, f, 0);
+	switch (ring) {
+	case RING_GFX:
+		si_dump_debug_state(&sctx->b.b, f, 0);
+		break;
+
+	case RING_DMA:
+		si_dump_dma(sctx, saved, f);
+		break;
+
+	default:
+		break;
+	}
+
 	fclose(f);
 
 	fprintf(stderr, "Detected a VM fault, exiting...\n");
@@ -797,6 +831,7 @@ void si_check_vm_faults(struct si_context *sctx)
 void si_init_debug_functions(struct si_context *sctx)
 {
 	sctx->b.b.dump_debug_state = si_dump_debug_state;
+	sctx->b.check_vm_faults = si_check_vm_faults;
 
 	/* Set the initial dmesg timestamp for this context, so that
 	 * only new messages will be checked for VM faults.
diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c
index 656d435..ec45d19 100644
--- a/src/gallium/drivers/radeonsi/si_hw_context.c
+++ b/src/gallium/drivers/radeonsi/si_hw_context.c
@@ -150,7 +150,7 @@ void si_context_gfx_flush(void *context, unsigned flags,
 		 */
 		ctx->b.ws->fence_wait(ctx->b.ws, ctx->last_gfx_fence, 800*1000*1000);
 
-		si_check_vm_faults(ctx);
+		si_check_vm_faults(&ctx->b, &ctx->last_gfx, RING_GFX);
 	}
 
 	si_begin_new_cs(ctx);
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 81ad570..c6e917c 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -354,7 +354,8 @@ void si_init_cp_dma_functions(struct si_context *sctx);
 
 /* si_debug.c */
 void si_init_debug_functions(struct si_context *sctx);
-void si_check_vm_faults(struct si_context *sctx);
+void si_check_vm_faults(struct r600_common_context *ctx,
+			struct radeon_saved_cs *saved, enum ring_type ring);
 bool si_replace_shader(unsigned num, struct radeon_shader_binary *binary);
 
 /* si_dma.c */
-- 
2.7.4



More information about the mesa-dev mailing list