From ac5a55ef115525d5b8fcade9158fedccea24174a Mon Sep 17 00:00:00 2001 From: Mark Collins Date: Thu, 20 Oct 2022 18:26:47 +0000 Subject: [PATCH] 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 Reviewed-by: Danylo Piliaiev Reviewed-by: Yonggang Luo Ack-by: Chia-I Wu Part-of: --- docs/u_trace.rst | 3 +++ src/util/perf/u_trace.c | 1 + src/util/perf/u_trace.h | 10 ++++++++++ src/util/perf/u_trace.py | 31 ++++++++++++++++++++++++++++++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/u_trace.rst b/docs/u_trace.rst index e7dafc07001..f055e44397c 100644 --- a/docs/u_trace.rst +++ b/docs/u_trace.rst @@ -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`` diff --git a/src/util/perf/u_trace.c b/src/util/perf/u_trace.c index 7ddcfed894b..13af48b9a68 100644 --- a/src/util/perf/u_trace.c +++ b/src/util/perf/u_trace.c @@ -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 }; diff --git a/src/util/perf/u_trace.h b/src/util/perf/u_trace.h index a8c6d2f0306..7b2e9049025 100644 --- a/src/util/perf/u_trace.h +++ b/src/util/perf/u_trace.h @@ -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 diff --git a/src/util/perf/u_trace.py b/src/util/perf/u_trace.py index bbcd942cc7b..521723249da 100644 --- a/src/util/perf/u_trace.py +++ b/src/util/perf/u_trace.py @@ -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