summaryrefslogtreecommitdiff
path: root/src/freedreno
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2024-07-08 10:53:57 -0700
committerMarge Bot <emma+marge@anholt.net>2024-07-09 16:44:47 +0000
commitbde26a32e19c8032c09f3c0f336da99c3d913043 (patch)
treebb9a3e4a1bc8f5ee35bc33816d9356469a7de839 /src/freedreno
parentc77a4e1db7d4916177fc9a98bf54e0c431fb8a21 (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.c4
-rw-r--r--src/freedreno/common/freedreno_rd_output.h2
-rw-r--r--src/freedreno/drm/freedreno_bo.c3
-rw-r--r--src/freedreno/drm/freedreno_device.c8
-rw-r--r--src/freedreno/drm/freedreno_priv.h4
-rw-r--r--src/freedreno/drm/msm/msm_priv.h87
-rw-r--r--src/freedreno/drm/msm/msm_ringbuffer_sp.c5
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);