From 6622735ea8f6a95af938561b4c35e1380f9c5537 Mon Sep 17 00:00:00 2001 From: Roberto Medina Date: Fri, 30 Jun 2023 17:51:25 +0200 Subject: [PATCH] arch: arm64: add support for coredump * Add support for coredump on ARM64 architectures. * Add the script used for post-processing coredump output. Signed-off-by: Marcelo Ruaro Signed-off-by: Rodrigo Cataldo Signed-off-by: Roberto Medina --- arch/Kconfig | 1 + arch/arm64/core/CMakeLists.txt | 1 + arch/arm64/core/coredump.c | 105 +++++++++++++++++++ include/zephyr/debug/coredump.h | 1 + scripts/coredump/gdbstubs/__init__.py | 4 + scripts/coredump/gdbstubs/arch/arm64.py | 131 ++++++++++++++++++++++++ 6 files changed, 243 insertions(+) create mode 100644 arch/arm64/core/coredump.c create mode 100644 scripts/coredump/gdbstubs/arch/arm64.py diff --git a/arch/Kconfig b/arch/Kconfig index 24dce5c0c9cd..6179fd7645e2 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -43,6 +43,7 @@ config ARM64 select ARCH_IS_SET select 64BIT select HAS_DTS + select ARCH_SUPPORTS_COREDUMP select HAS_ARM_SMCCC select ARCH_HAS_THREAD_LOCAL_STORAGE select USE_SWITCH diff --git a/arch/arm64/core/CMakeLists.txt b/arch/arm64/core/CMakeLists.txt index 2a44e1969c1e..25cd7f8df6b8 100644 --- a/arch/arm64/core/CMakeLists.txt +++ b/arch/arm64/core/CMakeLists.txt @@ -37,6 +37,7 @@ zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c) zephyr_library_sources_ifdef(CONFIG_HAS_ARM_SMCCC smccc-call.S) zephyr_library_sources_ifdef(CONFIG_AARCH64_IMAGE_HEADER header.S) zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) +zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c) if ((CONFIG_MP_MAX_NUM_CPUS GREATER 1) OR (CONFIG_SMP)) zephyr_library_sources(smp.c) endif () diff --git a/arch/arm64/core/coredump.c b/arch/arm64/core/coredump.c new file mode 100644 index 000000000000..399cf85e3d0f --- /dev/null +++ b/arch/arm64/core/coredump.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022 Huawei Technologies SASU + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* Identify the version of this block (in case of architecture changes). + * To be interpreted by the target architecture specific block parser. + */ +#define ARCH_HDR_VER 1 + +/* Structure to store the architecture registers passed arch_coredump_info_dump + * As callee saved registers are not provided in z_arch_esf_t structure in Zephyr + * we just need 22 registers. + */ +struct arm64_arch_block { + struct { + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t lr; + uint64_t spsr; + uint64_t elr; + } r; +} __packed; + + +/* + * Register block takes up too much stack space + * if defined within function. So define it here. + */ +static struct arm64_arch_block arch_blk; + +void arch_coredump_info_dump(const z_arch_esf_t *esf) +{ + /* Target architecture information header */ + /* Information just relevant to the python parser */ + 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)); + + /* + * Copies the thread registers to a memory block that will be printed out + * The thread registers are already provided by structure z_arch_esf_t + */ + arch_blk.r.x0 = esf->x0; + arch_blk.r.x1 = esf->x1; + arch_blk.r.x2 = esf->x2; + arch_blk.r.x3 = esf->x3; + arch_blk.r.x4 = esf->x4; + arch_blk.r.x5 = esf->x5; + arch_blk.r.x6 = esf->x6; + arch_blk.r.x7 = esf->x7; + arch_blk.r.x8 = esf->x8; + arch_blk.r.x9 = esf->x9; + arch_blk.r.x10 = esf->x10; + arch_blk.r.x11 = esf->x11; + arch_blk.r.x12 = esf->x12; + arch_blk.r.x13 = esf->x13; + arch_blk.r.x14 = esf->x14; + arch_blk.r.x15 = esf->x15; + arch_blk.r.x16 = esf->x16; + arch_blk.r.x17 = esf->x17; + arch_blk.r.x18 = esf->x18; + arch_blk.r.lr = esf->lr; + arch_blk.r.spsr = esf->spsr; + arch_blk.r.elr = esf->elr; + + /* 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_ARM64; +} diff --git a/include/zephyr/debug/coredump.h b/include/zephyr/debug/coredump.h index e3ab8df28d30..12b743e1f605 100644 --- a/include/zephyr/debug/coredump.h +++ b/include/zephyr/debug/coredump.h @@ -123,6 +123,7 @@ enum coredump_tgt_code { COREDUMP_TGT_ARM_CORTEX_M, COREDUMP_TGT_RISC_V, COREDUMP_TGT_XTENSA, + COREDUMP_TGT_ARM64, }; /* Coredump header */ diff --git a/scripts/coredump/gdbstubs/__init__.py b/scripts/coredump/gdbstubs/__init__.py index 72745dc8b872..c6d783206821 100644 --- a/scripts/coredump/gdbstubs/__init__.py +++ b/scripts/coredump/gdbstubs/__init__.py @@ -9,6 +9,7 @@ from gdbstubs.arch.arm_cortex_m import GdbStub_ARM_CortexM from gdbstubs.arch.risc_v import GdbStub_RISC_V from gdbstubs.arch.xtensa import GdbStub_Xtensa +from gdbstubs.arch.arm64 import GdbStub_ARM64 class TgtCode: UNKNOWN = 0 @@ -17,6 +18,7 @@ class TgtCode: ARM_CORTEX_M = 3 RISC_V = 4 XTENSA = 5 + ARM64 = 6 def get_gdbstub(logfile, elffile): stub = None @@ -33,5 +35,7 @@ def get_gdbstub(logfile, elffile): stub = GdbStub_RISC_V(logfile=logfile, elffile=elffile) elif tgt_code == TgtCode.XTENSA: stub = GdbStub_Xtensa(logfile=logfile, elffile=elffile) + elif tgt_code == TgtCode.ARM64: + stub = GdbStub_ARM64(logfile=logfile, elffile=elffile) return stub diff --git a/scripts/coredump/gdbstubs/arch/arm64.py b/scripts/coredump/gdbstubs/arch/arm64.py new file mode 100644 index 000000000000..008fb88c1b96 --- /dev/null +++ b/scripts/coredump/gdbstubs/arch/arm64.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022 Huawei Technologies SASU +# +# SPDX-License-Identifier: Apache-2.0 + +import binascii +import logging +import struct + +from gdbstubs.gdbstub import GdbStub + + +logger = logging.getLogger("gdbstub") + + +class RegNum(): + X0 = 0 # X0-X29 - 30 GP registers + X1 = 1 + X2 = 2 + X3 = 3 + X4 = 4 + X5 = 5 + X6 = 6 + X7 = 7 + X8 = 8 + X9 = 9 + X10 = 10 + X11 = 11 + X12 = 12 + X13 = 13 + X14 = 14 + X15 = 15 + X16 = 16 + X17 = 17 + X18 = 18 + X19 = 19 + X20 = 20 + X21 = 21 + X22 = 22 + X23 = 23 + X24 = 24 + X25 = 25 + X26 = 26 + X27 = 27 + X28 = 28 + X29 = 29 # Frame pointer register + LR = 30 # X30 Link Register(LR) + SP_EL0 = 31 # Stack pointer EL0 (SP_EL0) + PC = 32 # Program Counter (PC) + + +class GdbStub_ARM64(GdbStub): + ARCH_DATA_BLK_STRUCT = " unknown value + # Send in "xxxxxxxx" + pkt += b'x' * 16 + + idx += 1 + + self.put_gdb_packet(pkt) + + def handle_register_single_read_packet(self, pkt): + # Mark registers as "". + # 'p' packets are usually used for registers + # other than the general ones (e.g. eax, ebx) + # so we can safely reply "xxxxxxxx" here. + self.put_gdb_packet(b'x' * 16)