diff options
author | Rob Clark <robdclark@chromium.org> | 2024-07-08 10:53:57 -0700 |
---|---|---|
committer | Marge Bot <emma+marge@anholt.net> | 2024-07-09 16:44:47 +0000 |
commit | bde26a32e19c8032c09f3c0f336da99c3d913043 (patch) | |
tree | bb9a3e4a1bc8f5ee35bc33816d9356469a7de839 /src/freedreno | |
parent | c77a4e1db7d4916177fc9a98bf54e0c431fb8a21 (diff) |
freedreno/drm: Add rd dumper support
Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30083>
Diffstat (limited to 'src/freedreno')
-rw-r--r-- | src/freedreno/common/freedreno_rd_output.c | 4 | ||||
-rw-r--r-- | src/freedreno/common/freedreno_rd_output.h | 2 | ||||
-rw-r--r-- | src/freedreno/drm/freedreno_bo.c | 3 | ||||
-rw-r--r-- | src/freedreno/drm/freedreno_device.c | 8 | ||||
-rw-r--r-- | src/freedreno/drm/freedreno_priv.h | 4 | ||||
-rw-r--r-- | src/freedreno/drm/msm/msm_priv.h | 87 | ||||
-rw-r--r-- | src/freedreno/drm/msm/msm_ringbuffer_sp.c | 5 |
7 files changed, 108 insertions, 5 deletions
diff --git a/src/freedreno/common/freedreno_rd_output.c b/src/freedreno/common/freedreno_rd_output.c index db42ea5956b..231b6f33c9c 100644 --- a/src/freedreno/common/freedreno_rd_output.c +++ b/src/freedreno/common/freedreno_rd_output.c @@ -70,7 +70,7 @@ fd_rd_output_sanitize_name(char *name) } void -fd_rd_output_init(struct fd_rd_output *output, char* output_name) +fd_rd_output_init(struct fd_rd_output *output, const char* output_name) { const char *test_name = os_get_option("FD_RD_DUMP_TESTNAME"); ASSERTED int name_len; @@ -90,7 +90,7 @@ fd_rd_output_init(struct fd_rd_output *output, char* output_name) output->combine = true; char file_path[PATH_MAX]; - snprintf(file_path, sizeof(file_path), "%s/%s_combined.rd", + snprintf(file_path, sizeof(file_path), "%s/%s_combined.rd.gz", fd_rd_output_base_path, output->name); output->file = gzopen(file_path, "w"); } diff --git a/src/freedreno/common/freedreno_rd_output.h b/src/freedreno/common/freedreno_rd_output.h index 7d597b79ebe..b3d2aebe33e 100644 --- a/src/freedreno/common/freedreno_rd_output.h +++ b/src/freedreno/common/freedreno_rd_output.h @@ -44,7 +44,7 @@ struct fd_rd_output { }; void -fd_rd_output_init(struct fd_rd_output *output, char* output_name); +fd_rd_output_init(struct fd_rd_output *output, const char* output_name); void fd_rd_output_fini(struct fd_rd_output *output); diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index 83d49c37bba..80b5a453d9c 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -640,7 +640,8 @@ fd_bo_map_os_mmap(struct fd_bo *bo) bo->dev->fd, offset); } -static void * +/* For internal use only, does not check FD_BO_NOMAP: */ +void * __fd_bo_map(struct fd_bo *bo) { if (!bo->map) { diff --git a/src/freedreno/drm/freedreno_device.c b/src/freedreno/drm/freedreno_device.c index 7c00b8610a0..f4adf6a543e 100644 --- a/src/freedreno/drm/freedreno_device.c +++ b/src/freedreno/drm/freedreno_device.c @@ -29,6 +29,9 @@ #include <sys/types.h> #include "util/os_file.h" +#include "util/u_process.h" + +#include "freedreno_rd_output.h" #include "freedreno_drmif.h" #include "freedreno_drm_perfetto.h" @@ -91,6 +94,9 @@ out: fd_drm_perfetto_init(); + fd_rd_dump_env_init(); + fd_rd_output_init(&dev->rd, util_get_process_name()); + p_atomic_set(&dev->refcnt, 1); dev->fd = fd; dev->handle_table = @@ -184,6 +190,8 @@ fd_device_del(struct fd_device *dev) if (!unref(&dev->refcnt)) return; + fd_rd_output_fini(&dev->rd); + assert(list_is_empty(&dev->deferred_submits)); assert(!dev->deferred_submits_fence); diff --git a/src/freedreno/drm/freedreno_priv.h b/src/freedreno/drm/freedreno_priv.h index b59629a7ee5..b7686cfc4ab 100644 --- a/src/freedreno/drm/freedreno_priv.h +++ b/src/freedreno/drm/freedreno_priv.h @@ -52,6 +52,7 @@ #include "freedreno_common.h" #include "freedreno_dev_info.h" #include "freedreno_drmif.h" +#include "freedreno_rd_output.h" #include "freedreno_ringbuffer.h" extern simple_mtx_t table_lock; @@ -272,6 +273,8 @@ struct fd_device { simple_mtx_t suballoc_lock; struct util_queue submit_queue; + + struct fd_rd_output rd; }; static inline bool @@ -464,6 +467,7 @@ struct fd_bo_funcs { void fd_bo_add_fence(struct fd_bo *bo, struct fd_fence *fence); void *fd_bo_map_os_mmap(struct fd_bo *bo); +void *__fd_bo_map(struct fd_bo *bo); enum fd_bo_state { FD_BO_STATE_IDLE, diff --git a/src/freedreno/drm/msm/msm_priv.h b/src/freedreno/drm/msm/msm_priv.h index ed9c785420a..c17228f4bb8 100644 --- a/src/freedreno/drm/msm/msm_priv.h +++ b/src/freedreno/drm/msm/msm_priv.h @@ -27,9 +27,12 @@ #ifndef MSM_PRIV_H_ #define MSM_PRIV_H_ +#include "freedreno_drmif.h" #include "freedreno_priv.h" +#include "freedreno_rd_output.h" #include "util/timespec.h" +#include "util/u_process.h" #ifndef __user #define __user @@ -99,6 +102,90 @@ msm_dump_submit(struct drm_msm_gem_submit *req) } } +static inline bool +__should_dump(struct fd_bo *bo) +{ + return (bo->reloc_flags & FD_RELOC_DUMP) || FD_RD_DUMP(FULL); +} + +static inline void +__snapshot_buf(struct fd_rd_output *rd, struct fd_bo *bo, uint64_t iova, + uint32_t size, bool full) +{ + uint64_t offset = 0; + + if (iova) { + offset = iova - fd_bo_get_iova(bo); + } else { + iova = fd_bo_get_iova(bo); + size = bo->size; + } + + fd_rd_output_write_section(rd, RD_GPUADDR, (uint32_t[]){ + iova, size, iova >> 32 + }, 12); + + if (!full) + return; + + const char *buf = __fd_bo_map(bo); + buf += offset; + fd_rd_output_write_section(rd, RD_BUFFER_CONTENTS, buf, size); +} + +static inline void +msm_dump_rd(struct fd_pipe *pipe, struct drm_msm_gem_submit *req) +{ + struct fd_rd_output *rd = &pipe->dev->rd; + + if (!fd_rd_dump_env.flags || !req->nr_cmds || + !fd_rd_output_begin(rd, req->fence)) + return; + + if (FD_RD_DUMP(FULL)) { + fd_pipe_wait(pipe, &(struct fd_fence) { + /* this is cheating a bit, but msm_pipe_wait only needs kfence */ + .kfence = req->fence, + }); + } + + const char *procname = util_get_process_name(); + fd_rd_output_write_section(rd, RD_CHIP_ID, &to_msm_pipe(pipe)->chip_id, 8); + fd_rd_output_write_section(rd, RD_CMD, procname, strlen(procname)); + + struct drm_msm_gem_submit_bo *bos = U642VOID(req->bos); + struct drm_msm_gem_submit_cmd *cmds = U642VOID(req->cmds); + + for (unsigned i = 0; i < req->nr_bos; i++) { + /* This size param to fd_bo_from_handle() only matters if the bo isn't already in + * the handle table. Which it should be. + */ + struct fd_bo *bo = fd_bo_from_handle(pipe->dev, bos[i].handle, 0); + + __snapshot_buf(rd, bo, 0, 0, __should_dump(bo)); + + fd_bo_del(bo); + } + + for (unsigned i = 0; i < req->nr_cmds; i++) { + struct drm_msm_gem_submit_cmd *cmd = &cmds[i]; + struct fd_bo *bo = fd_bo_from_handle(pipe->dev, bos[cmd->submit_idx].handle, 0); + uint64_t iova = fd_bo_get_iova(bo) + cmd->submit_offset; + + /* snapshot cmdstream bo's (if we haven't already): */ + if (!__should_dump(bo)) + __snapshot_buf(rd, bo, iova, cmd->size, true); + + fd_rd_output_write_section(rd, RD_CMDSTREAM_ADDR, (uint32_t[]){ + iova, cmd->size >> 2, iova >> 32 + }, 12); + + fd_bo_del(bo); + } + + fd_rd_output_end(rd); +} + static inline void get_abs_timeout(struct drm_msm_timespec *tv, uint64_t ns) { diff --git a/src/freedreno/drm/msm/msm_ringbuffer_sp.c b/src/freedreno/drm/msm/msm_ringbuffer_sp.c index 36876d4e8ca..b555f8407dd 100644 --- a/src/freedreno/drm/msm/msm_ringbuffer_sp.c +++ b/src/freedreno/drm/msm/msm_ringbuffer_sp.c @@ -31,6 +31,7 @@ #include "util/os_file.h" #include "drm/freedreno_ringbuffer_sp.h" +#include "freedreno_rd_output.h" #include "msm_priv.h" static int @@ -146,7 +147,7 @@ flush_submit_list(struct list_head *submit_list) DEBUG_MSG("nr_cmds=%u, nr_bos=%u", req.nr_cmds, req.nr_bos); - ret = drmCommandWriteRead(msm_pipe->base.dev->fd, DRM_MSM_GEM_SUBMIT, &req, + ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_GEM_SUBMIT, &req, sizeof(req)); if (ret) { ERROR_MSG("submit failed: %d (%s)", ret, strerror(errno)); @@ -156,6 +157,8 @@ flush_submit_list(struct list_head *submit_list) fd_submit->out_fence->fence_fd = req.fence_fd; } + msm_dump_rd(pipe, &req); + if (!bos_on_stack) free(submit_bos); |