1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #ifndef DEBUG_H
7 #define DEBUG_H
8 
9 #ifndef __ASSEMBLER__
10 #include <stdarg.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #endif
14 #include <utils_def.h>
15 
16 /*
17  * The log output macros print output to the console. These macros produce
18  * compiled log output only if the LOG_LEVEL defined in the makefile (or the
19  * make command line) is greater or equal than the level required for that
20  * type of log output.
21  *
22  * The format expected is the same as for printf(). For example:
23  * INFO("Info %s.\n", "message")    -> INFO:    Info message.
24  * WARN("Warning %s.\n", "message") -> WARNING: Warning message.
25  */
26 #define LOG_LEVEL_NONE		0
27 #define LOG_LEVEL_ERROR		10
28 #define LOG_LEVEL_NOTICE	20
29 #define LOG_LEVEL_WARNING	30
30 #define LOG_LEVEL_INFO		40
31 #define LOG_LEVEL_VERBOSE	50
32 
33 /* If the LOG_LEVEL is not defined through the build */
34 #ifndef LOG_LEVEL
35   #ifdef NDEBUG /* Release */
36     #define LOG_LEVEL	LOG_LEVEL_NOTICE
37   #else /* Debug */
38     #define LOG_LEVEL	LOG_LEVEL_INFO
39   #endif
40 #endif
41 
42 #ifndef __ASSEMBLER__
43 /*
44  * If the log output is too low then this macro is used in place of rmm_log()
45  * below. The intent is to get the compiler to evaluate the function call for
46  * type checking and format specifier correctness but let it optimize it out.
47  */
48 #define no_rmm_log(fmt, ...)				\
49 	do {						\
50 		if (false) {				\
51 			rmm_log(fmt, ##__VA_ARGS__);	\
52 		}					\
53 	} while (false)
54 
55 #if LOG_LEVEL >= LOG_LEVEL_ERROR
56 # define ERROR(...)	rmm_log(__VA_ARGS__)
57 #else
58 # define ERROR(...)	no_rmm_log(__VA_ARGS__)
59 #endif
60 
61 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
62 # define NOTICE(...)	rmm_log(__VA_ARGS__)
63 #else
64 # define NOTICE(...)	no_rmm_log(__VA_ARGS__)
65 #endif
66 
67 #if LOG_LEVEL >= LOG_LEVEL_WARNING
68 # define WARN(...)	rmm_log(__VA_ARGS__)
69 #else
70 # define WARN(...)	no_rmm_log(__VA_ARGS__)
71 #endif
72 
73 #if LOG_LEVEL >= LOG_LEVEL_INFO
74 # define INFO(...)	rmm_log(__VA_ARGS__)
75 #else
76 # define INFO(...)	no_rmm_log(__VA_ARGS__)
77 #endif
78 
79 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
80 # define VERBOSE(...)	rmm_log(__VA_ARGS__)
81 #else
82 # define VERBOSE(...)	no_rmm_log(__VA_ARGS__)
83 #endif
84 
85 /*
86  * FIXME: Fully implement panic() handlers once it is decided how to panic.
87  */
88 
89 #define panic()				\
90 	do {				\
91 	} while (true)
92 
93 __attribute__((__format__(__printf__, 1, 2)))
rmm_log(const char * fmt,...)94 static inline void rmm_log(const char *fmt, ...)
95 {
96 	va_list args;
97 
98 	va_start(args, fmt);
99 	(void)vprintf(fmt, args);
100 	va_end(args);
101 }
102 
103 void backtrace(uintptr_t frame_pointer);
104 
105 #endif /* __ASSEMBLER__ */
106 #endif /* DEBUG_H */
107