1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2016 Intel Corporation. All rights reserved.
4  *
5  * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
6  *         Keyon Jie <yang.jie@linux.intel.com>
7  *         Artur Kloniecki <arturx.kloniecki@linux.intel.com>
8  *         Karol Trzcinski <karolx.trzcinski@linux.intel.com>
9  */
10 
11 #ifndef __SOF_TRACE_TRACE_H__
12 #define __SOF_TRACE_TRACE_H__
13 
14 #ifndef RELATIVE_FILE
15 #error "This file requires RELATIVE_FILE to be defined. " \
16 	"Add it to CMake's target with sof_append_relative_path_definitions."
17 #endif
18 
19 #if !CONFIG_LIBRARY
20 #include <platform/trace/trace.h>
21 #endif
22 #include <sof/common.h>
23 #include <sof/sof.h>
24 #include <sof/trace/preproc.h>
25 
26 #include <stdbool.h>
27 #include <stdint.h>
28 #if CONFIG_LIBRARY
29 #include <stdio.h>
30 #endif
31 
32 struct sof;
33 struct trace;
34 struct tr_ctx;
35 
36 /* bootloader trace values */
37 #define TRACE_BOOT_LDR_ENTRY		0x100
38 #define TRACE_BOOT_LDR_HPSRAM		0x110
39 #define TRACE_BOOT_LDR_MANIFEST		0x120
40 #define TRACE_BOOT_LDR_LPSRAM		0x130
41 #define TRACE_BOOT_LDR_L1DRAM		0x140
42 #define TRACE_BOOT_LDR_JUMP		0x150
43 
44 #define TRACE_BOOT_LDR_PARSE_MODULE	0x210
45 #define TRACE_BOOT_LDR_PARSE_SEGMENT	0x220
46 
47 /* general trace init codes - only used at boot
48  * when main trace is not available
49  */
50 #define TRACE_BOOT_START		0x1000
51 #define TRACE_BOOT_ARCH			0x2000
52 #define TRACE_BOOT_SYS			0x3000
53 #define TRACE_BOOT_PLATFORM		0x4000
54 
55 /* system specific codes */
56 #define TRACE_BOOT_SYS_HEAP		(TRACE_BOOT_SYS + 0x100)
57 #define TRACE_BOOT_SYS_TRACES		(TRACE_BOOT_SYS + 0x200)
58 #define TRACE_BOOT_SYS_NOTIFIER		(TRACE_BOOT_SYS + 0x300)
59 #define TRACE_BOOT_SYS_POWER		(TRACE_BOOT_SYS + 0x400)
60 
61 /* platform/device specific codes */
62 #define TRACE_BOOT_PLATFORM_ENTRY	(TRACE_BOOT_PLATFORM + 0x100)
63 #define TRACE_BOOT_PLATFORM_IRQ		(TRACE_BOOT_PLATFORM + 0x110)
64 #define TRACE_BOOT_PLATFORM_MBOX	(TRACE_BOOT_PLATFORM + 0x120)
65 #define TRACE_BOOT_PLATFORM_SHIM	(TRACE_BOOT_PLATFORM + 0x130)
66 #define TRACE_BOOT_PLATFORM_PMC		(TRACE_BOOT_PLATFORM + 0x140)
67 #define TRACE_BOOT_PLATFORM_TIMER	(TRACE_BOOT_PLATFORM + 0x150)
68 #define TRACE_BOOT_PLATFORM_CLOCK	(TRACE_BOOT_PLATFORM + 0x160)
69 #define TRACE_BOOT_PLATFORM_SCHED	(TRACE_BOOT_PLATFORM + 0x170)
70 #define TRACE_BOOT_PLATFORM_AGENT	(TRACE_BOOT_PLATFORM + 0x180)
71 #define TRACE_BOOT_PLATFORM_CPU_FREQ	(TRACE_BOOT_PLATFORM + 0x190)
72 #define TRACE_BOOT_PLATFORM_SSP_FREQ	(TRACE_BOOT_PLATFORM + 0x1A0)
73 #define TRACE_BOOT_PLATFORM_DMA		(TRACE_BOOT_PLATFORM + 0x1B0)
74 #define TRACE_BOOT_PLATFORM_IPC		(TRACE_BOOT_PLATFORM + 0x1C0)
75 #define TRACE_BOOT_PLATFORM_IDC		(TRACE_BOOT_PLATFORM + 0x1D0)
76 #define TRACE_BOOT_PLATFORM_DAI		(TRACE_BOOT_PLATFORM + 0x1E0)
77 #define TRACE_BOOT_PLATFORM_SSP		(TRACE_BOOT_PLATFORM + 0x1F0)
78 #define TRACE_BOOT_PLATFORM_SPI		(TRACE_BOOT_PLATFORM + 0x200)
79 #define TRACE_BOOT_PLATFORM_DMA_TRACE	(TRACE_BOOT_PLATFORM + 0x210)
80 
81 #define _TRACE_EVENT_MAX_ARGUMENT_COUNT 4
82 
trace_get(void)83 static inline struct trace *trace_get(void)
84 {
85 	return sof_get()->trace;
86 }
87 
88 /* Silences compiler warnings about unused variables */
89 #define trace_unused(class, ctx, id_1, id_2, format, ...) \
90 	UNUSED(ctx, id_1, id_2, ##__VA_ARGS__)
91 
92 struct trace_filter {
93 	uint32_t uuid_id;	/**< type id, or 0 when not important */
94 	int32_t comp_id;	/**< component id or -1 when not important */
95 	int32_t pipe_id;	/**< pipeline id or -1 when not important */
96 	int32_t log_level;	/**< new log level value */
97 };
98 
99 #if CONFIG_TRACE
100 
101 /*
102  * trace_event macro definition
103  *
104  * trace_event() macro is used for logging events that occur at runtime.
105  * It comes in 2 main flavours, atomic and non-atomic. Depending of definitions
106  * above, it might also propagate log messages to mbox if desired.
107  *
108  * First argument is always class of event being logged, as defined in
109  * user/trace.h - TRACE_CLASS_* (deprecated - do not use).
110  * Second argument is string literal in printf format, followed by up to 4
111  * parameters (uint32_t), that are used to expand into string fromat when
112  * parsing log data.
113  *
114  * All compile-time accessible data (verbosity, class, source file name, line
115  * index and string literal) are linked into .static_log_entries section
116  * of binary and then extracted by smex, so they do not contribute to loadable
117  * image size. This way more elaborate log messages are possible and encouraged,
118  * for better debugging experience, without worrying about runtime performance.
119  */
120 
121 /* Map the different trace_xxxx_with_ids(... ) levels to the
122  * _trace_event_with_ids(level_xxxx, ...) macro shared across log
123  * levels.
124  */
125 #define trace_event_with_ids(class, ctx, id_1, id_2, format, ...)	\
126 	_trace_event_with_ids(LOG_LEVEL_INFO, class, ctx, id_1, id_2,	\
127 			      format, ##__VA_ARGS__)
128 
129 #define trace_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...)     \
130 	_trace_event_atomic_with_ids(LOG_LEVEL_INFO, class, ctx, id_1, id_2, \
131 				     format, ##__VA_ARGS__)
132 
133 #define trace_warn_with_ids(class, ctx, id_1, id_2, format, ...)	 \
134 	_trace_event_with_ids(LOG_LEVEL_WARNING, class, ctx, id_1, id_2, \
135 			      format, ##__VA_ARGS__)
136 
137 #define trace_warn_atomic_with_ids(class, ctx, id_1, id_2, format, ...)	\
138 	_trace_event_atomic_with_ids(LOG_LEVEL_WARNING, class,		\
139 				     ctx, id_1, id_2,			\
140 				     format, ##__VA_ARGS__)
141 
142 void trace_flush_dma_to_mbox(void);
143 void trace_on(void);
144 void trace_off(void);
145 void trace_init(struct sof *sof);
146 
147 /* All tracing macros in this file end up calling these functions in the end. */
148 void trace_log_filtered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
149 			uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, ...);
150 void trace_log_unfiltered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
151 			  uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, ...);
152 struct sof_ipc_trace_filter_elem *trace_filter_fill(struct sof_ipc_trace_filter_elem *elem,
153 						    struct sof_ipc_trace_filter_elem *end,
154 						    struct trace_filter *filter);
155 int trace_filter_update(const struct trace_filter *elem);
156 
157 #define _trace_event_with_ids(lvl, class, ctx, id_1, id_2, format, ...)	\
158 	_log_message(trace_log_filtered, false, lvl, class, ctx, id_1, id_2, format, ##__VA_ARGS__)
159 
160 #define _trace_event_atomic_with_ids(lvl, class, ctx, id_1, id_2, format, ...)	\
161 	_log_message(trace_log_filtered, true, lvl, class, ctx, id_1, id_2, format, ##__VA_ARGS__)
162 
163 /**
164  * Appends one SOF dictionary entry and log statement to the ring buffer
165  * implementing the 'etrace' in shared memory.
166  *
167  * @param atomic_context Take the trace->lock if false.
168  * @param log_entry_pointer dictionary index produced by the
169  *        _DECLARE_LOG_ENTRY macro.
170  * @param n_args number of va_args
171  */
172 void mtrace_dict_entry(bool atomic_context, uint32_t log_entry_pointer, int n_args, ...);
173 
174 /** Posts a fully prepared log header + log entry */
175 void mtrace_event(const char *complete_packet, uint32_t length);
176 
177 /** The start of this linker output MUST match the 'ldc_entry_header'
178  *  struct defined in the logger program running in user space.
179  */
180 #define _DECLARE_LOG_ENTRY(lvl, format, comp_class, n_params)	\
181 	__section(".static_log." #lvl)				\
182 	static const struct {					\
183 		uint32_t level;					\
184 		uint32_t component_class;			\
185 		uint32_t params_num;				\
186 		uint32_t line_idx;				\
187 		uint32_t file_name_len;				\
188 		uint32_t text_len;				\
189 		const char file_name[sizeof(RELATIVE_FILE)];	\
190 		const char text[sizeof(format)];		\
191 	} log_entry = {						\
192 		lvl,						\
193 		comp_class,					\
194 		n_params,						\
195 		__LINE__,					\
196 		sizeof(RELATIVE_FILE),				\
197 		sizeof(format),					\
198 		RELATIVE_FILE,					\
199 		format						\
200 	}
201 
202 /* _log_message() */
203 
204 #ifdef CONFIG_LIBRARY
205 
206 extern int test_bench_trace;
207 char *get_trace_class(uint32_t trace_class);
208 #define _log_message(ignored_log_func, atomic, level, comp_class, ctx, id_1, id_2, format, ...)	\
209 do {											\
210 	(void)ctx;									\
211 	(void)id_1;									\
212 	(void)id_2;									\
213 	if (test_bench_trace) {								\
214 		char *msg = "%s " format;						\
215 		fprintf(stderr, msg, get_trace_class(comp_class), ##__VA_ARGS__);	\
216 		fprintf(stderr, "\n");							\
217 	}										\
218 } while (0)
219 
220 #define trace_point(x)  do {} while (0)
221 
222 #else  /* CONFIG_LIBRARY */
223 
224 #define trace_point(x) platform_trace_point(x)
225 
226 #define BASE_LOG_ASSERT_FAIL_MSG \
227 unsupported_amount_of_params_in_trace_event\
228 _thrown_from_macro_BASE_LOG_in_trace_h
229 
230 #define CT_ASSERT(COND, MESSAGE) \
231 	((void)sizeof(char[1 - 2 * !(COND)]))
232 
233 #define trace_check_size_uint32(a) \
234 	CT_ASSERT(sizeof(a) <= sizeof(uint32_t), "error: trace argument is bigger than a uint32_t");
235 
236 #define STATIC_ASSERT_ARG_SIZE(...) \
237 	META_MAP(1, trace_check_size_uint32, __VA_ARGS__)
238 
239 /** _log_message is where the memory-saving dictionary magic described
240  * above happens: the "format" string argument is moved to a special
241  * linker section and replaced by a &log_entry pointer to it.
242  */
243 #define _log_message(log_func, atomic, lvl, comp_class, ctx, id_1, id_2, format, ...)	\
244 do {											\
245 	_DECLARE_LOG_ENTRY(lvl, format, comp_class,					\
246 			   META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__));		\
247 	STATIC_ASSERT_ARG_SIZE(__VA_ARGS__);						\
248 	STATIC_ASSERT(_TRACE_EVENT_MAX_ARGUMENT_COUNT >=				\
249 			META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__),			\
250 		BASE_LOG_ASSERT_FAIL_MSG						\
251 	);										\
252 	log_func(atomic, &log_entry, ctx, lvl, id_1, id_2,				\
253 		 META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), ##__VA_ARGS__);		\
254 } while (0)
255 
256 #endif /* CONFIG_LIBRARY */
257 
258 #else /* CONFIG_TRACE */
259 
260 #define trace_event_with_ids(class, ctx, id_1, id_2, format, ...)	\
261 	trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
262 #define trace_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
263 	trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
264 
265 #define trace_warn_with_ids(class, ctx, id_1, id_2, format, ...)	\
266 	trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
267 #define trace_warn_atomic_with_ids(class, ctx, id_1, id_2, format, ...)	\
268 	trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
269 
270 #define trace_point(x)  do {} while (0)
271 
trace_flush_dma_to_mbox(void)272 static inline void trace_flush_dma_to_mbox(void) { }
trace_on(void)273 static inline void trace_on(void) { }
trace_off(void)274 static inline void trace_off(void) { }
trace_init(struct sof * sof)275 static inline void trace_init(struct sof *sof) { }
trace_filter_update(const struct trace_filter * filter)276 static inline int trace_filter_update(const struct trace_filter *filter)
277 	{ return 0; }
278 
279 #endif /* CONFIG_TRACE */
280 
281 #if CONFIG_TRACEV
282 /* Enable tr_dbg() statements by defining tracev_...() */
283 #define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...)	\
284 	_trace_event_with_ids(LOG_LEVEL_VERBOSE, class,			\
285 			      ctx, id_1, id_2,				\
286 			      format, ##__VA_ARGS__)
287 
288 #define tracev_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
289 	_trace_event_atomic_with_ids(LOG_LEVEL_VERBOSE, class,		  \
290 				     ctx, id_1, id_2,			  \
291 				     format, ##__VA_ARGS__)
292 
293 #else /* CONFIG_TRACEV */
294 #define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...)	\
295 	trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
296 #define tracev_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
297 	trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
298 
299 #endif /* CONFIG_TRACEV */
300 
301 /* The _error_ level has 2, 1 or 0 backends depending on Kconfig */
302 #if CONFIG_TRACEE
303 /* LOG_LEVEL_CRITICAL messages are duplicated to the mail box */
304 #define _trace_error_with_ids(class, ctx, id_1, id_2, format, ...)			\
305 	_log_message(trace_log_filtered, true, LOG_LEVEL_CRITICAL, class, ctx, id_1,	\
306 		     id_2, format, ##__VA_ARGS__)
307 #define trace_error_with_ids(class, ctx, id_1, id_2, format, ...)	\
308 	_trace_error_with_ids(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
309 #define trace_error_atomic_with_ids(...) trace_error_with_ids(__VA_ARGS__)
310 
311 #elif CONFIG_TRACE
312 /* Goes to trace_log_filtered() too but with a downgraded, LOG_INFO level */
313 #define trace_error_with_ids(...) trace_event_with_ids(__VA_ARGS__)
314 #define trace_error_atomic_with_ids(...) \
315 	trace_event_atomic_with_ids(__VA_ARGS__)
316 
317 #else /* CONFIG_TRACEE, CONFIG_TRACE */
318 #define trace_error_with_ids(class, ctx, id_1, id_2, format, ...)	\
319 	trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
320 #define trace_error_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \
321 	trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__)
322 
323 #endif /* CONFIG_TRACEE, CONFIG_TRACE */
324 
325 /** Default value when there is no specific pipeline, dev, dai, etc. */
326 #define _TRACE_INV_ID		-1
327 
328 /** This has been replaced in commits 6ce635aa82 and earlier by the
329  * DECLARE_TR_CTX, tr_ctx and component UUID system below
330  */
331 #define _TRACE_INV_CLASS	TRACE_CLASS_DEPRECATED
332 
333 /**
334  * Trace context.
335  */
336 struct tr_ctx {
337 	const struct sof_uuid_entry *uuid_p;	/**< UUID pointer, use SOF_UUID() to init */
338 	uint32_t level;				/**< Default log level */
339 };
340 
341 #if defined(UNIT_TEST) || defined(__ZEPHYR__)
342 #define TRACE_CONTEXT_SECTION
343 #else
344 #define TRACE_CONTEXT_SECTION __section(".trace_ctx")
345 #endif
346 
347 /**
348  * Declares trace context.
349  * @param ctx_name (Symbol) name.
350  * @param uuid UUID pointer, use SOF_UUID() to inititalize.
351  * @param default_log_level Default log level.
352  */
353 #define DECLARE_TR_CTX(ctx_name, uuid, default_log_level)	\
354 	struct tr_ctx ctx_name TRACE_CONTEXT_SECTION = {	\
355 		.uuid_p = uuid,					\
356 		.level = default_log_level,			\
357 	}
358 
359 /* tracing from device (component, pipeline, dai, ...) */
360 
361 /** \brief Trace from a device on err level.
362  *
363  * @param get_ctx_m Macro that can retrieve trace context from dev
364  * @param get_id_m Macro that can retrieve device's id0 from the dev
365  * @param get_subid_m Macro that can retrieve device's id1 from the dev
366  * @param dev Device
367  * @param fmt Format followed by parameters
368  * @param ... Parameters
369  */
370 #define trace_dev_err(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...)	\
371 	trace_error_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev),		\
372 			     get_id_m(dev), get_subid_m(dev),		\
373 			     fmt, ##__VA_ARGS__)
374 
375 /** \brief Trace from a device on warning level. */
376 #define trace_dev_warn(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...)	\
377 	trace_warn_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev),		\
378 			    get_id_m(dev), get_subid_m(dev),		\
379 			    fmt, ##__VA_ARGS__)
380 
381 /** \brief Trace from a device on info level. */
382 #define trace_dev_info(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...)	\
383 	trace_event_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev),		\
384 			     get_id_m(dev), get_subid_m(dev),		\
385 			     fmt, ##__VA_ARGS__)
386 
387 /** \brief Trace from a device on dbg level. */
388 #define trace_dev_dbg(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...)	\
389 	tracev_event_with_ids(_TRACE_INV_CLASS,				\
390 			      get_ctx_m(dev), get_id_m(dev),		\
391 			      get_subid_m(dev), fmt, ##__VA_ARGS__)
392 
393 /* tracing from infrastructure part */
394 
395 #define tr_err(ctx, fmt, ...) \
396 	trace_error_with_ids(_TRACE_INV_CLASS, ctx, \
397 			     _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
398 
399 #define tr_err_atomic(ctx, fmt, ...) \
400 	trace_error_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
401 				    _TRACE_INV_ID, _TRACE_INV_ID, \
402 				    fmt, ##__VA_ARGS__)
403 
404 #define tr_warn(ctx, fmt, ...) \
405 	trace_warn_with_ids(_TRACE_INV_CLASS, ctx, \
406 			    _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
407 
408 #define tr_warn_atomic(ctx, fmt, ...) \
409 	trace_warn_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
410 				   _TRACE_INV_ID, _TRACE_INV_ID, \
411 				   fmt, ##__VA_ARGS__)
412 
413 #define tr_info(ctx, fmt, ...) \
414 	trace_event_with_ids(_TRACE_INV_CLASS, ctx, \
415 			     _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
416 
417 #define tr_info_atomic(ctx, fmt, ...) \
418 	trace_event_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
419 				    _TRACE_INV_ID, _TRACE_INV_ID, \
420 				    fmt, ##__VA_ARGS__)
421 
422 /* tracev_ output depends on CONFIG_TRACEV=y */
423 #define tr_dbg(ctx, fmt, ...) \
424 	tracev_event_with_ids(_TRACE_INV_CLASS, ctx, \
425 			      _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__)
426 
427 #define tr_dbg_atomic(ctx, fmt, ...) \
428 	tracev_event_atomic_with_ids(_TRACE_INV_CLASS, ctx, \
429 				     _TRACE_INV_ID, _TRACE_INV_ID, \
430 				     fmt, ##__VA_ARGS__)
431 
432 #if CONFIG_TRACE
433 
434 /** Direct, low-level access to mbox / shared memory logging when DMA
435  * tracing is either not initialized yet or disabled or found broken for
436  * any reason.
437  * To keep it simpler than and with minimal dependencies on
438  * the huge number of lines above, this does not check arguments at compile
439  * time.
440  * There is neither log level filtering, throttling or any other
441  * advanced feature.
442  */
443 #define mtrace_printf(log_level, format_str, ...)			\
444 	do {								\
445 		STATIC_ASSERT(META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)  \
446 			      <= _TRACE_EVENT_MAX_ARGUMENT_COUNT,	\
447 			      too_many_mtrace_printf_arguments);	\
448 		_DECLARE_LOG_ENTRY(log_level, format_str, _TRACE_INV_CLASS, \
449 				   META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)); \
450 		mtrace_dict_entry(true, (uint32_t)&log_entry,			\
451 				  META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \
452 				  ##__VA_ARGS__);			\
453 	} while (0)
454 
455 
456 #else
457 
mtrace_printf(int log_level,const char * format_str,...)458 static inline void mtrace_printf(int log_level, const char *format_str, ...)
459 {
460 };
461 
462 #endif /* CONFIG_TRACE */
463 
464 #endif /* __SOF_TRACE_TRACE_H__ */
465