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
6#ifndef __SOF_TRACE_TRACE_SOFLOGGER_H__
7#define __SOF_TRACE_TRACE_SOFLOGGER_H__
8
9#if !CONFIG_LIBRARY
10#include <platform/trace/trace.h>
11#endif
12
13#if CONFIG_LIBRARY
14#include <stdio.h>
15#endif
16
17struct sof;
18struct trace;
19struct tr_ctx;
20
22 uint32_t uuid_id;
23 int32_t comp_id;
24 int32_t pipe_id;
25 int32_t log_level;
26};
27
31#define _DECLARE_LOG_ENTRY(lvl, format, comp_class, n_params) \
32 __section(".static_log." #lvl) \
33 static const struct { \
34 uint32_t level; \
35 uint32_t component_class; \
36 uint32_t params_num; \
37 uint32_t line_idx; \
38 uint32_t file_name_len; \
39 uint32_t text_len; \
40 const char file_name[sizeof(RELATIVE_FILE)]; \
41 const char text[sizeof(format)]; \
42 } log_entry = { \
43 lvl, \
44 comp_class, \
45 n_params, \
46 __LINE__, \
47 sizeof(RELATIVE_FILE), \
48 sizeof(format), \
49 RELATIVE_FILE, \
50 format \
51 }
52
53#define _TRACE_EVENT_MAX_ARGUMENT_COUNT 4
54
55static inline struct trace *trace_get(void)
56{
57 return sof_get()->trace;
58}
59
60#include <stdarg.h>
61#include <user/trace.h> /* LOG_LEVEL_... */
62
63/*
64 * trace_event macro definition
65 *
66 * trace_event() macro is used for logging events that occur at runtime.
67 * It comes in 2 main flavours, atomic and non-atomic. Depending of definitions
68 * above, it might also propagate log messages to mbox if desired.
69 *
70 * First argument is always class of event being logged, as defined in
71 * user/trace.h - TRACE_CLASS_* (deprecated - do not use).
72 * Second argument is string literal in printf format, followed by up to 4
73 * parameters (uint32_t), that are used to expand into string fromat when
74 * parsing log data.
75 *
76 * All compile-time accessible data (verbosity, class, source file name, line
77 * index and string literal) are linked into .static_log_entries section
78 * of binary and then extracted by smex, so they do not contribute to loadable
79 * image size. This way more elaborate log messages are possible and encouraged,
80 * for better debugging experience, without worrying about runtime performance.
81 */
82
83/* Map the different trace_xxxx_with_ids(... ) levels to the
84 * _trace_event_with_ids(level_xxxx, ...) macro shared across log
85 * levels.
86 */
87#define trace_event_with_ids(class, ctx, id_1, id_2, format, ...) \
88 _trace_event_with_ids(LOG_LEVEL_INFO, class, ctx, id_1, id_2, \
89 format, ##__VA_ARGS__)
90
91#define trace_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
92 _trace_event_atomic_with_ids(LOG_LEVEL_INFO, class, ctx, id_1, id_2, \
93 format, ##__VA_ARGS__)
94
95#define trace_warn_with_ids(class, ctx, id_1, id_2, format, ...) \
96 _trace_event_with_ids(LOG_LEVEL_WARNING, class, ctx, id_1, id_2, \
97 format, ##__VA_ARGS__)
98
99#define trace_warn_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
100 _trace_event_atomic_with_ids(LOG_LEVEL_WARNING, class, \
101 ctx, id_1, id_2, \
102 format, ##__VA_ARGS__)
103
105void trace_on(void);
106void trace_off(void);
107void trace_init(struct sof *sof);
108
109/* All tracing macros in this file end up calling these functions in the end. */
110typedef void (*log_func_t)(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
111 uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args);
112
113void trace_log_filtered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
114 uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args);
115void trace_log_unfiltered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
116 uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args);
118 struct sof_ipc_trace_filter_elem *end,
119 struct trace_filter *filter);
120int trace_filter_update(const struct trace_filter *elem);
121
122#define _trace_event_with_ids(lvl, class, ctx, id_1, id_2, format, ...) \
123 _log_message(trace_log_filtered, false, lvl, class, ctx, id_1, id_2, format, ##__VA_ARGS__)
124
125#define _trace_event_atomic_with_ids(lvl, class, ctx, id_1, id_2, format, ...) \
126 _log_message(trace_log_filtered, true, lvl, class, ctx, id_1, id_2, format, ##__VA_ARGS__)
127
137void mtrace_dict_entry(bool atomic_context, uint32_t log_entry_pointer, int n_args, ...);
138
140void mtrace_event(const char *complete_packet, uint32_t length);
141
142#ifdef CONFIG_TRACEM /* Send everything to shared memory too */
143# ifdef __ZEPHYR__
144/* We don't use Zephyr's dictionary yet so there's not enough space for
145 * DEBUG messages
146 */
147# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_INFO
148# else
149# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_DEBUG
150# endif
151#else /* copy only ERRORS */
152# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_ERROR
153#endif /* CONFIG_TRACEM */
154
155/* This function is _not_ passed the format string to save space */
156void _log_sofdict(log_func_t sofdict_logf, bool atomic, const void *log_entry,
157 const struct tr_ctx *ctx, const uint32_t lvl,
158 uint32_t id_1, uint32_t id_2, int arg_count, ...);
159
160/* _log_message() */
161
162#ifdef CONFIG_LIBRARY
163
164#include <sys/time.h>
165
166/* trace level used on host configurations */
167extern int host_trace_level;
168
169char *get_trace_class(uint32_t trace_class);
170#define _log_message(ignored_log_func, atomic, level, comp_class, ctx, id_1, id_2, format, ...) \
171do { \
172 (void)ctx; \
173 (void)id_1; \
174 (void)id_2; \
175 struct timeval tv; \
176 char slevel[5][4] = {"dis", "err", "wrn", "inf", "dbg"}; \
177 char *msg = "(%s:%d) " format; \
178 if (level <= host_trace_level) { \
179 gettimeofday(&tv, NULL); \
180 fprintf(stderr, "trace: [%ld.%6.6ld] <%s> ", tv.tv_sec, tv.tv_usec, \
181 slevel[level]); \
182 fprintf(stderr, msg, strrchr(__FILE__, '/') + 1, \
183 __LINE__, ##__VA_ARGS__); \
184 fprintf(stderr, "\n"); \
185 } \
186} while (0)
187
188#define trace_point(x) do {} while (0)
189
190#else /* CONFIG_LIBRARY */
191
192#define trace_point(x) platform_trace_point(x)
193
194#define BASE_LOG_ASSERT_FAIL_MSG \
195unsupported_amount_of_params_in_trace_event\
196_thrown_from_macro_BASE_LOG_in_trace_h
197
198#define CT_ASSERT(COND, MESSAGE) \
199 ((void)sizeof(char[1 - 2 * !(COND)]))
200
201#define trace_check_size_uint32(a) \
202 CT_ASSERT(sizeof(a) <= sizeof(uint32_t), "error: trace argument is bigger than a uint32_t");
203
204#define STATIC_ASSERT_ARG_SIZE(...) \
205 META_MAP(1, trace_check_size_uint32, __VA_ARGS__)
206
212#define _log_message(log_func, atomic, lvl, comp_class, ctx, id_1, id_2, format, ...) \
213do { \
214 _DECLARE_LOG_ENTRY(lvl, format, comp_class, \
215 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)); \
216 STATIC_ASSERT_ARG_SIZE(__VA_ARGS__); \
217 STATIC_ASSERT(_TRACE_EVENT_MAX_ARGUMENT_COUNT >= \
218 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \
219 BASE_LOG_ASSERT_FAIL_MSG \
220 ); \
221 _log_sofdict(log_func, atomic, &log_entry, ctx, lvl, id_1, id_2, \
222 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), ##__VA_ARGS__); \
223 _log_nodict(atomic, META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \
224 lvl, format, ##__VA_ARGS__); \
225} while (0)
226
227#ifdef __ZEPHYR__
228/* Just like XTOS, only the most urgent messages go to limited
229 * shared memory.
230 */
231#define _log_nodict(atomic, arg_count, lvl, format, ...) \
232do { \
233 if ((lvl) <= MTRACE_DUPLICATION_LEVEL) \
234 printk("%llu " format "\n", k_cycle_get_64(), \
235 ##__VA_ARGS__); \
236} while (0)
237#else
238#define _log_nodict(atomic, n_args, lvl, format, ...)
239#endif
240
241#endif /* CONFIG_LIBRARY */
242
243#if CONFIG_TRACEV
244/* Enable tr_dbg() statements by defining tracev_...() */
245#define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...) \
246 _trace_event_with_ids(LOG_LEVEL_VERBOSE, class, \
247 ctx, id_1, id_2, \
248 format, ##__VA_ARGS__)
249
250#define tracev_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
251 _trace_event_atomic_with_ids(LOG_LEVEL_VERBOSE, class, \
252 ctx, id_1, id_2, \
253 format, ##__VA_ARGS__)
254
255#else /* CONFIG_TRACEV */
256#define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...) \
257 trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
258#define tracev_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
259 trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
260
261#endif /* CONFIG_TRACEV */
262
263/* The _error_ level has 2, 1 or 0 backends depending on Kconfig */
264#if CONFIG_TRACEE
265/* LOG_LEVEL_CRITICAL messages are duplicated to the mail box */
266#define _trace_error_with_ids(class, ctx, id_1, id_2, format, ...) \
267 _log_message(trace_log_filtered, true, LOG_LEVEL_CRITICAL, class, ctx, id_1, \
268 id_2, format, ##__VA_ARGS__)
269#define trace_error_with_ids(class, ctx, id_1, id_2, format, ...) \
270 _trace_error_with_ids(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
271#define trace_error_atomic_with_ids(...) trace_error_with_ids(__VA_ARGS__)
272
273#elif CONFIG_TRACE
274/* Goes to trace_log_filtered() too but with a downgraded, LOG_INFO level */
275#define trace_error_with_ids(...) trace_event_with_ids(__VA_ARGS__)
276#define trace_error_atomic_with_ids(...) \
277 trace_event_atomic_with_ids(__VA_ARGS__)
278
279#endif /* CONFIG_TRACEE, CONFIG_TRACE */
280
281/* tracing from device (component, pipeline, dai, ...) */
282
292#define trace_dev_err(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \
293 trace_error_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \
294 get_id_m(dev), get_subid_m(dev), \
295 fmt, ##__VA_ARGS__)
296
298#define trace_dev_warn(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \
299 trace_warn_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \
300 get_id_m(dev), get_subid_m(dev), \
301 fmt, ##__VA_ARGS__)
302
304#define trace_dev_info(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \
305 trace_event_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \
306 get_id_m(dev), get_subid_m(dev), \
307 fmt, ##__VA_ARGS__)
308
310#define trace_dev_dbg(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \
311 tracev_event_with_ids(_TRACE_INV_CLASS, \
312 get_ctx_m(dev), get_id_m(dev), \
313 get_subid_m(dev), fmt, ##__VA_ARGS__)
314
315/* tracing from infrastructure part */
316
317#define tr_err_atomic(ctx, fmt, ...) \
318 trace_error_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
319 _TRACE_INV_ID, _TRACE_INV_ID, \
320 fmt, ##__VA_ARGS__)
321
322#define tr_warn_atomic(ctx, fmt, ...) \
323 trace_warn_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
324 _TRACE_INV_ID, _TRACE_INV_ID, \
325 fmt, ##__VA_ARGS__)
326
327#define tr_info_atomic(ctx, fmt, ...) \
328 trace_event_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
329 _TRACE_INV_ID, _TRACE_INV_ID, \
330 fmt, ##__VA_ARGS__)
331
332#define tr_dbg_atomic(ctx, fmt, ...) \
333 tracev_event_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
334 _TRACE_INV_ID, _TRACE_INV_ID, \
335 fmt, ##__VA_ARGS__)
336
337#define tr_err(ctx, fmt, ...) \
338 trace_error_with_ids(_TRACE_INV_CLASS, ctx, \
339 _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
340
341#define tr_warn(ctx, fmt, ...) \
342 trace_warn_with_ids(_TRACE_INV_CLASS, ctx, \
343 _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
344
345#define tr_info(ctx, fmt, ...) \
346 trace_event_with_ids(_TRACE_INV_CLASS, ctx, \
347 _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
348
349/* tracev_ output depends on CONFIG_TRACEV=y */
350#define tr_dbg(ctx, fmt, ...) \
351 tracev_event_with_ids(_TRACE_INV_CLASS, ctx, \
352 _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
353
363#define mtrace_printf(log_level, format_str, ...) \
364 do { \
365 STATIC_ASSERT(META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__) \
366 <= _TRACE_EVENT_MAX_ARGUMENT_COUNT, \
367 too_many_mtrace_printf_arguments); \
368 _DECLARE_LOG_ENTRY(log_level, format_str, _TRACE_INV_CLASS, \
369 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)); \
370 mtrace_dict_entry(true, (uint32_t)&log_entry, \
371 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \
372 ##__VA_ARGS__); \
373 } while (0)
374
375#endif
struct sof * sof_get(void)
struct trace * trace
Definition sof.h:16
part of sof_ipc_trace_filter, ABI3.17
Definition trace.h:70
General firmware context.
Definition sof.h:44
struct trace * trace
Definition sof.h:61
Definition trace.h:135
Definition trace-soflogger.h:21
uint32_t uuid_id
type id, or 0 when not important
Definition trace-soflogger.h:22
int32_t log_level
new log level value
Definition trace-soflogger.h:25
int32_t pipe_id
pipeline id or -1 when not important
Definition trace-soflogger.h:24
int32_t comp_id
component id or -1 when not important
Definition trace-soflogger.h:23
uint32_t length
Definition tlv.h:1
void mtrace_event(const char *complete_packet, uint32_t length)
Posts a fully prepared log header + log entry.
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)
Definition trace-soflogger.h:110
void trace_flush_dma_to_mbox(void)
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)
void mtrace_dict_entry(bool atomic_context, uint32_t log_entry_pointer, int n_args,...)
Appends one SOF dictionary entry and log statement to the ring buffer implementing the 'etrace' in sh...
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)
void trace_init(struct sof *sof)
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,...)
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)
int trace_filter_update(const struct trace_filter *elem)
void trace_off(void)
static struct trace * trace_get(void)
Definition trace-soflogger.h:55
void trace_on(void)