Sound Open Firmware
Loading...
Searching...
No Matches
trace-soflogger.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2016,2024 Intel Corporation.
4 */
5
12#ifndef __SOF_TRACE_TRACE_SOFLOGGER_H__
13#define __SOF_TRACE_TRACE_SOFLOGGER_H__
14
15#if !CONFIG_LIBRARY
16#include <platform/trace/trace.h>
17#endif
18
19#if CONFIG_LIBRARY
20#include <stdio.h>
21#endif
22
23struct sof;
24struct trace;
25struct tr_ctx;
26
32 uint32_t uuid_id;
33 int32_t comp_id;
34 int32_t pipe_id;
35 int32_t log_level;
36};
37
41#define _DECLARE_LOG_ENTRY(lvl, format, comp_class, n_params) \
42 __section(".static_log." #lvl) \
43 static const struct { \
44 uint32_t level; \
45 uint32_t component_class; \
46 uint32_t params_num; \
47 uint32_t line_idx; \
48 uint32_t file_name_len; \
49 uint32_t text_len; \
50 const char file_name[sizeof(RELATIVE_FILE)]; \
51 const char text[sizeof(format)]; \
52 } log_entry = { \
53 lvl, \
54 comp_class, \
55 n_params, \
56 __LINE__, \
57 sizeof(RELATIVE_FILE), \
58 sizeof(format), \
59 RELATIVE_FILE, \
60 format \
61 }
62
63#define _TRACE_EVENT_MAX_ARGUMENT_COUNT 4
64
70static inline struct trace *trace_get(void)
71{
72 return sof_get()->trace;
73}
74
75#include <stdarg.h>
76#include <user/trace.h> /* LOG_LEVEL_... */
77
78/*
79 * trace_event macro definition
80 *
81 * trace_event() macro is used for logging events that occur at runtime.
82 * It comes in 2 main flavours, atomic and non-atomic. Depending of definitions
83 * above, it might also propagate log messages to mbox if desired.
84 *
85 * First argument is always class of event being logged, as defined in
86 * user/trace.h - TRACE_CLASS_* (deprecated - do not use).
87 * Second argument is string literal in printf format, followed by up to 4
88 * parameters (uint32_t), that are used to expand into string fromat when
89 * parsing log data.
90 *
91 * All compile-time accessible data (verbosity, class, source file name, line
92 * index and string literal) are linked into .static_log_entries section
93 * of binary and then extracted by smex, so they do not contribute to loadable
94 * image size. This way more elaborate log messages are possible and encouraged,
95 * for better debugging experience, without worrying about runtime performance.
96 */
97
98/* Map the different trace_xxxx_with_ids(... ) levels to the
99 * _trace_event_with_ids(level_xxxx, ...) macro shared across log
100 * levels.
101 */
102#define trace_event_with_ids(class, ctx, id_1, id_2, format, ...) \
103 _trace_event_with_ids(LOG_LEVEL_INFO, class, ctx, id_1, id_2, \
104 format, ##__VA_ARGS__)
105
106#define trace_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
107 _trace_event_atomic_with_ids(LOG_LEVEL_INFO, class, ctx, id_1, id_2, \
108 format, ##__VA_ARGS__)
109
110#define trace_warn_with_ids(class, ctx, id_1, id_2, format, ...) \
111 _trace_event_with_ids(LOG_LEVEL_WARNING, class, ctx, id_1, id_2, \
112 format, ##__VA_ARGS__)
113
114#define trace_warn_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
115 _trace_event_atomic_with_ids(LOG_LEVEL_WARNING, class, \
116 ctx, id_1, id_2, \
117 format, ##__VA_ARGS__)
118
124
129void trace_on(void);
130
135void trace_off(void);
136
142void trace_init(struct sof *sof);
143
156typedef void (*log_func_t)(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
157 uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args);
158
171void trace_log_filtered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
172 uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args);
173
186void trace_log_unfiltered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
187 uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args);
188
198 struct sof_ipc_trace_filter_elem *end,
199 struct trace_filter *filter);
200
207int trace_filter_update(const struct trace_filter *elem);
208
209#define _trace_event_with_ids(lvl, class, ctx, id_1, id_2, format, ...) \
210 _log_message(trace_log_filtered, false, lvl, class, ctx, id_1, id_2, format, ##__VA_ARGS__)
211
212#define _trace_event_atomic_with_ids(lvl, class, ctx, id_1, id_2, format, ...) \
213 _log_message(trace_log_filtered, true, lvl, class, ctx, id_1, id_2, format, ##__VA_ARGS__)
214
222void mtrace_dict_entry(bool atomic_context, uint32_t log_entry_pointer, int n_args, ...);
223
230void mtrace_event(const char *complete_packet, uint32_t length);
231
232#ifdef CONFIG_TRACEM /* Send everything to shared memory too */
233# ifdef __ZEPHYR__
234/* We don't use Zephyr's dictionary yet so there's not enough space for
235 * DEBUG messages
236 */
237# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_INFO
238# else
239# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_DEBUG
240# endif
241#else /* copy only ERRORS */
242# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_ERROR
243#endif /* CONFIG_TRACEM */
244
257void _log_sofdict(log_func_t sofdict_logf, bool atomic, const void *log_entry,
258 const struct tr_ctx *ctx, const uint32_t lvl,
259 uint32_t id_1, uint32_t id_2, int arg_count, ...);
260
261/* _log_message() */
262
263#ifdef CONFIG_LIBRARY
264
265#include <sys/time.h>
266
267/* trace level used on host configurations */
268extern int host_trace_level;
269
270char *get_trace_class(uint32_t trace_class);
271#define _log_message(ignored_log_func, atomic, level, comp_class, ctx, id_1, id_2, format, ...) \
272do { \
273 (void)ctx; \
274 (void)id_1; \
275 (void)id_2; \
276 struct timeval tv; \
277 char slevel[5][4] = {"dis", "err", "wrn", "inf", "dbg"}; \
278 char *msg = "(%s:%d) " format; \
279 if (level <= host_trace_level) { \
280 gettimeofday(&tv, NULL); \
281 fprintf(stderr, "trace: [%ld.%6.6ld] <%s> ", tv.tv_sec, tv.tv_usec, \
282 slevel[level]); \
283 fprintf(stderr, msg, strrchr(__FILE__, '/') + 1, \
284 __LINE__, ##__VA_ARGS__); \
285 fprintf(stderr, "\n"); \
286 } \
287} while (0)
288
289#define trace_point(x) do {} while (0)
290
291#else /* CONFIG_LIBRARY */
292
293#define trace_point(x) platform_trace_point(x)
294
295#define BASE_LOG_ASSERT_FAIL_MSG \
296unsupported_amount_of_params_in_trace_event\
297_thrown_from_macro_BASE_LOG_in_trace_h
298
299#define CT_ASSERT(COND, MESSAGE) \
300 ((void)sizeof(char[1 - 2 * !(COND)]))
301
302#define trace_check_size_uint32(a) \
303 CT_ASSERT(sizeof(a) <= sizeof(uint32_t), "error: trace argument is bigger than a uint32_t");
304
305#define STATIC_ASSERT_ARG_SIZE(...) \
306 META_MAP(1, trace_check_size_uint32, __VA_ARGS__)
307
313#define _log_message(log_func, atomic, lvl, comp_class, ctx, id_1, id_2, format, ...) \
314do { \
315 _DECLARE_LOG_ENTRY(lvl, format, comp_class, \
316 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)); \
317 STATIC_ASSERT_ARG_SIZE(__VA_ARGS__); \
318 STATIC_ASSERT(_TRACE_EVENT_MAX_ARGUMENT_COUNT >= \
319 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \
320 BASE_LOG_ASSERT_FAIL_MSG \
321 ); \
322 _log_sofdict(log_func, atomic, &log_entry, ctx, lvl, id_1, id_2, \
323 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), ##__VA_ARGS__); \
324 _log_nodict(atomic, META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \
325 lvl, format, ##__VA_ARGS__); \
326} while (0)
327
328#ifdef __ZEPHYR__
329/* Just like XTOS, only the most urgent messages go to limited
330 * shared memory.
331 */
332#define _log_nodict(atomic, arg_count, lvl, format, ...) \
333do { \
334 if ((lvl) <= MTRACE_DUPLICATION_LEVEL) \
335 printk("%llu " format "\n", k_cycle_get_64(), \
336 ##__VA_ARGS__); \
337} while (0)
338#else
339#define _log_nodict(atomic, n_args, lvl, format, ...)
340#endif
341
342#endif /* CONFIG_LIBRARY */
343
344#if CONFIG_TRACEV
345/* Enable tr_dbg() statements by defining tracev_...() */
346#define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...) \
347 _trace_event_with_ids(LOG_LEVEL_VERBOSE, class, \
348 ctx, id_1, id_2, \
349 format, ##__VA_ARGS__)
350
351#define tracev_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
352 _trace_event_atomic_with_ids(LOG_LEVEL_VERBOSE, class, \
353 ctx, id_1, id_2, \
354 format, ##__VA_ARGS__)
355
356#else /* CONFIG_TRACEV */
357#define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...) \
358 trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
359#define tracev_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
360 trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
361
362#endif /* CONFIG_TRACEV */
363
364/* The _error_ level has 2, 1 or 0 backends depending on Kconfig */
365#if CONFIG_TRACEE
366/* LOG_LEVEL_CRITICAL messages are duplicated to the mail box */
367#define _trace_error_with_ids(class, ctx, id_1, id_2, format, ...) \
368 _log_message(trace_log_filtered, true, LOG_LEVEL_CRITICAL, class, ctx, id_1, \
369 id_2, format, ##__VA_ARGS__)
370#define trace_error_with_ids(class, ctx, id_1, id_2, format, ...) \
371 _trace_error_with_ids(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
372#define trace_error_atomic_with_ids(...) trace_error_with_ids(__VA_ARGS__)
373
374#elif CONFIG_TRACE
375/* Goes to trace_log_filtered() too but with a downgraded, LOG_INFO level */
376#define trace_error_with_ids(...) trace_event_with_ids(__VA_ARGS__)
377#define trace_error_atomic_with_ids(...) \
378 trace_event_atomic_with_ids(__VA_ARGS__)
379
380#endif /* CONFIG_TRACEE, CONFIG_TRACE */
381
382/* tracing from device (component, pipeline, dai, ...) */
383
393#define trace_dev_err(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \
394 trace_error_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \
395 get_id_m(dev), get_subid_m(dev), \
396 fmt, ##__VA_ARGS__)
397
399#define trace_dev_warn(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \
400 trace_warn_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \
401 get_id_m(dev), get_subid_m(dev), \
402 fmt, ##__VA_ARGS__)
403
405#define trace_dev_info(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \
406 trace_event_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \
407 get_id_m(dev), get_subid_m(dev), \
408 fmt, ##__VA_ARGS__)
409
411#define trace_dev_dbg(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \
412 tracev_event_with_ids(_TRACE_INV_CLASS, \
413 get_ctx_m(dev), get_id_m(dev), \
414 get_subid_m(dev), fmt, ##__VA_ARGS__)
415
416/* tracing from infrastructure part */
417
418#define tr_err_atomic(ctx, fmt, ...) \
419 trace_error_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
420 _TRACE_INV_ID, _TRACE_INV_ID, \
421 fmt, ##__VA_ARGS__)
422
423#define tr_warn_atomic(ctx, fmt, ...) \
424 trace_warn_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
425 _TRACE_INV_ID, _TRACE_INV_ID, \
426 fmt, ##__VA_ARGS__)
427
428#define tr_info_atomic(ctx, fmt, ...) \
429 trace_event_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
430 _TRACE_INV_ID, _TRACE_INV_ID, \
431 fmt, ##__VA_ARGS__)
432
433#define tr_dbg_atomic(ctx, fmt, ...) \
434 tracev_event_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
435 _TRACE_INV_ID, _TRACE_INV_ID, \
436 fmt, ##__VA_ARGS__)
437
438#define tr_err(ctx, fmt, ...) \
439 trace_error_with_ids(_TRACE_INV_CLASS, ctx, \
440 _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
441
442#define tr_warn(ctx, fmt, ...) \
443 trace_warn_with_ids(_TRACE_INV_CLASS, ctx, \
444 _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
445
446#define tr_info(ctx, fmt, ...) \
447 trace_event_with_ids(_TRACE_INV_CLASS, ctx, \
448 _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
449
450/* tracev_ output depends on CONFIG_TRACEV=y */
451#define tr_dbg(ctx, fmt, ...) \
452 tracev_event_with_ids(_TRACE_INV_CLASS, ctx, \
453 _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
454
464#define mtrace_printf(log_level, format_str, ...) \
465 do { \
466 STATIC_ASSERT(META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__) \
467 <= _TRACE_EVENT_MAX_ARGUMENT_COUNT, \
468 too_many_mtrace_printf_arguments); \
469 _DECLARE_LOG_ENTRY(log_level, format_str, _TRACE_INV_CLASS, \
470 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)); \
471 mtrace_dict_entry(true, (uint32_t)&log_entry, \
472 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \
473 ##__VA_ARGS__); \
474 } while (0)
475
476#endif
void mtrace_event(const char *complete_packet, uint32_t length)
Posts a fully prepared log header and log entry packet to mtrace buffer.
void(* log_func_t)(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args)
Function pointer type for formatted trace logger backends.
Definition trace-soflogger.h:156
void trace_flush_dma_to_mbox(void)
Flush buffered trace data from DMA buffer to Mailbox Window.
void trace_log_unfiltered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args)
Emit an unfiltered dictionary trace message directly to buffers.
void mtrace_dict_entry(bool atomic_context, uint32_t log_entry_pointer, int n_args,...)
Appends one SOF dictionary entry and log statement to shared memory mtrace.
void trace_log_filtered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args)
Emit a filtered dictionary trace message.
void trace_init(struct sof *sof)
Initialize the trace subsystem and allocate global trace buffers.
void _log_sofdict(log_func_t sofdict_logf, bool atomic, const void *log_entry, const struct tr_ctx *ctx, const uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count,...)
Internal dictionary logger formatting and dispatch helper.
struct sof_ipc_trace_filter_elem * trace_filter_fill(struct sof_ipc_trace_filter_elem *elem, struct sof_ipc_trace_filter_elem *end, struct trace_filter *filter)
Populate an IPC trace filter element array.
int trace_filter_update(const struct trace_filter *elem)
Update runtime trace filtering configuration from IPC payload.
void trace_off(void)
Globally pause trace event logging.
static struct trace * trace_get(void)
Retrieve global trace subsystem context from SOF runtime.
Definition trace-soflogger.h:70
void trace_on(void)
Globally resume trace event logging.
struct sof * sof_get(void)
Get the global Sound Open Firmware runtime instance pointer.
User-space ABI log levels and binary trace packet header definitions.
part of sof_ipc_trace_filter, ABI3.17
Definition trace.h:74
General firmware context.
Definition sof.h:50
struct trace * trace
Definition sof.h:67
Definition trace.h:132
Runtime trace filter criteria for components and pipelines.
Definition trace-soflogger.h:31
uint32_t uuid_id
Component UUID type identifier, or 0 for wildcard.
Definition trace-soflogger.h:32
int32_t log_level
Target log level threshold (LOG_LEVEL_*)
Definition trace-soflogger.h:35
int32_t pipe_id
Pipeline ID, or -1 for wildcard.
Definition trace-soflogger.h:34
int32_t comp_id
Component ID, or -1 for wildcard.
Definition trace-soflogger.h:33