@@ -215,7 +215,8 @@ The public API headers are grouped by topics:
[log] (@ref rte_log.h),
[errno] (@ref rte_errno.h),
[trace] (@ref rte_trace.h),
- [trace_point] (@ref rte_trace_point.h)
+ [trace_point] (@ref rte_trace_point.h),
+ [oops] (@ref rte_oops.h)
- **misc**:
[EAL config] (@ref rte_eal.h),
@@ -226,3 +226,7 @@ Other options
To disable use of max SIMD bitwidth limit::
--force-max-simd-bitwidth=0
+
+* ``--no-oops``:
+
+ Disable default EAL oops handler.
@@ -62,6 +62,16 @@ New Features
* Added bus-level parsing of the devargs syntax.
* Kept compatibility with the legacy syntax as parsing fallback.
+* **Added APIs for oops handling support.**
+
+ Added support for decoding the oops fault with ``libunwind`` based backtrace,
+ architecture-specific register dump, instruction memory dump, and
+ stack memory dump. EAL installs the default oops handler if ``no-oops`` EAL
+ command line argument is not provided. The default EAL oops handler stores the
+ existing handler and invoke after decoding. It also offers ``rte_oops_decode``
+ API to integrate the EAL oops decode function where the application does not
+ use the default EAL handler.
+
Removed Items
-------------
@@ -107,6 +107,7 @@ eal_long_options[] = {
{OPT_TELEMETRY, 0, NULL, OPT_TELEMETRY_NUM },
{OPT_NO_TELEMETRY, 0, NULL, OPT_NO_TELEMETRY_NUM },
{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
+ {OPT_NO_OOPS, 0, NULL, OPT_NO_OOPS_NUM },
/* legacy options that will be removed in future */
{OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM },
@@ -1825,6 +1826,9 @@ eal_parse_common_option(int opt, const char *optarg,
return -1;
}
break;
+ case OPT_NO_OOPS_NUM:
+ conf->no_oops = 1;
+ break;
/* don't know what to do, leave this to caller */
default:
@@ -2128,6 +2132,7 @@ eal_common_usage(void)
" --"OPT_TELEMETRY" Enable telemetry support (on by default)\n"
" --"OPT_NO_TELEMETRY" Disable telemetry support\n"
" --"OPT_FORCE_MAX_SIMD_BITWIDTH" Force the max SIMD bitwidth\n"
+ " --"OPT_NO_OOPS" Disable default oops EAL handler(on by default)\n"
"\nEAL options for DEBUG use only:\n"
" --"OPT_HUGE_UNLINK" Unlink hugepage files after init\n"
" --"OPT_NO_HUGE" Use malloc instead of hugetlbfs\n"
@@ -94,6 +94,7 @@ struct internal_config {
unsigned int no_telemetry; /**< true to disable Telemetry */
struct simd_bitwidth max_simd_bitwidth;
/**< max simd bitwidth path to use */
+ unsigned int no_oops; /**< true to disable oops */
};
void eal_reset_internal_config(struct internal_config *internal_cfg);
@@ -93,6 +93,8 @@ enum {
OPT_NO_TELEMETRY_NUM,
#define OPT_FORCE_MAX_SIMD_BITWIDTH "force-max-simd-bitwidth"
OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
+#define OPT_NO_OOPS "no-oops"
+ OPT_NO_OOPS_NUM,
/* legacy option that will be removed in future */
#define OPT_PCI_BLACKLIST "pci-blacklist"
@@ -716,6 +716,9 @@ void __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset);
*/
void __rte_thread_uninit(void);
+int eal_oops_init(void);
+void eal_oops_fini(void);
+
/**
* asprintf(3) replacement for Windows.
*/
@@ -692,6 +692,7 @@ rte_eal_init(int argc, char **argv)
return -1;
}
+
thread_id = pthread_self();
eal_reset_internal_config(internal_conf);
@@ -719,6 +720,11 @@ rte_eal_init(int argc, char **argv)
/* FreeBSD always uses legacy memory model */
internal_conf->legacy_mem = true;
+ if (internal_conf->no_oops == 0 && eal_oops_init()) {
+ rte_eal_init_alert("oops init failed.");
+ rte_errno = ENOENT;
+ }
+
if (eal_plugins_init() < 0) {
rte_eal_init_alert("Cannot init plugins");
rte_errno = EINVAL;
@@ -973,6 +979,8 @@ rte_eal_cleanup(void)
rte_eal_memory_detach();
rte_trace_save();
eal_trace_fini();
+ if (internal_conf->no_oops == 0)
+ eal_oops_fini();
eal_cleanup_config(internal_conf);
return 0;
}
@@ -30,6 +30,7 @@ headers += files(
'rte_malloc.h',
'rte_memory.h',
'rte_memzone.h',
+ 'rte_oops.h',
'rte_pci_dev_feature_defs.h',
'rte_pci_dev_features.h',
'rte_per_lcore.h',
new file mode 100644
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell.
+ */
+
+#ifndef _RTE_OOPS_H_
+#define _RTE_OOPS_H_
+
+#include <rte_common.h>
+#include <rte_compat.h>
+#include <rte_config.h>
+
+/**
+ * @file
+ *
+ * RTE oops API
+ *
+ * This file provides the oops handling APIs to RTE applications.
+ *
+ * On rte_eal_init() invocation and if *--no-oops* not provided in the EAL
+ * command line argument, then EAL library installs the oops handler for
+ * the essential signals. The rte_oops_signals_enabled() API provides the list
+ * of signals the library installed by the EAL.
+ *
+ * The default EAL oops handler decodes the oops message using rte_oops_decode()
+ * and then calls the signal handler installed by the application before
+ * invoking the rte_eal_init(). This scheme will also enable the use of
+ * the default coredump handler(for gdb etc.) provided by OS if the application
+ * does not install any specific signal handler.
+ *
+ * The second case where the application installs the signal handler after
+ * the rte_eal_init() invocation, rte_oops_decode() provides the means of
+ * decoding the oops message in the application's fault handler.
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Maximum number of oops signals enabled in EAL.
+ * @see rte_oops_signals_enabled()
+ */
+#define RTE_OOPS_SIGNALS_MAX 32
+
+/**
+ * Get the list of enabled oops signals installed by EAL.
+ *
+ * @param [out] signals
+ * A pointer to store the enabled signals.
+ * Value NULL is allowed. if not NULL, then the size of this array must be
+ * at least RTE_OOPS_SIGNALS_MAX.
+ *
+ * @return
+ * Number of enabled oops signals.
+ */
+__rte_experimental
+int rte_oops_signals_enabled(int *signals);
+
+#if defined(RTE_EXEC_ENV_LINUX) || defined(RTE_EXEC_ENV_FREEBSD)
+#include <signal.h>
+#include <ucontext.h>
+
+/**
+ * Decode an oops
+ *
+ * This prototype is same as sa_sigaction defined in signal.h.
+ * Application must register signal handler using sigaction() with
+ * sa_flag as SA_SIGINFO flag to get this information from unix OS.
+ *
+ * @param sig
+ * Signal number
+ * @param info
+ * Signal info provided by sa_sigaction. Value NULL is allowed.
+ * @param uc
+ * ucontext_t provided when signal installed with SA_SIGINFO flag.
+ * Value NULL is allowed.
+ *
+ */
+__rte_experimental
+void rte_oops_decode(int sig, siginfo_t *info, ucontext_t *uc);
+#else
+
+/**
+ * Decode an oops
+ *
+ * @param sig
+ * Signal number
+ */
+__rte_experimental
+void rte_oops_decode(int sig);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_OOPS_H_ */
@@ -1017,6 +1017,11 @@ rte_eal_init(int argc, char **argv)
return -1;
}
+ if (internal_conf->no_oops == 0 && eal_oops_init()) {
+ rte_eal_init_alert("oops init failed.");
+ rte_errno = ENOENT;
+ }
+
if (eal_plugins_init() < 0) {
rte_eal_init_alert("Cannot init plugins");
rte_errno = EINVAL;
@@ -1370,6 +1375,8 @@ rte_eal_cleanup(void)
rte_eal_memory_detach();
rte_trace_save();
eal_trace_fini();
+ if (internal_conf->no_oops == 0)
+ eal_oops_fini();
eal_cleanup_config(internal_conf);
return 0;
}
new file mode 100644
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+
+#include <rte_oops.h>
+
+#include "eal_private.h"
+
+void
+rte_oops_decode(int sig, siginfo_t *info, ucontext_t *uc)
+{
+ RTE_SET_USED(sig);
+ RTE_SET_USED(info);
+ RTE_SET_USED(uc);
+
+}
+
+int
+rte_oops_signals_enabled(int *signals)
+{
+ RTE_SET_USED(signals);
+
+ return 0;
+}
+
+int
+eal_oops_init(void)
+{
+ return 0;
+}
+
+void
+eal_oops_fini(void)
+{
+}
@@ -6,5 +6,6 @@ sources += files(
'eal_unix_memory.c',
'eal_unix_timer.c',
'eal_firmware.c',
+ 'eal_oops.c',
'rte_thread.c',
)
@@ -426,6 +426,10 @@ EXPERIMENTAL {
# added in 21.08
rte_power_monitor_multi; # WINDOWS_NO_EXPORT
+
+ # added in 21.11
+ rte_oops_signals_enabled; # WINDOWS_NO_EXPORT
+ rte_oops_decode; # WINDOWS_NO_EXPORT
};
INTERNAL {