Module: Mesa Branch: main Commit: a496abf17746b1250e8365742346623d6e67477c URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=a496abf17746b1250e8365742346623d6e67477c
Author: Lionel Landwerlin <[email protected]> Date: Fri Sep 30 17:51:50 2022 +0300 intel/hang_replay: add the ability to pass the context image to sim-drm Signed-off-by: Lionel Landwerlin <[email protected]> Acked-by: Tapani Pälli <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21167> --- src/intel/common/intel_hang_dump.h | 29 +++++--- src/intel/tools/intel_hang_replay.c | 131 +++++++++++++++++++++++++----------- 2 files changed, 110 insertions(+), 50 deletions(-) diff --git a/src/intel/common/intel_hang_dump.h b/src/intel/common/intel_hang_dump.h index 832225d472c..a7fe1f1ebf8 100644 --- a/src/intel/common/intel_hang_dump.h +++ b/src/intel/common/intel_hang_dump.h @@ -36,10 +36,11 @@ #define INTEL_HANG_DUMP_MAGIC (0x4245012345676463) enum intel_hang_dump_block_type { - INTEL_HANG_DUMP_BLOCK_TYPE_HEADER = 1, - INTEL_HANG_DUMP_BLOCK_TYPE_BO = 2, - INTEL_HANG_DUMP_BLOCK_TYPE_MAP = 3, - INTEL_HANG_DUMP_BLOCK_TYPE_EXEC = 4, + INTEL_HANG_DUMP_BLOCK_TYPE_HEADER = 1, + INTEL_HANG_DUMP_BLOCK_TYPE_BO = 2, + INTEL_HANG_DUMP_BLOCK_TYPE_MAP = 3, + INTEL_HANG_DUMP_BLOCK_TYPE_EXEC = 4, + INTEL_HANG_DUMP_BLOCK_TYPE_HW_IMAGE = 5, }; struct intel_hang_dump_block_base { @@ -92,12 +93,22 @@ struct intel_hang_dump_block_exec { uint64_t offset; }; +struct intel_hang_dump_block_hw_image { + struct intel_hang_dump_block_base base; + + /* Buffer size */ + uint64_t size; + + /* Data follows */ +}; + union intel_hang_dump_block_all { - struct intel_hang_dump_block_base base; - struct intel_hang_dump_block_header header; - struct intel_hang_dump_block_bo bo; - struct intel_hang_dump_block_map map; - struct intel_hang_dump_block_exec exec; + struct intel_hang_dump_block_base base; + struct intel_hang_dump_block_header header; + struct intel_hang_dump_block_bo bo; + struct intel_hang_dump_block_map map; + struct intel_hang_dump_block_exec exec; + struct intel_hang_dump_block_hw_image hw_img; }; #endif /* INTEL_HANG_DUMP_H */ diff --git a/src/intel/tools/intel_hang_replay.c b/src/intel/tools/intel_hang_replay.c index b4e270d1c6b..2a34d802db3 100644 --- a/src/intel/tools/intel_hang_replay.c +++ b/src/intel/tools/intel_hang_replay.c @@ -20,6 +20,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * + * Capture the hanging application with INTEL_DEBUG=capture-all + * + * Turn the error state into a replay file with : + * $ intel_error2hangdump error_state + * + * Replay with : + * $ intel_hang_replay -d error_state.dmp */ #include <fcntl.h> @@ -151,6 +158,7 @@ struct gem_bo { uint32_t gem_handle; uint64_t offset; uint64_t size; + bool hw_img; }; static int @@ -272,22 +280,28 @@ main(int argc, char *argv[]) util_dynarray_init(&buffers, mem_ctx); union intel_hang_dump_block_all block_header; - struct intel_hang_dump_block_exec init = {}, exec = {}; + struct intel_hang_dump_block_exec init = { + .offset = -1, + }, exec = { + .offset = -1, + }; while (read(file_fd, &block_header.base, sizeof(block_header.base)) == sizeof(block_header.base)) { static const size_t block_size[] = { - [INTEL_HANG_DUMP_BLOCK_TYPE_HEADER] = sizeof(struct intel_hang_dump_block_header), - [INTEL_HANG_DUMP_BLOCK_TYPE_BO] = sizeof(struct intel_hang_dump_block_bo), - [INTEL_HANG_DUMP_BLOCK_TYPE_MAP] = sizeof(struct intel_hang_dump_block_map), - [INTEL_HANG_DUMP_BLOCK_TYPE_EXEC] = sizeof(struct intel_hang_dump_block_exec), + [INTEL_HANG_DUMP_BLOCK_TYPE_HEADER] = sizeof(struct intel_hang_dump_block_header), + [INTEL_HANG_DUMP_BLOCK_TYPE_BO] = sizeof(struct intel_hang_dump_block_bo), + [INTEL_HANG_DUMP_BLOCK_TYPE_MAP] = sizeof(struct intel_hang_dump_block_map), + [INTEL_HANG_DUMP_BLOCK_TYPE_EXEC] = sizeof(struct intel_hang_dump_block_exec), + [INTEL_HANG_DUMP_BLOCK_TYPE_HW_IMAGE] = sizeof(struct intel_hang_dump_block_hw_image), }; assert(block_header.base.type < ARRAY_SIZE(block_size)); size_t remaining_size = block_size[block_header.base.type] - sizeof(block_header.base); ssize_t ret = read(file_fd, &block_header.base + 1, remaining_size); + bool has_hw_image = false; assert(ret == remaining_size); switch (block_header.base.type) { @@ -298,9 +312,11 @@ main(int argc, char *argv[]) case INTEL_HANG_DUMP_BLOCK_TYPE_BO: { struct gem_bo *bo = util_dynarray_grow(&buffers, struct gem_bo, 1); - bo->file_offset = lseek(file_fd, 0, SEEK_CUR); - bo->offset = block_header.bo.offset; - bo->size = block_header.bo.size; + *bo = (struct gem_bo) { + .file_offset = lseek(file_fd, 0, SEEK_CUR), + .offset = block_header.bo.offset, + .size = block_header.bo.size, + }; total_vma += bo->size; skip_data(file_fd, bo->size); if (list) { @@ -310,11 +326,31 @@ main(int argc, char *argv[]) break; } + case INTEL_HANG_DUMP_BLOCK_TYPE_HW_IMAGE: { + struct gem_bo *bo = util_dynarray_grow(&buffers, struct gem_bo, 1); + *bo = (struct gem_bo) { + .file_offset = lseek(file_fd, 0, SEEK_CUR), + .offset = 0, + .size = block_header.hw_img.size, + .hw_img = true, + }; + total_vma += bo->size; + skip_data(file_fd, bo->size); + if (list) { + fprintf(stderr, "buffer: offset=0x%016lx size=0x%016lx name=hw_img\n", + bo->offset, bo->size); + } + has_hw_image = true; + break; + } + case INTEL_HANG_DUMP_BLOCK_TYPE_MAP: { struct gem_bo *bo = util_dynarray_grow(&buffers, struct gem_bo, 1); - bo->file_offset = 0; - bo->offset = block_header.map.offset; - bo->size = block_header.map.size; + *bo = (struct gem_bo) { + .file_offset = 0, + .offset = block_header.map.offset, + .size = block_header.map.size, + }; total_vma += bo->size; if (list) { fprintf(stderr, "map : offset=0x%016lx size=0x%016lx name=%s\n", @@ -324,7 +360,7 @@ main(int argc, char *argv[]) } case INTEL_HANG_DUMP_BLOCK_TYPE_EXEC: { - if (init.offset == 0) { + if (init.offset == 0 && !has_hw_image) { if (list) fprintf(stderr, "init : offset=0x%016lx\n", block_header.exec.offset); init = block_header.exec; @@ -437,6 +473,9 @@ main(int argc, char *argv[]) EXEC_OBJECT_PINNED, .offset = bo->offset, }; + + if (bo->hw_img) + execbuf_bo->flags |= EXEC_OBJECT_NEEDS_GTT; } assert(batch_bo != NULL); @@ -446,37 +485,47 @@ main(int argc, char *argv[]) int ret; - fprintf(stderr, "init: 0x%016lx\n", init_bo->offset); - *execbuf_bo = (struct drm_i915_gem_exec_object2) { - .handle = init_bo->gem_handle, - .relocation_count = 0, - .relocs_ptr = 0, - .flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS | - EXEC_OBJECT_PINNED | - EXEC_OBJECT_WRITE /* to be able to wait on the BO */, - .offset = init_bo->offset, - }; - ret = execbuffer(drm_fd, &execbuffer_bos, init_bo, init.offset); - if (ret != 0) { - fprintf(stderr, "initialization buffer failed to execute errno=%i\n", errno); - exit(-1); + if (init_bo) { + fprintf(stderr, "init: 0x%016lx\n", init_bo->offset); + *execbuf_bo = (struct drm_i915_gem_exec_object2) { + .handle = init_bo->gem_handle, + .relocation_count = 0, + .relocs_ptr = 0, + .flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS | + EXEC_OBJECT_PINNED | + EXEC_OBJECT_WRITE /* to be able to wait on the BO */, + .offset = init_bo->offset, + }; + ret = execbuffer(drm_fd, &execbuffer_bos, init_bo, init.offset); + if (ret != 0) { + fprintf(stderr, "initialization buffer failed to execute errno=%i\n", errno); + exit(-1); + } + } else { + fprintf(stderr, "no init BO\n"); } - fprintf(stderr, "exec: 0x%016lx aperture=%.2fMb\n", batch_bo->offset, - gem_allocated / 1024.0 / 1024.0); - *execbuf_bo = (struct drm_i915_gem_exec_object2) { - .handle = batch_bo->gem_handle, - .relocation_count = 0, - .relocs_ptr = 0, - .flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS | - EXEC_OBJECT_PINNED | - EXEC_OBJECT_WRITE /* to be able to wait on the BO */, - .offset = batch_bo->offset, - }; - ret = execbuffer(drm_fd, &execbuffer_bos, batch_bo, exec.offset); - if (ret != 0) { - fprintf(stderr, "replayed buffer failed to execute errno=%i\n", errno); - exit(-1); + if (batch_bo) { + fprintf(stderr, "exec: 0x%016lx aperture=%.2fMb\n", batch_bo->offset, + gem_allocated / 1024.0 / 1024.0); + *execbuf_bo = (struct drm_i915_gem_exec_object2) { + .handle = batch_bo->gem_handle, + .relocation_count = 0, + .relocs_ptr = 0, + .flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS | + EXEC_OBJECT_PINNED | + EXEC_OBJECT_WRITE /* to be able to wait on the BO */, + .offset = batch_bo->offset, + }; + ret = execbuffer(drm_fd, &execbuffer_bos, batch_bo, exec.offset); + if (ret != 0) { + fprintf(stderr, "replayed buffer failed to execute errno=%i\n", errno); + exit(-1); + } else { + fprintf(stderr, "exec completed successfully\n"); + } + } else { + fprintf(stderr, "no exec BO\n"); } }
