debug: coredump: add xtensa coredump

Adds Xtensa as supported architecture for coredump. Fixes
a few typos in documentation, Kconfig and a C file. Dumps
minimal set of registers shown by 'info registers' in GDB
for the sample_controller and ESP32 SOCs. Updates tests.

Signed-off-by: Lauren Murphy <lauren.murphy@intel.com>
This commit is contained in:
Lauren Murphy 2021-10-20 20:53:04 -05:00 committed by Anas Nashif
commit c1711997bc
9 changed files with 174 additions and 12 deletions

View file

@ -37,7 +37,7 @@ config XTENSA_NO_IPC
bool "Core has no IPC support" bool "Core has no IPC support"
select ATOMIC_OPERATIONS_C select ATOMIC_OPERATIONS_C
help help
Uncheck this if you core does not implement "SCOMPARE1" register and "s32c1i" Uncheck this if your core does not implement "SCOMPARE1" register and "s32c1i"
instruction. instruction.
config XTENSA_RESET_VECTOR config XTENSA_RESET_VECTOR

View file

@ -18,6 +18,7 @@ zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c)
zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c)
zephyr_library_sources_ifdef(CONFIG_XTENSA_ENABLE_BACKTRACE xtensa_backtrace.c) zephyr_library_sources_ifdef(CONFIG_XTENSA_ENABLE_BACKTRACE xtensa_backtrace.c)
zephyr_library_sources_ifdef(CONFIG_XTENSA_ENABLE_BACKTRACE debug_helpers_asm.S) zephyr_library_sources_ifdef(CONFIG_XTENSA_ENABLE_BACKTRACE debug_helpers_asm.S)
zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c)
zephyr_library_sources_ifdef(CONFIG_GDBSTUB gdbstub.c) zephyr_library_sources_ifdef(CONFIG_GDBSTUB gdbstub.c)

159
arch/xtensa/core/coredump.c Normal file
View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2021 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <debug/coredump.h>
#include <xtensa-asm2.h>
#define ARCH_HDR_VER 1
#define XTENSA_BLOCK_HDR_VER 1
enum xtensa_soc_code {
XTENSA_SOC_UNKNOWN = 0,
XTENSA_SOC_SAMPLE_CONTROLLER,
XTENSA_SOC_ESP32,
};
struct xtensa_arch_block {
/* Each Xtensa SOC can omit registers (e.g. loop
* registers) or assign different index numbers
* in xtensa-config.c. GDB identifies registers
* based on these indices
*
* (This must be the first field or the GDB server
* won't be able to unpack the struct while parsing)
*/
uint8_t soc;
/* Future versions of Xtensa coredump
* may expand minimum set of registers
*
* (This should stay the second field for the same
* reason as the first once we have more versions)
*/
uint16_t version;
struct {
/* Minimum set shown by GDB 'info registers',
* skipping user-defined register EXPSTATE
*
* WARNING: IF YOU CHANGE THE ORDER OF THE REGISTERS,
* YOU MUST UPDATE THE ORDER OF THE REGISTERS IN
* EACH OF THE XtensaSoc_ RegNum enums IN
* scripts/coredump/gdbstubs/arch/xtensa.py TO MATCH.
* See xtensa.py's map_register function for details
*/
uint32_t pc;
uint32_t exccause;
uint32_t excvaddr;
uint32_t sar;
uint32_t ps;
#if XCHAL_HAVE_S32C1I
uint32_t scompare1;
#endif
uint32_t a0;
uint32_t a1;
uint32_t a2;
uint32_t a3;
uint32_t a4;
uint32_t a5;
uint32_t a6;
uint32_t a7;
uint32_t a8;
uint32_t a9;
uint32_t a10;
uint32_t a11;
uint32_t a12;
uint32_t a13;
uint32_t a14;
uint32_t a15;
#if XCHAL_HAVE_LOOPS
uint32_t lbeg;
uint32_t lend;
uint32_t lcount;
#endif
} r;
} __packed;
/*
* This might be too large for stack space if defined
* inside function. So do it here.
*/
static struct xtensa_arch_block arch_blk;
void arch_coredump_info_dump(const z_arch_esf_t *esf)
{
struct coredump_arch_hdr_t hdr = {
.id = COREDUMP_ARCH_HDR_ID,
.hdr_version = ARCH_HDR_VER,
.num_bytes = sizeof(arch_blk),
};
/* Nothing to process */
if (esf == NULL) {
return;
}
(void)memset(&arch_blk, 0, sizeof(arch_blk));
arch_blk.version = XTENSA_BLOCK_HDR_VER;
#if CONFIG_SOC_XTENSA_SAMPLE_CONTROLLER
arch_blk.soc = XTENSA_SOC_SAMPLE_CONTROLLER;
#elif CONFIG_SOC_ESP32
arch_blk.soc = XTENSA_SOC_ESP32;
#else
arch_blk.soc = XTENSA_SOC_UNKNOWN;
#endif
__asm__ volatile("rsr.exccause %0" : "=r"(arch_blk.r.exccause));
int *bsa = *(int **)esf;
arch_blk.r.pc = bsa[BSA_PC_OFF/4];
__asm__ volatile("rsr.excvaddr %0" : "=r"(arch_blk.r.excvaddr));
arch_blk.r.ps = bsa[BSA_PS_OFF/4];
#if XCHAL_HAVE_S32C1I
arch_blk.r.scompare1 = bsa[BSA_SCOMPARE1_OFF];
#endif
arch_blk.r.sar = bsa[BSA_SAR_OFF/4];
arch_blk.r.a0 = bsa[BSA_A0_OFF/4];
arch_blk.r.a1 = (uint32_t)((char *)bsa) + BASE_SAVE_AREA_SIZE;
arch_blk.r.a2 = bsa[BSA_A2_OFF/4];
arch_blk.r.a3 = bsa[BSA_A3_OFF/4];
if (bsa - esf > 4) {
arch_blk.r.a4 = bsa[-4];
arch_blk.r.a5 = bsa[-3];
arch_blk.r.a6 = bsa[-2];
arch_blk.r.a7 = bsa[-1];
}
if (bsa - esf > 8) {
arch_blk.r.a8 = bsa[-8];
arch_blk.r.a9 = bsa[-7];
arch_blk.r.a10 = bsa[-6];
arch_blk.r.a11 = bsa[-5];
}
if (bsa - esf > 12) {
arch_blk.r.a12 = bsa[-12];
arch_blk.r.a13 = bsa[-11];
arch_blk.r.a14 = bsa[-10];
arch_blk.r.a15 = bsa[-9];
}
#if XCHAL_HAVE_LOOPS
arch_blk.r.lbeg = bsa[BSA_LBEG_OFF/4];
arch_blk.r.lend = bsa[BSA_LEND_OFF/4];
arch_blk.r.lcount = bsa[BSA_LCOUNT_OFF/4];
#endif
/* Send for output */
coredump_buffer_output((uint8_t *)&hdr, sizeof(hdr));
coredump_buffer_output((uint8_t *)&arch_blk, sizeof(arch_blk));
}
uint16_t arch_coredump_tgt_code_get(void)
{
return COREDUMP_TGT_XTENSA;
}

View file

@ -4,8 +4,8 @@ Core Dump
######### #########
The core dump module enables dumping the CPU registers and memory content The core dump module enables dumping the CPU registers and memory content
for offline debugging. This module is called when fatal error is for offline debugging. This module is called when a fatal error is
encountered, and the data is printed or stored according to which backends encountered and prints or stores data according to which backends
are enabled. are enabled.
Configuration Configuration
@ -25,15 +25,15 @@ Here are the choices regarding memory dump:
* ``DEBUG_COREDUMP_MEMORY_DUMP_MIN``: only dumps the stack of the exception * ``DEBUG_COREDUMP_MEMORY_DUMP_MIN``: only dumps the stack of the exception
thread, its thread struct, and some other bare minimal data to support thread, its thread struct, and some other bare minimal data to support
walking the stack in debugger. Use this only if absolute minimum of data walking the stack in the debugger. Use this only if absolute minimum of data
dump is desired. dump is desired.
Usage Usage
***** *****
When the core dump module is enabled, during fatal error, CPU registers When the core dump module is enabled, during a fatal error, CPU registers
and memory content are being printed or stored according to which backends and memory content are printed or stored according to which backends
are enabled. This core dump data can fed into a custom made GDB server as are enabled. This core dump data can fed into a custom-made GDB server as
a remote target for GDB (and other GDB compatible debuggers). CPU registers, a remote target for GDB (and other GDB compatible debuggers). CPU registers,
memory content and stack can be examined in the debugger. memory content and stack can be examined in the debugger.

View file

@ -78,6 +78,7 @@ enum coredump_tgt_code {
COREDUMP_TGT_X86_64, COREDUMP_TGT_X86_64,
COREDUMP_TGT_ARM_CORTEX_M, COREDUMP_TGT_ARM_CORTEX_M,
COREDUMP_TGT_RISC_V, COREDUMP_TGT_RISC_V,
COREDUMP_TGT_XTENSA,
}; };
/* Coredump header */ /* Coredump header */

View file

@ -8,6 +8,7 @@ config SOC_ESP32
select CLOCK_CONTROL_ESP32 select CLOCK_CONTROL_ESP32
select DYNAMIC_INTERRUPTS select DYNAMIC_INTERRUPTS
select ARCH_HAS_GDBSTUB select ARCH_HAS_GDBSTUB
select ARCH_SUPPORTS_COREDUMP
if SOC_ESP32 if SOC_ESP32

View file

@ -5,3 +5,4 @@ config SOC_XTENSA_SAMPLE_CONTROLLER
bool "Xtensa sample_controller core" bool "Xtensa sample_controller core"
select XTENSA select XTENSA
select XTENSA_HAL select XTENSA_HAL
select ARCH_SUPPORTS_COREDUMP

View file

@ -357,7 +357,7 @@ config GDBSTUB_SERIAL_BACKEND
bool "Use serial backend" bool "Use serial backend"
depends on SERIAL depends on SERIAL
help help
Use serial as backenf for GDB Use serial as backend for GDB
endchoice endchoice
@ -366,7 +366,7 @@ config GDBSTUB_SERIAL_BACKEND_NAME
depends on GDBSTUB_SERIAL_BACKEND depends on GDBSTUB_SERIAL_BACKEND
default "UART_0" default "UART_0"
help help
Use serial as backenf for GDB Use serial as backend for GDB
config GDBSTUB_BUF_SZ config GDBSTUB_BUF_SZ
int "GDB backend send/receive buffer size (in bytes)" int "GDB backend send/receive buffer size (in bytes)"

View file

@ -273,10 +273,9 @@ out:
} }
/** /**
* @brief Process the stored coredump in flash partition. * @brief Erase the stored coredump from flash partition.
* *
* This reads the stored coredump data and processes it via * This erases the stored coredump data from the flash partition.
* the callback function.
* *
* @return 0 if successful; error otherwise * @return 0 if successful; error otherwise
*/ */