arm-trusted-firmware/include/common/debug.h
Govindraj Raja 7e619ecc89 refactor(aarch64): refactor usage of elx_panic
Currently we call el3_panic for panics from EL3 and elx_panic for
panics from lower ELs.

When we boot into a rich OS environment and interact with BL31 using
SMC/ABI calls and we can also decide to handle any lower EL panics in
EL3. Panic can occur in lower EL from rich OS or during SMC/ABI calls
after context switch to EL3.

But after booting into any rich OS we may land in panic either from
rich OS or while servicing any SMC call, here the logic to use
el3_panic or elx_panic is flawed as spsr_el3[3:0] is always EL3h
and end up in elx_panic even if panic occurred from EL3 during
SMC handling.

We try to decouple the elx_panic usage for its intended purpose,
introduce lower_el_panic which would call elx_panic, currently
lower_el_panic is called from default platform_ea_handle which
would be called due to panic from any of the lower ELs.

Also remove the weak linkage for elx_panic and rename it to
report_elx_panic which could be used with lower_el_panic.

Change-Id: I268bca89c01c60520d127ef6c7ba851460edc747
Signed-off-by: Govindraj Raja <govindraj.raja@arm.com>
2023-02-21 17:26:01 +00:00

135 lines
3.6 KiB
C

/*
* Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef DEBUG_H
#define DEBUG_H
#include <lib/utils_def.h>
/*
* The log output macros print output to the console. These macros produce
* compiled log output only if the LOG_LEVEL defined in the makefile (or the
* make command line) is greater or equal than the level required for that
* type of log output.
*
* The format expected is the same as for printf(). For example:
* INFO("Info %s.\n", "message") -> INFO: Info message.
* WARN("Warning %s.\n", "message") -> WARNING: Warning message.
*/
#define LOG_LEVEL_NONE U(0)
#define LOG_LEVEL_ERROR U(10)
#define LOG_LEVEL_NOTICE U(20)
#define LOG_LEVEL_WARNING U(30)
#define LOG_LEVEL_INFO U(40)
#define LOG_LEVEL_VERBOSE U(50)
#ifndef __ASSEMBLER__
#include <cdefs.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <drivers/console.h>
/*
* Define Log Markers corresponding to each log level which will
* be embedded in the format string and is expected by tf_log() to determine
* the log level.
*/
#define LOG_MARKER_ERROR "\xa" /* 10 */
#define LOG_MARKER_NOTICE "\x14" /* 20 */
#define LOG_MARKER_WARNING "\x1e" /* 30 */
#define LOG_MARKER_INFO "\x28" /* 40 */
#define LOG_MARKER_VERBOSE "\x32" /* 50 */
/*
* If the log output is too low then this macro is used in place of tf_log()
* below. The intent is to get the compiler to evaluate the function call for
* type checking and format specifier correctness but let it optimize it out.
*/
#define no_tf_log(fmt, ...) \
do { \
if (false) { \
tf_log(fmt, ##__VA_ARGS__); \
} \
} while (false)
#if LOG_LEVEL >= LOG_LEVEL_ERROR
# define ERROR(...) tf_log(LOG_MARKER_ERROR __VA_ARGS__)
# define ERROR_NL() tf_log_newline(LOG_MARKER_ERROR)
#else
# define ERROR(...) no_tf_log(LOG_MARKER_ERROR __VA_ARGS__)
# define ERROR_NL()
#endif
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
# define NOTICE(...) tf_log(LOG_MARKER_NOTICE __VA_ARGS__)
#else
# define NOTICE(...) no_tf_log(LOG_MARKER_NOTICE __VA_ARGS__)
#endif
#if LOG_LEVEL >= LOG_LEVEL_WARNING
# define WARN(...) tf_log(LOG_MARKER_WARNING __VA_ARGS__)
#else
# define WARN(...) no_tf_log(LOG_MARKER_WARNING __VA_ARGS__)
#endif
#if LOG_LEVEL >= LOG_LEVEL_INFO
# define INFO(...) tf_log(LOG_MARKER_INFO __VA_ARGS__)
#else
# define INFO(...) no_tf_log(LOG_MARKER_INFO __VA_ARGS__)
#endif
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
# define VERBOSE(...) tf_log(LOG_MARKER_VERBOSE __VA_ARGS__)
#else
# define VERBOSE(...) no_tf_log(LOG_MARKER_VERBOSE __VA_ARGS__)
#endif
const char *get_el_str(unsigned int el);
#if ENABLE_BACKTRACE
void backtrace(const char *cookie);
#else
#define backtrace(x)
#endif
void __dead2 do_panic(void);
void __dead2 report_elx_panic(void);
#define panic() \
do { \
backtrace(__func__); \
console_flush(); \
do_panic(); \
} while (false)
#if CRASH_REPORTING
/* --------------------------------------------------------------------
* do_lower_el_panic assumes it's called due to a panic from a lower EL
* This call will not return.
* --------------------------------------------------------------------
*/
#define lower_el_panic() \
do { \
console_flush(); \
report_elx_panic(); \
} while (false)
#else
#define lower_el_panic()
#endif
/* Function called when stack protection check code detects a corrupted stack */
void __dead2 __stack_chk_fail(void);
void tf_log(const char *fmt, ...) __printflike(1, 2);
void tf_log_newline(const char log_fmt[2]);
void tf_log_set_max_level(unsigned int log_level);
#endif /* __ASSEMBLER__ */
#endif /* DEBUG_H */