// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com>
*/
/* For debugging crashes, userspace can: * * tail -f /sys/kernel/debug/dri/<minor>/rd > logfile.rd * * to log the cmdstream in a format that is understood by freedreno/cffdump * utility. By comparing the last successfully completed fence #, to the * cmdstream for the next fence, you can narrow down which process and submit * caused the gpu crash/lockup. * * Additionally: * * tail -f /sys/kernel/debug/dri/<minor>/hangrd > logfile.rd * * will capture just the cmdstream from submits which triggered a GPU hang. * * This bypasses drm_debugfs_create_files() mainly because we need to use * our own fops for a bit more control. In particular, we don't want to * do anything if userspace doesn't have the debugfs file open. * * The module-param "rd_full", which defaults to false, enables snapshotting * all (non-written) buffers in the submit, rather than just cmdstream bo's. * This is useful to capture the contents of (for example) vbo's or textures, * or shader programs (if not emitted inline in cmdstream).
*/
while (sz > 0) { char *fptr = &fifo->buf[fifo->head]; int n;
wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open); if (!rd->open) return;
/* Note that smp_load_acquire() is not strictly required * as CIRC_SPACE_TO_END() does not access the tail more * than once.
*/
n = min(sz, circ_space_to_end(&rd->fifo));
memcpy(fptr, ptr, n);
ret = wait_event_interruptible(rd->fifo_event,
circ_count(&rd->fifo) > 0); if (ret) goto out;
/* Note that smp_load_acquire() is not strictly required * as CIRC_CNT_TO_END() does not access the head more than * once.
*/
n = min_t(int, sz, circ_count_to_end(&rd->fifo)); if (copy_to_user(buf, fptr, n)) {
ret = -EFAULT; goto out;
}
/* Reset fifo to clear any previously unread data: */
rd->fifo.head = rd->fifo.tail = 0;
/* the parsing tools need to know gpu-id to know which * register database to load. * * Note: These particular params do not require a context
*/
gpu->funcs->get_param(gpu, NULL, MSM_PARAM_GPU_ID, &val, &zero);
gpu_id = val;
/* * Always write the GPUADDR header so can get a complete list of all the * buffers in the cmd
*/
rd_write_section(rd, RD_GPUADDR,
(uint32_t[3]){ iova, size, iova >> 32 }, 12);
if (!full) return;
buf = msm_gem_get_vaddr_active(obj); if (IS_ERR(buf)) return;
for (i = 0; i < submit->nr_cmds; i++) {
uint64_t iova = submit->cmd[i].iova;
uint32_t szd = submit->cmd[i].size; /* in dwords */
switch (submit->cmd[i].type) { case MSM_SUBMIT_CMD_IB_TARGET_BUF: /* ignore IB-targets, we've logged the buffer, the * parser tool will follow the IB based on the logged * buffer/gpuaddr, so nothing more to do.
*/ break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: case MSM_SUBMIT_CMD_BUF:
rd_write_section(rd, RD_CMDSTREAM_ADDR,
(uint32_t[3]){ iova, szd, iova >> 32 }, 12); break;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.