This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit cdeb720bf8a3b7fd29693c40e36e11cd9633b209 Author: Tiago Medicci Serrano <[email protected]> AuthorDate: Wed Sep 4 16:25:57 2024 -0300 xtensa/esp32[|s2|s3]: Fix task backtrace dump - Fix `MAKE_PC_FROM_RA` macro to consider the instruction region base address; - Add sanity check for calculated PC and SP registers; - Check if the stack pointer is within the interrupt stack to enable backtrace dump if an exception occurs during the ISR; --- arch/risc-v/src/common/espressif/Make.defs | 2 +- arch/xtensa/include/irq.h | 2 +- arch/xtensa/src/common/xtensa_backtrace.c | 28 ++++++++++++++++--- arch/xtensa/src/common/xtensa_macros.S | 29 +++++++++++++++++--- arch/xtensa/src/esp32/Make.defs | 4 +-- arch/xtensa/src/esp32/chip_macros.h | 31 +++++++++++++++++++--- arch/xtensa/src/esp32/chip_memory.h | 8 +++++- arch/xtensa/src/esp32s2/Make.defs | 4 +-- arch/xtensa/src/esp32s2/chip_memory.h | 8 +++++- arch/xtensa/src/esp32s3/Make.defs | 4 +-- arch/xtensa/src/esp32s3/chip_macros.h | 31 +++++++++++++++++++--- arch/xtensa/src/esp32s3/chip_memory.h | 8 +++++- .../esp32/esp32-wrover-kit/configs/gpio/defconfig | 1 - 13 files changed, 133 insertions(+), 27 deletions(-) diff --git a/arch/risc-v/src/common/espressif/Make.defs b/arch/risc-v/src/common/espressif/Make.defs index 7002bd2b5b..97b24aa1c2 100644 --- a/arch/risc-v/src/common/espressif/Make.defs +++ b/arch/risc-v/src/common/espressif/Make.defs @@ -136,7 +136,7 @@ endif ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty ifndef ESP_HAL_3RDPARTY_VERSION - ESP_HAL_3RDPARTY_VERSION = 20690e67695f0a8170a19ec99e2e9a13b620e94d + ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd endif ifndef ESP_HAL_3RDPARTY_URL diff --git a/arch/xtensa/include/irq.h b/arch/xtensa/include/irq.h index 21ce8f20f4..1d299f428e 100644 --- a/arch/xtensa/include/irq.h +++ b/arch/xtensa/include/irq.h @@ -250,7 +250,7 @@ noinstrument_function static inline void xtensa_setps(uint32_t ps) /* Return the current value of the stack pointer */ -static inline uint32_t up_getsp(void) +static inline_function uint32_t up_getsp(void) { register uint32_t sp; diff --git a/arch/xtensa/src/common/xtensa_backtrace.c b/arch/xtensa/src/common/xtensa_backtrace.c index 8029eba2c8..fb6da7a144 100644 --- a/arch/xtensa/src/common/xtensa_backtrace.c +++ b/arch/xtensa/src/common/xtensa_backtrace.c @@ -30,14 +30,29 @@ #include "sched/sched.h" #include "xtensa.h" +#include "chip.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* When the Windowed Register Option is configured, the register-window call + * instructions only store the low 30 bits of the return address, enabling + * addressing instructions within a 1GB region. To convert the return address + * to a valid PC, we need to add the base address of the instruction region. + * The following macro is used to define the base address of the 1GB region, + * which may not start in 0x00000000. This macro can be overriden in + * `chip_memory.h` of the chip directory. + */ + +#ifndef XTENSA_INSTUCTION_REGION +# define XTENSA_INSTUCTION_REGION 0x00000000 +#endif + /* Convert return address to a valid pc */ -#define MAKE_PC_FROM_RA(ra) (uintptr_t *)((ra) & 0x3fffffff) +#define MAKE_PC_FROM_RA(ra) \ + (uintptr_t *)(((ra) & 0x3fffffff) | XTENSA_INSTUCTION_REGION) /**************************************************************************** * Private Types @@ -173,17 +188,21 @@ static int backtrace_stack(uintptr_t *base, uintptr_t *limit, while (i < size) { - ra = (uintptr_t *)*(sp - 4); + ra = MAKE_PC_FROM_RA((uintptr_t)(*(sp - 4))); sp = (uintptr_t *)*(sp - 3); - if (sp >= limit || sp < base || ra == NULL) + if (!(xtensa_ptr_exec(ra) && xtensa_sp_sane((uintptr_t)sp)) +#if CONFIG_ARCH_INTERRUPTSTACK < 15 + || sp >= limit || sp < base +#endif + ) { break; } if ((*skip)-- <= 0) { - buffer[i++] = MAKE_PC_FROM_RA((uintptr_t)ra); + buffer[i++] = ra; } } @@ -250,6 +269,7 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size, int skip) (void *)up_getsp(), NULL, buffer, size, &skip); #else + xtensa_window_spill(); ret = backtrace_stack(rtcb->stack_base_ptr, rtcb->stack_base_ptr + rtcb->adj_stack_size, (void *)up_getsp(), NULL, diff --git a/arch/xtensa/src/common/xtensa_macros.S b/arch/xtensa/src/common/xtensa_macros.S index 7b531dc131..de73d49195 100644 --- a/arch/xtensa/src/common/xtensa_macros.S +++ b/arch/xtensa/src/common/xtensa_macros.S @@ -42,9 +42,32 @@ ****************************************************************************/ #if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15 - .macro setintstack tmp1 tmp2 - movi a1, g_intstacktop - .endm + .macro setintstack tmp1 tmp2 + + /* Load g_intstacktop (the start of the interrupt stack) */ + + movi \tmp1, g_intstacktop + + /* If a1 < g_intstackalloc (outside the interrupt stack boundary), + * set a1 (sp) to g_intstacktop (switch to the interrupt stack). + */ + + movi \tmp2, g_intstackalloc /* Load the end (low address) of the interrupt stack */ + sub \tmp2, a1, \tmp2 + movltz a1, \tmp1, \tmp2 + + /* If a1 >= g_intstacktop, sp is outside the interrupt stack boundaries */ + + movi \tmp2, g_intstacktop /* Load the start (high address) of the interrupt stack */ + sub \tmp2, a1, \tmp2 + movgez a1, \tmp1, \tmp2 + + /* If neither movltz and movgez moved g_intstacktop (on /tmp1) to a1, + * it means that the stack pointer was already pointing to the interrupt + * stack and no action is required. + */ + + .endm #endif /**************************************************************************** diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index 983e6d7aac..740b9de033 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -213,7 +213,7 @@ endif ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty ifndef ESP_HAL_3RDPARTY_VERSION - ESP_HAL_3RDPARTY_VERSION = 20690e67695f0a8170a19ec99e2e9a13b620e94d + ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd endif ifndef ESP_HAL_3RDPARTY_URL @@ -246,7 +246,7 @@ chip/$(ESP_HAL_3RDPARTY_REPO): # Silent preprocessor warnings -CFLAGS += -Wno-undef -Wno-unused-variable +CFLAGS += -Wno-undef -Wno-unused-variable -fno-jump-tables -fno-tree-switch-conversion # Enable strict volatile bitfield access diff --git a/arch/xtensa/src/esp32/chip_macros.h b/arch/xtensa/src/esp32/chip_macros.h index 2a68cedf45..d7a06e424c 100644 --- a/arch/xtensa/src/esp32/chip_macros.h +++ b/arch/xtensa/src/esp32/chip_macros.h @@ -120,10 +120,33 @@ #if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15 .macro setintstack tmp1 tmp2 - getcoreid \tmp1 /* tmp1 = Core ID (0 or 1) */ - movi \tmp2, g_cpu_intstack_top /* tmp2 = Array of stack pointers */ - addx4 \tmp2, \tmp1, \tmp2 /* tmp2 = tmp2 + (tmp1 << 2) */ - l32i a1, \tmp2, 0 /* a1 = *tmp2 */ + getcoreid \tmp1 /* tmp1 = Core ID (0 or 1) */ + movi \tmp2, g_cpu_intstack_top /* tmp2 = Array of stack pointers */ + addx4 \tmp2, \tmp1, \tmp2 /* tmp2 = tmp2 + (tmp1 << 2) */ + l32i \tmp1, \tmp2, 0 /* Load the top of the interrupt stack for this core */ + + /* tmp1 represents the top of the interrupt stack for this core + * If a1 >= tmp1, sp is outside the interrupt stack boundaries. + */ + + l32i \tmp2, \tmp2, 0 /* Load the top of the interrupt stack for this core */ + sub \tmp2, a1, \tmp2 + movgez a1, \tmp1, \tmp2 + + /* If a1 < (tmp1 - INTSTACK_SIZE), sp is outside the interrupt stack + * boundaries. + */ + + movi \tmp2, CONFIG_ARCH_INTERRUPTSTACK + sub \tmp2, \tmp1, \tmp2 + sub \tmp2, a1, \tmp2 + movltz a1, \tmp1, \tmp2 + + /* If neither movltz and movgez moved the top of the interrupt stack to + * a1, it means that the stack pointer was already pointing to the + * interrupt stack and no action is required. + */ + .endm #endif diff --git a/arch/xtensa/src/esp32/chip_memory.h b/arch/xtensa/src/esp32/chip_memory.h index 91b513d862..0636213ef1 100644 --- a/arch/xtensa/src/esp32/chip_memory.h +++ b/arch/xtensa/src/esp32/chip_memory.h @@ -29,6 +29,12 @@ #include "hardware/esp32_soc.h" #endif +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define XTENSA_INSTUCTION_REGION 0x40000000 + /**************************************************************************** * Inline Functions ****************************************************************************/ @@ -48,7 +54,7 @@ extern "C" static inline bool xtensa_sp_sane(uint32_t sp) { - return (esp32_sp_dram(sp) && ((sp & 0x0f) == 0)); + return esp32_sp_dram(sp); } /**************************************************************************** diff --git a/arch/xtensa/src/esp32s2/Make.defs b/arch/xtensa/src/esp32s2/Make.defs index 29b74def1f..840ea0cdcf 100644 --- a/arch/xtensa/src/esp32s2/Make.defs +++ b/arch/xtensa/src/esp32s2/Make.defs @@ -145,7 +145,7 @@ endif ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty ifndef ESP_HAL_3RDPARTY_VERSION - ESP_HAL_3RDPARTY_VERSION = 20690e67695f0a8170a19ec99e2e9a13b620e94d + ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd endif ifndef ESP_HAL_3RDPARTY_URL @@ -171,7 +171,7 @@ chip/$(ESP_HAL_3RDPARTY_REPO): # Silent preprocessor warnings -CFLAGS += -Wno-undef -Wno-unused-variable +CFLAGS += -Wno-undef -Wno-unused-variable -fno-jump-tables -fno-tree-switch-conversion # Enable strict volatile bitfield access diff --git a/arch/xtensa/src/esp32s2/chip_memory.h b/arch/xtensa/src/esp32s2/chip_memory.h index b4d42826f3..f3180cb6f4 100644 --- a/arch/xtensa/src/esp32s2/chip_memory.h +++ b/arch/xtensa/src/esp32s2/chip_memory.h @@ -29,6 +29,12 @@ #include "hardware/esp32s2_soc.h" #endif +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define XTENSA_INSTUCTION_REGION 0x40000000 + /**************************************************************************** * Inline Functions ****************************************************************************/ @@ -48,7 +54,7 @@ extern "C" static inline bool xtensa_sp_sane(uint32_t sp) { - return (esp32s2_sp_dram(sp) && ((sp & 0x0f) == 0)); + return esp32s2_sp_dram(sp); } /**************************************************************************** diff --git a/arch/xtensa/src/esp32s3/Make.defs b/arch/xtensa/src/esp32s3/Make.defs index 5fed43a911..6fadf64279 100644 --- a/arch/xtensa/src/esp32s3/Make.defs +++ b/arch/xtensa/src/esp32s3/Make.defs @@ -211,7 +211,7 @@ endif ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty ifndef ESP_HAL_3RDPARTY_VERSION - ESP_HAL_3RDPARTY_VERSION = 20690e67695f0a8170a19ec99e2e9a13b620e94d + ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd endif ifndef ESP_HAL_3RDPARTY_URL @@ -244,7 +244,7 @@ chip/$(ESP_HAL_3RDPARTY_REPO): # Silent preprocessor warnings -CFLAGS += -Wno-undef -Wno-unused-variable +CFLAGS += -Wno-undef -Wno-unused-variable -fno-jump-tables -fno-tree-switch-conversion CFLAGS += ${DEFINE_PREFIX}_RETARGETABLE_LOCKING # Enable strict volatile bitfield access diff --git a/arch/xtensa/src/esp32s3/chip_macros.h b/arch/xtensa/src/esp32s3/chip_macros.h index 658789489f..652d95a3a3 100644 --- a/arch/xtensa/src/esp32s3/chip_macros.h +++ b/arch/xtensa/src/esp32s3/chip_macros.h @@ -104,10 +104,33 @@ #if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15 .macro setintstack tmp1 tmp2 - getcoreid \tmp1 /* tmp1 = Core ID (0 or 1) */ - movi \tmp2, g_cpu_intstack_top /* tmp2 = Array of stack pointers */ - addx4 \tmp2, \tmp1, \tmp2 /* tmp2 = tmp2 + (tmp1 << 2) */ - l32i a1, \tmp2, 0 /* a1 = *tmp2 */ + getcoreid \tmp1 /* tmp1 = Core ID (0 or 1) */ + movi \tmp2, g_cpu_intstack_top /* tmp2 = Array of stack pointers */ + addx4 \tmp2, \tmp1, \tmp2 /* tmp2 = tmp2 + (tmp1 << 2) */ + l32i \tmp1, \tmp2, 0 /* Load the top of the interrupt stack for this core */ + + /* tmp1 represents the top of the interrupt stack for this core + * If a1 >= tmp1, sp is outside the interrupt stack boundaries. + */ + + l32i \tmp2, \tmp2, 0 /* Load the top of the interrupt stack for this core */ + sub \tmp2, a1, \tmp2 + movgez a1, \tmp1, \tmp2 + + /* If a1 < (tmp1 - INTSTACK_SIZE), sp is outside the interrupt stack + * boundaries. + */ + + movi \tmp2, CONFIG_ARCH_INTERRUPTSTACK + sub \tmp2, \tmp1, \tmp2 + sub \tmp2, a1, \tmp2 + movltz a1, \tmp1, \tmp2 + + /* If neither movltz and movgez moved the top of the interrupt stack to + * a1, it means that the stack pointer was already pointing to the + * interrupt stack and no action is required. + */ + .endm #endif diff --git a/arch/xtensa/src/esp32s3/chip_memory.h b/arch/xtensa/src/esp32s3/chip_memory.h index 4df97a4d0c..4c745c1216 100644 --- a/arch/xtensa/src/esp32s3/chip_memory.h +++ b/arch/xtensa/src/esp32s3/chip_memory.h @@ -32,6 +32,12 @@ #include "hardware/esp32s3_soc.h" #endif +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define XTENSA_INSTUCTION_REGION 0x40000000 + /**************************************************************************** * Inline Functions ****************************************************************************/ @@ -51,7 +57,7 @@ extern "C" static inline bool xtensa_sp_sane(uint32_t sp) { - return (esp32s3_sp_dram(sp) && ((sp & 0x0f) == 0)); + return esp32s3_sp_dram(sp); } /**************************************************************************** diff --git a/boards/xtensa/esp32/esp32-wrover-kit/configs/gpio/defconfig b/boards/xtensa/esp32/esp32-wrover-kit/configs/gpio/defconfig index f5fbcae5a2..69fc2e6655 100644 --- a/boards/xtensa/esp32/esp32-wrover-kit/configs/gpio/defconfig +++ b/boards/xtensa/esp32/esp32-wrover-kit/configs/gpio/defconfig @@ -48,4 +48,3 @@ CONFIG_START_YEAR=2011 CONFIG_SYSLOG_BUFFER=y CONFIG_SYSTEM_NSH=y CONFIG_UART0_SERIAL_CONSOLE=y -CONFIG_XTENSA_INTBACKTRACE=y
