mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-15 09:04:17 +00:00

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>
135 lines
3.6 KiB
C
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 */
|