common/utrace: Add CS logging support

Viewing CS traces retrieved from the driver is common practice to
determine driver bugs but there is no way to determine what
function a certain part of the CS was emitted by. This is crucial
information to determine what function is responsible for emitting
broken CS packets and to help with navigation of the CS trace.

Signed-off-by: Mark Collins <mark@igalia.com>
Reviewed-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Reviewed-by: Yonggang Luo <luoyonggang@gmail.com>
Ack-by: Chia-I Wu <olvaffe@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18271>
This commit is contained in:
Mark Collins 2022-10-20 18:26:47 +00:00 committed by Marge Bot
parent 8370a0d6bf
commit ac5a55ef11
4 changed files with 44 additions and 1 deletions

View File

@ -37,6 +37,9 @@ u_trace is controlled by environment variables:
enables perfetto instrumentation prior to connecting, perfetto
traces can be collected without setting this but it may miss some
events prior to the tracing session being started.
``markers``
enables marker instrumentation, will print utrace markers into
the CS which can then be viewed by dumping the CS from the driver.
:envvar:`MESA_GPU_TRACEFILE`
specifies a file where to write the output instead of ``stdout``

View File

@ -365,6 +365,7 @@ static const struct debug_named_value config_control[] = {
#ifdef HAVE_PERFETTO
{ "perfetto", U_TRACE_TYPE_PERFETTO_ENV, "Enable perfetto" },
#endif
{ "markers", U_TRACE_TYPE_MARKERS, "Enable marker trace"},
DEBUG_NAMED_VALUE_END
};

View File

@ -137,6 +137,7 @@ enum u_trace_type {
U_TRACE_TYPE_JSON = 1u << 1,
U_TRACE_TYPE_PERFETTO_ACTIVE = 1u << 2,
U_TRACE_TYPE_PERFETTO_ENV = 1u << 3,
U_TRACE_TYPE_MARKERS = 1u << 4,
U_TRACE_TYPE_PRINT_JSON = U_TRACE_TYPE_PRINT | U_TRACE_TYPE_JSON,
U_TRACE_TYPE_PERFETTO = U_TRACE_TYPE_PERFETTO_ACTIVE | U_TRACE_TYPE_PERFETTO_ENV,
@ -326,6 +327,15 @@ u_trace_should_process(struct u_trace_context *utctx) {
return p_atomic_read_relaxed(&utctx->enabled_traces) & U_TRACE_TYPE_REQUIRE_PROCESSING;
}
/**
* Return whether to emit markers into the command stream even if the queue
* isn't active.
*/
static ALWAYS_INLINE bool
u_trace_markers_enabled(struct u_trace_context *utctx) {
return p_atomic_read_relaxed(&utctx->enabled_traces) & U_TRACE_TYPE_MARKERS;
}
#ifdef __cplusplus
}
#endif

View File

@ -34,7 +34,7 @@ class Tracepoint(object):
"""
def __init__(self, name, args=[], toggle_name=None,
tp_struct=None, tp_print=None, tp_perfetto=None,
end_of_pipe=False):
tp_markers=None, end_of_pipe=False):
"""Parameters:
- name: the tracepoint name, a tracepoint function with the given
@ -45,6 +45,9 @@ class Tracepoint(object):
- tp_print: (optional) array of format string followed by expressions
- tp_perfetto: (optional) driver provided callback which can generate
perfetto events
- tp_markers: (optional) driver provided printf-style callback which can
generate CS markers, this requires 'need_cs_param' as the first param
is the CS that the label should be emitted into
"""
assert isinstance(name, str)
assert isinstance(args, list)
@ -57,6 +60,7 @@ class Tracepoint(object):
self.tp_struct = tp_struct
self.tp_print = tp_print
self.tp_perfetto = tp_perfetto
self.tp_markers = tp_markers
self.end_of_pipe = end_of_pipe
self.toggle_name = toggle_name
@ -405,6 +409,27 @@ static void __print_json_${trace_name}(FILE *out, const void *arg) {
#define __print_${trace_name} NULL
#define __print_json_${trace_name} NULL
% endif
% if trace.tp_markers is not None:
__attribute__((format(printf, 2, 3))) void ${trace.tp_markers}(void *, const char *, ...);
static void __emit_label_${trace_name}(void *cs, struct trace_${trace_name} *entry) {
${trace.tp_markers}(cs, "${trace_name}("
% for idx,arg in enumerate(trace.tp_struct):
"${"," if idx != 0 else ""}${arg.name}=${arg.c_format}"
% endfor
")"
% for arg in trace.tp_struct:
% if arg.to_prim_type:
,${arg.to_prim_type.format('entry->' + arg.name)}
% else:
,entry->${arg.name}
% endif
% endfor
);
}
% endif
static const struct u_tracepoint __tp_${trace_name} = {
ALIGN_POT(sizeof(struct trace_${trace_name}), 8), /* keep size 64b aligned */
"${trace_name}",
@ -435,6 +460,10 @@ void __trace_${trace_name}(
% for arg in trace.tp_struct:
__entry->${arg.name} = ${arg.var};
% endfor
% if trace.tp_markers is not None:
if (enabled_traces & U_TRACE_TYPE_MARKERS)
__emit_label_${trace_name}(cs, __entry);
% endif
}
% endfor