1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2015-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /** 25 * Standard printf logging interface 26 */ 27 28 #ifndef NVPRINTF_H 29 #define NVPRINTF_H 30 31 #include "utils/nvprintf_level.h" 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 #if defined(GSP_PLUGIN_BUILD) || (defined(NVRM) && NVOS_IS_LIBOS) 38 39 /** 40 * GSPRM uses a different system for logging. 41 * The format strings, filename, line number, etc. are stored in a separate 42 * data segment that is not loaded on the GSP, but is available to the decoder. 43 */ 44 45 #include "libos_log.h" 46 47 /** 48 * Define NV_PRINTF_LEVEL to the minimum level for debug output. This is compared 49 * to the level for each NV_PRINT to cull them at compile time. 50 */ 51 #define NV_PRINTF_LEVEL LEVEL_NOTICE 52 53 #undef NV_PRINTF_ENABLED 54 #define NV_PRINTF_ENABLED 1 55 56 #undef NV_PRINTF_STRINGS_ALLOWED 57 #define NV_PRINTF_STRINGS_ALLOWED 0 58 59 #define NV_PRINTF_STRING_SECTION LIBOS_SECTION_LOGGING 60 61 #define MAKE_NV_PRINTF_STR MAKE_LIBOS_LOGGING_STR 62 63 // NVLOG is not used on GSP-RM. 64 #undef NVLOG_ENABLED 65 #define NVLOG_ENABLED 0 66 67 // Direct dmesg printing through NV_PRINTF_STRING is a no-op on GSP-RM 68 #define NV_PRINTF_STRING(module, level, format, ...) 69 70 #if defined(GSP_PLUGIN_BUILD) 71 void log_vgpu_log_entry(const NvU64 n_args, const NvU64 * args); 72 #define LIBOS_LOG_ENTRY log_vgpu_log_entry 73 #else 74 void log_rm_log_entry(const NvU64 n_args, const NvU64 * args); 75 #define LIBOS_LOG_ENTRY log_rm_log_entry 76 #endif 77 78 #define NV_PRINTF(level, format, ...) do { \ 79 if (NV_PRINTF_LEVEL_ENABLED(level)) \ 80 { \ 81 LIBOS_LOG_INTERNAL(LIBOS_LOG_ENTRY, level, \ 82 format, ##__VA_ARGS__); \ 83 } \ 84 } while (0) 85 86 #define NV_PRINTF_EX(module, level, format, ...) do { \ 87 if (NV_PRINTF_LEVEL_ENABLED(level)) \ 88 { \ 89 LIBOS_LOG_INTERNAL(LIBOS_LOG_ENTRY, level, \ 90 format, ##__VA_ARGS__); \ 91 } \ 92 } while (0) 93 94 #define NV_LOG_SPECIAL(level, special, ...) do { \ 95 if (NV_PRINTF_LEVEL_ENABLED(level)) \ 96 { \ 97 LIBOS_LOG_INTERNAL_SPECIAL(LIBOS_LOG_ENTRY, level, \ 98 special, ##__VA_ARGS__); \ 99 } \ 100 } while (0) 101 102 #else // defined(NVRM) && NVOS_IS_LIBOS 103 104 /** 105 * @defgroup NV_PRINTF Utility Printing Macros 106 * 107 * @brief Provides a light abstraction layer for printf logging. 108 * 109 * NvPort and NvLog are used for portability and logging primitives. 110 * If an environment cannot use these directly then it can override 111 * the NV_PORT_HEADER and NV_LOG_HEADER defines in its makefile 112 * to point to appropriate replacements. 113 * @{ 114 */ 115 116 #if defined(NVRM) && !defined(NVWATCH) 117 #undef NV_PRINTF_PREFIX 118 #define NV_PRINTF_PREFIX "NVRM" 119 #undef NV_PRINTF_PREFIX_SEPARATOR 120 #define NV_PRINTF_PREFIX_SEPARATOR ": " 121 #endif 122 123 #ifndef NV_PRINTF_PREFIX 124 /** 125 * @brief Prefix to prepend to all messages printed by @ref NV_PRINTF. 126 */ 127 #define NV_PRINTF_PREFIX "" 128 #endif 129 130 #ifndef NV_PRINTF_PREFIX_SEPARATOR 131 /** 132 * @brief Separator between prefix messages printed by @ref NV_PRINTF. 133 * 134 * If defined, it must be a single character followed by an optional space. 135 */ 136 #define NV_PRINTF_PREFIX_SEPARATOR "" 137 #endif 138 139 #ifndef NV_PRINTF_ADD_PREFIX 140 /** 141 * @brief Apply the full prefix string to a format string. 142 * 143 * This is a function-like macro so it can support inserting arguments after the 144 * format string. Example: 145 * #define NV_PRINTF_ADD_PREFIX(fmt) "%s():"fmt, __FUNCTION__ 146 */ 147 #define NV_PRINTF_ADD_PREFIX(fmt) NV_PRINTF_PREFIX NV_PRINTF_PREFIX_SEPARATOR fmt 148 #endif 149 150 // Include portability header, falling back to NvPort if not provided. 151 #ifndef NV_PORT_HEADER 152 #define NV_PORT_HEADER "nvport/nvport.h" 153 #endif 154 #include NV_PORT_HEADER 155 156 // Include logging header, falling back to NvLog if not provided. 157 #ifndef NV_LOG_HEADER 158 #define NV_LOG_HEADER "nvlog/nvlog_printf.h" 159 #endif 160 #include NV_LOG_HEADER 161 162 #define NV_PRINTF_STRING_SECTION 163 164 #define MAKE_NV_PRINTF_STR(str) str 165 166 /** 167 * @def NV_PRINTF(level, format, args...) 168 * @brief Standard formatted printing/logging interface. 169 * 170 * @param level - Debug level to print at. One of @ref NV_PRINTF_LEVELS 171 * @param format - A standard printf format string. Must be a string literal. 172 * @param args... - Arguments for the format string literal, like regular printf 173 * 174 * The logging header can redefine the behavior, but the basic implementation 175 * will just print to standard output, like the printf function. 176 * 177 * This will print to the @ref NV_PRINTF_MODULE module. If the module is not 178 * defined, it will default to GLOBAL. Use @ref NV_PRINTF_EX to specify another 179 * module. 180 * 181 * This will prefix the prints with @ref NV_PRINTF_PREFIX string and function 182 * name. To specify a different (or no) prefix, use @ref NV_PRINTF_EX 183 * 184 * @note The format string must be a string literal. The level can be a variable, 185 * but it may have positive speed and size effects to use the above levels 186 * directly. 187 */ 188 #ifndef NV_PRINTF 189 #define NV_PRINTF(level, format, ...) \ 190 NV_PRINTF_EX(NV_PRINTF_MODULE, level, NV_PRINTF_ADD_PREFIX(format), ##__VA_ARGS__) 191 #endif 192 193 /** 194 * @def NV_PRINTF_EX(module, level, format, args...) 195 * @brief Extended version of the standard @ref NV_PRINTF 196 * 197 * This interface allows you to explicitly specify the module to print to and 198 * doesn't perform any automatic prefixing. 199 * 200 * The logging header can redefine the behavior, but the basic implementation 201 * will just print to standard output, like the printf function. 202 * 203 * @note The format string must be a string literal. The level can be a variable, 204 * but it may have positive speed and size effects to use the above levels 205 * directly. 206 */ 207 #ifndef NV_PRINTF_EX 208 #define NV_PRINTF_EX(module, level, format, ...) \ 209 do \ 210 { \ 211 NVLOG_PRINTF(module, NVLOG_ROUTE_RM, level, format, ##__VA_ARGS__); \ 212 NV_PRINTF_STRING(module, level, format, ##__VA_ARGS__); \ 213 } while (0) 214 #endif 215 216 /** 217 * @def NV_PRINTF_STRINGS_ALLOWED 218 * @brief This switch controls whether strings are allowed to appear in the 219 * final binary. 220 * 221 * By default, strings are allowed on DEBUG and QA builds, and all MODS builds 222 */ 223 #ifndef NV_PRINTF_STRINGS_ALLOWED 224 #if defined(DEBUG) || defined(NV_MODS) || defined(QA_BUILD) 225 #define NV_PRINTF_STRINGS_ALLOWED 1 226 #else 227 #define NV_PRINTF_STRINGS_ALLOWED 0 228 #endif 229 #endif // NV_PRINTF_STRINGS_ALLOWED 230 231 // 232 // Default values for the compile time switches: 233 // - Strings are allowed on DEBUG and QA builds, and all MODS builds 234 // - NV_PRINTF is only available if strings are allowed 235 // - All levels are available if NV_PRINTF is available. 236 237 // 238 // Special handling for RM internal prints so we have equivalent functionality 239 // between NV_PRINTF and DBG_PRINTF. This is needed to seamlessly migrate RM to 240 // the new interface. The implementations will eventually be fully extracted and 241 // only depend on other common code, such as NvPort. 242 // 243 #if defined(NVRM) && !defined(NVWATCH) 244 245 #if NV_PRINTF_STRINGS_ALLOWED 246 247 // Declare internal RM print function: 248 // This is utDbg_Printf in unit tests and nvDbg_Printf in regular RM builds 249 #if defined(RM_UNITTEST) 250 #define NVRM_PRINTF_FUNCTION utDbg_Printf 251 #else 252 #define NVRM_PRINTF_FUNCTION nvDbg_Printf 253 #endif // defined(RM_UNITTEST) 254 255 void NVRM_PRINTF_FUNCTION(const char *file, 256 int line, 257 const char *function, 258 int debuglevel, 259 const char *s, 260 ...) NVPORT_CHECK_PRINTF_ARGUMENTS(5, 6); 261 262 #define NV_PRINTF_STRING(module, level, format, ...) \ 263 NVRM_PRINTF_FUNCTION(NV_FILE_STR, __LINE__, NV_FUNCTION_STR, level, format, ##__VA_ARGS__) 264 265 #endif // NV_PRINTF_STRINGS_ALLOWED 266 267 // RM always has printf enabled 268 #define NV_PRINTF_ENABLED 1 269 270 #endif // defined(NVRM) && !defined(NVWATCH) 271 272 // 273 // Default definitions if none are specified 274 // 275 276 /** 277 * @def NV_PRINTF_ENABLED 278 * @brief This macro evaluates to 1 if NV_PRINTF is available (either as regular 279 * debug prints or binary logging) 280 * 281 * By default, it is available on all builds that allow strings 282 */ 283 #ifndef NV_PRINTF_ENABLED 284 #define NV_PRINTF_ENABLED NV_PRINTF_STRINGS_ALLOWED 285 #endif 286 287 #if NV_PRINTF_STRINGS_ALLOWED 288 #define NV_PRINTF_LEVEL LEVEL_INFO 289 #else 290 #define NV_PRINTF_LEVEL LEVEL_NOTICE 291 #endif 292 293 /** 294 * @def NV_PRINTF_STRING(module, level, format, ...) 295 * @brief Prints the string to the given output, if strings are allowed. 296 */ 297 #ifndef NV_PRINTF_STRING 298 #if NV_PRINTF_STRINGS_ALLOWED 299 #define NV_PRINTF_STRING(module, level, format, ...) \ 300 portDbgPrintf(format, ##__VA_ARGS__) 301 302 #if !defined(portDbgPrintf) && !PORT_IS_FUNC_SUPPORTED(portDbgPrintf) 303 #error "NV_PORT_HEADER must implement portDbgPrintf()" 304 #endif 305 306 #else 307 #define NV_PRINTF_STRING(module, level, format, ...) 308 #endif 309 #endif // NV_PRINTF_STRING 310 311 #ifndef NVLOG_PRINTF 312 #define NVLOG_PRINTF(...) 313 #endif 314 315 #endif // defined(NVRM) && NVOS_IS_LIBOS 316 317 /** 318 * @def NV_PRINTF_COND(condition, leveltrue, levelfalse, format, args...) 319 * @brief NV_PRINTF with conditional print level 320 * 321 * Splits NV_PRINTF calls with a print level based on a variable or ternary 322 * operation, to be handled by preprocessors to remove INFO-level prints 323 * 324 * If condition is true, uses leveltrue, else uses levelfalse 325 */ 326 #ifndef NV_PRINTF_COND 327 #define NV_PRINTF_COND(condition, leveltrue, levelfalse, format, ...) \ 328 do { \ 329 if (condition) \ 330 { \ 331 NV_PRINTF(leveltrue, format, ##__VA_ARGS__); \ 332 } \ 333 else \ 334 { \ 335 NV_PRINTF(levelfalse, format, ##__VA_ARGS__); \ 336 } \ 337 } while (0) 338 #endif 339 340 // 341 // NV_FILE and NV_FUNCTION macros are used to wrap the __FILE__ and __FUNCTION__ 342 // macros, respectively, to enable passing them as parameters on release builds 343 // without linking the strings into the object files. Instead, this will use 344 // NV_LOG and other utilities to pass values in a way that the same information 345 // can be decoded on retail builds. 346 // 347 // On non-release builds, the strings are directly referenced and included in 348 // the builds (just like their normal references in DBG_PRINTF() and 349 // DBG_BREAKPOINT()). 350 // 351 // In MODS builds, we allow all printfs, but don't automatically include the 352 // __FILE__ or __FUNCTION__ references. 353 // 354 #if NV_PRINTF_STRINGS_ALLOWED && (!defined(NV_MODS) || defined(SIM_BUILD) || defined(DEBUG) || defined(NV_MODS_INTERNAL)) 355 #define NV_FILE_STR __FILE__ 356 #define NV_FILE __FILE__ 357 #define NV_FILE_FMT "%s" 358 #define NV_FILE_TYPE const char * 359 #define NV_FUNCTION_STR __FUNCTION__ 360 #define NV_FUNCTION __FUNCTION__ 361 #define NV_FUNCTION_FMT "%s" 362 #define NV_FUNCTION_TYPE const char * 363 #else 364 #ifndef NV_FILE_STR 365 #define NV_FILE_STR "<file>" 366 #endif 367 #ifdef NVLOG_FILEID 368 # define NV_FILE NVLOG_FILEID 369 #else 370 # define NV_FILE 0 371 #endif 372 #define NV_FILE_FMT "<fileid:0x%06x>" 373 #define NV_FILE_TYPE NvU32 374 // 375 // A couple caveats on portUtilExGetStackTrace(): 376 // 377 // 1. portUtilExGetStackTrace is not supported on all builds. For example, see 378 // GCC support in util-gcc-clang.h. 379 // 380 // 2. portUtilExGetStackTrace(0) will give us the current IP, which is 381 // current_function()+offset. Commands such as `ln` in windbg can translate the 382 // IP into func+offset. But sometimes, due to inlining/optimizations, the 383 // current function at runtime is not the same as at compile time. In the 384 // inlining example, if a function using NV_FUNCTION is inlined, the pointer 385 // printed will be calling_function()+offset. 386 // 387 //#define NV_FUNCTION portUtilExGetStackTrace(0) 388 #define NV_FUNCTION_STR "<func>" 389 #define NV_FUNCTION 0 390 #define NV_FUNCTION_FMT "<func:%p>" 391 #define NV_FUNCTION_TYPE NvUPtr 392 #endif 393 394 #ifdef __cplusplus 395 } 396 #endif //__cplusplus 397 398 /// @} 399 #endif // NVPRINTF_H 400