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>
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user