From: Nicolai Hähnle Date: Mon, 20 Jun 2016 15:19:28 +0000 (+0200) Subject: radeon: check VM faults from DMA flush X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d46a9db840b8f82c079a6610723e8a6c519c46cd;p=mesa.git radeon: check VM faults from DMA flush Reviewed-by: Marek Olšák --- diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c index 289fb364963..8b6f3ab58cd 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 78421e34968..fe29f689a77 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -580,6 +580,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 8e16e2906a4..f3bcae94cdc 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 656d435361c..ec45d19353b 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 81ad570edc9..c6e917cf069 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 */