tu: Implement utrace CS marker support

Adds support for emitting utrace markers into the CS, this allows
for useful debug information that can be decoded from a recorded
command stream.

Signed-off-by: Mark Collins <mark@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18271>
This commit is contained in:
Mark Collins 2022-10-20 18:28:33 +00:00 committed by Marge Bot
parent ac5a55ef11
commit d151ba5c30
4 changed files with 113 additions and 4 deletions

View file

@ -39,6 +39,10 @@ extern "C" {
#define CP_TYPE4_PKT 0x40000000
#define CP_TYPE7_PKT 0x70000000
#define CP_NOP_MESG 0x4D455347
#define CP_NOP_BEGN 0x4245474E
#define CP_NOP_END 0x454E4400
/*
* Helpers for pm4 pkt header building/parsing:
*/

View file

@ -435,3 +435,71 @@ tu_cs_reset(struct tu_cs *cs)
cs->entry_count = 0;
}
void
tu_cs_emit_debug_string(struct tu_cs *cs, const char *string, int len)
{
assert(cs->mode == TU_CS_MODE_GROW);
/* max packet size is 0x3fff dwords */
len = MIN2(len, 0x3fff * 4);
tu_cs_emit_pkt7(cs, CP_NOP, align(len, 4) / 4);
const uint32_t *buf = (const uint32_t *) string;
tu_cs_emit_array(cs, buf, len / 4);
buf += len / 4;
len = len % 4;
/* copy remainder bytes without reading past end of input string */
if (len > 0) {
uint32_t w = 0;
memcpy(&w, buf, len);
tu_cs_emit(cs, w);
}
}
void
tu_cs_emit_debug_magic_strv(struct tu_cs *cs,
uint32_t magic,
const char *fmt,
va_list args)
{
int fmt_len = vsnprintf(NULL, 0, fmt, args);
int len = 4 + fmt_len + 1;
char *string = (char *) malloc(len);
/* format: <magic><formatted string>\0 */
*(uint32_t *) string = magic;
vsnprintf(string + 4, fmt_len + 1, fmt, args);
tu_cs_emit_debug_string(cs, string, len);
free(string);
}
__attribute__((format(printf, 2, 3))) void
tu_cs_emit_debug_msg(struct tu_cs *cs, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
tu_cs_emit_debug_magic_strv(cs, CP_NOP_MESG, fmt, args);
va_end(args);
}
void
tu_cs_trace_start(void *cs, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
tu_cs_emit_debug_magic_strv((struct tu_cs *) cs, CP_NOP_BEGN, fmt, args);
va_end(args);
}
void
tu_cs_trace_end(void *cs, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
tu_cs_emit_debug_magic_strv((struct tu_cs *) cs, CP_NOP_END, fmt, args);
va_end(args);
}

View file

@ -375,6 +375,40 @@ tu_cs_emit_call(struct tu_cs *cs, const struct tu_cs *target)
tu_cs_emit_ib(cs, target->entries + i);
}
/**
* Emit a CP_NOP with a string tail into the command stream.
*/
void
tu_cs_emit_debug_string(struct tu_cs *cs, const char *string, int len);
void
tu_cs_emit_debug_magic_strv(struct tu_cs *cs,
uint32_t magic,
const char *fmt,
va_list args);
__attribute__((format(printf, 2, 3))) void
tu_cs_emit_debug_msg(struct tu_cs *cs, const char *fmt, ...);
/**
* Emit a single message into the CS that denote the calling function and any
* optional printf-style parameters when utrace markers are enabled.
*/
#define TU_CS_DEBUG_MSG(CS, FORMAT_STRING, ...) \
do { \
if (unlikely(u_trace_markers_enabled(&(CS)->device->trace_context))) \
tu_cs_emit_debug_msg(CS, "%s(" FORMAT_STRING ")", __func__, \
## __VA_ARGS__); \
} while (0)
typedef struct tu_cs *tu_debug_scope;
__attribute__((format(printf, 2, 3))) void
tu_cs_trace_start(void *cs, const char *fmt, ...);
__attribute__((format(printf, 2, 3))) void
tu_cs_trace_end(void *cs, const char *fmt, ...);
/* Helpers for bracketing a large sequence of commands of unknown size inside
* a CP_COND_REG_EXEC packet.
*/

View file

@ -45,7 +45,8 @@ tu_default_tps = []
#
def begin_end_tp(name, args=[], tp_struct=None, tp_print=None,
tp_default_enabled=True):
tp_default_enabled=True, marker_tp=True,
queue_tp=True):
global tu_default_tps
if tp_default_enabled:
tu_default_tps.append(name)
@ -53,11 +54,13 @@ def begin_end_tp(name, args=[], tp_struct=None, tp_print=None,
toggle_name=name,
args=args,
tp_struct=tp_struct,
tp_perfetto='tu_perfetto_start_{0}'.format(name),
tp_print=tp_print)
tp_perfetto='tu_perfetto_start_{0}'.format(name) if queue_tp else None,
tp_print=tp_print if queue_tp else None,
tp_markers='tu_cs_trace_start' if marker_tp else None)
Tracepoint('end_{0}'.format(name),
toggle_name=name,
tp_perfetto='tu_perfetto_end_{0}'.format(name))
tp_perfetto='tu_perfetto_end_{0}'.format(name),
tp_markers='tu_cs_trace_end' if marker_tp else None)
begin_end_tp('cmd_buffer',
args=[ArgStruct(type='const struct tu_cmd_buffer *', var='cmd')],