mirror of
https://github.com/apache/nuttx.git
synced 2026-05-29 04:19:37 +08:00
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;
This commit is contained in:
committed by
Xiang Xiao
parent
d6ee1742a9
commit
cdeb720bf8
@@ -136,7 +136,7 @@ endif
|
|||||||
|
|
||||||
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
|
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
|
||||||
ifndef ESP_HAL_3RDPARTY_VERSION
|
ifndef ESP_HAL_3RDPARTY_VERSION
|
||||||
ESP_HAL_3RDPARTY_VERSION = 20690e67695f0a8170a19ec99e2e9a13b620e94d
|
ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef ESP_HAL_3RDPARTY_URL
|
ifndef ESP_HAL_3RDPARTY_URL
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ noinstrument_function static inline void xtensa_setps(uint32_t ps)
|
|||||||
|
|
||||||
/* Return the current value of the stack pointer */
|
/* 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;
|
register uint32_t sp;
|
||||||
|
|
||||||
|
|||||||
@@ -30,14 +30,29 @@
|
|||||||
|
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
#include "xtensa.h"
|
#include "xtensa.h"
|
||||||
|
#include "chip.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* 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 */
|
/* 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
|
* Private Types
|
||||||
@@ -173,17 +188,21 @@ static int backtrace_stack(uintptr_t *base, uintptr_t *limit,
|
|||||||
|
|
||||||
while (i < size)
|
while (i < size)
|
||||||
{
|
{
|
||||||
ra = (uintptr_t *)*(sp - 4);
|
ra = MAKE_PC_FROM_RA((uintptr_t)(*(sp - 4)));
|
||||||
sp = (uintptr_t *)*(sp - 3);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*skip)-- <= 0)
|
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,
|
(void *)up_getsp(), NULL,
|
||||||
buffer, size, &skip);
|
buffer, size, &skip);
|
||||||
#else
|
#else
|
||||||
|
xtensa_window_spill();
|
||||||
ret = backtrace_stack(rtcb->stack_base_ptr,
|
ret = backtrace_stack(rtcb->stack_base_ptr,
|
||||||
rtcb->stack_base_ptr + rtcb->adj_stack_size,
|
rtcb->stack_base_ptr + rtcb->adj_stack_size,
|
||||||
(void *)up_getsp(), NULL,
|
(void *)up_getsp(), NULL,
|
||||||
|
|||||||
@@ -42,9 +42,32 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
|
#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||||
.macro setintstack tmp1 tmp2
|
.macro setintstack tmp1 tmp2
|
||||||
movi a1, g_intstacktop
|
|
||||||
.endm
|
/* 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
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ endif
|
|||||||
|
|
||||||
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
|
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
|
||||||
ifndef ESP_HAL_3RDPARTY_VERSION
|
ifndef ESP_HAL_3RDPARTY_VERSION
|
||||||
ESP_HAL_3RDPARTY_VERSION = 20690e67695f0a8170a19ec99e2e9a13b620e94d
|
ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef ESP_HAL_3RDPARTY_URL
|
ifndef ESP_HAL_3RDPARTY_URL
|
||||||
@@ -246,7 +246,7 @@ chip/$(ESP_HAL_3RDPARTY_REPO):
|
|||||||
|
|
||||||
# Silent preprocessor warnings
|
# 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
|
# Enable strict volatile bitfield access
|
||||||
|
|
||||||
|
|||||||
@@ -120,10 +120,33 @@
|
|||||||
|
|
||||||
#if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
|
#if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||||
.macro setintstack tmp1 tmp2
|
.macro setintstack tmp1 tmp2
|
||||||
getcoreid \tmp1 /* tmp1 = Core ID (0 or 1) */
|
getcoreid \tmp1 /* tmp1 = Core ID (0 or 1) */
|
||||||
movi \tmp2, g_cpu_intstack_top /* tmp2 = Array of stack pointers */
|
movi \tmp2, g_cpu_intstack_top /* tmp2 = Array of stack pointers */
|
||||||
addx4 \tmp2, \tmp1, \tmp2 /* tmp2 = tmp2 + (tmp1 << 2) */
|
addx4 \tmp2, \tmp1, \tmp2 /* tmp2 = tmp2 + (tmp1 << 2) */
|
||||||
l32i a1, \tmp2, 0 /* a1 = *tmp2 */
|
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
|
.endm
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,12 @@
|
|||||||
#include "hardware/esp32_soc.h"
|
#include "hardware/esp32_soc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define XTENSA_INSTUCTION_REGION 0x40000000
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Inline Functions
|
* Inline Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -48,7 +54,7 @@ extern "C"
|
|||||||
|
|
||||||
static inline bool xtensa_sp_sane(uint32_t sp)
|
static inline bool xtensa_sp_sane(uint32_t sp)
|
||||||
{
|
{
|
||||||
return (esp32_sp_dram(sp) && ((sp & 0x0f) == 0));
|
return esp32_sp_dram(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ endif
|
|||||||
|
|
||||||
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
|
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
|
||||||
ifndef ESP_HAL_3RDPARTY_VERSION
|
ifndef ESP_HAL_3RDPARTY_VERSION
|
||||||
ESP_HAL_3RDPARTY_VERSION = 20690e67695f0a8170a19ec99e2e9a13b620e94d
|
ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef ESP_HAL_3RDPARTY_URL
|
ifndef ESP_HAL_3RDPARTY_URL
|
||||||
@@ -171,7 +171,7 @@ chip/$(ESP_HAL_3RDPARTY_REPO):
|
|||||||
|
|
||||||
# Silent preprocessor warnings
|
# 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
|
# Enable strict volatile bitfield access
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,12 @@
|
|||||||
#include "hardware/esp32s2_soc.h"
|
#include "hardware/esp32s2_soc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define XTENSA_INSTUCTION_REGION 0x40000000
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Inline Functions
|
* Inline Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -48,7 +54,7 @@ extern "C"
|
|||||||
|
|
||||||
static inline bool xtensa_sp_sane(uint32_t sp)
|
static inline bool xtensa_sp_sane(uint32_t sp)
|
||||||
{
|
{
|
||||||
return (esp32s2_sp_dram(sp) && ((sp & 0x0f) == 0));
|
return esp32s2_sp_dram(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ endif
|
|||||||
|
|
||||||
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
|
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
|
||||||
ifndef ESP_HAL_3RDPARTY_VERSION
|
ifndef ESP_HAL_3RDPARTY_VERSION
|
||||||
ESP_HAL_3RDPARTY_VERSION = 20690e67695f0a8170a19ec99e2e9a13b620e94d
|
ESP_HAL_3RDPARTY_VERSION = b4c723a119344b4b71d69819019d55637fb570fd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef ESP_HAL_3RDPARTY_URL
|
ifndef ESP_HAL_3RDPARTY_URL
|
||||||
@@ -244,7 +244,7 @@ chip/$(ESP_HAL_3RDPARTY_REPO):
|
|||||||
|
|
||||||
# Silent preprocessor warnings
|
# 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
|
CFLAGS += ${DEFINE_PREFIX}_RETARGETABLE_LOCKING
|
||||||
|
|
||||||
# Enable strict volatile bitfield access
|
# Enable strict volatile bitfield access
|
||||||
|
|||||||
@@ -104,10 +104,33 @@
|
|||||||
|
|
||||||
#if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
|
#if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||||
.macro setintstack tmp1 tmp2
|
.macro setintstack tmp1 tmp2
|
||||||
getcoreid \tmp1 /* tmp1 = Core ID (0 or 1) */
|
getcoreid \tmp1 /* tmp1 = Core ID (0 or 1) */
|
||||||
movi \tmp2, g_cpu_intstack_top /* tmp2 = Array of stack pointers */
|
movi \tmp2, g_cpu_intstack_top /* tmp2 = Array of stack pointers */
|
||||||
addx4 \tmp2, \tmp1, \tmp2 /* tmp2 = tmp2 + (tmp1 << 2) */
|
addx4 \tmp2, \tmp1, \tmp2 /* tmp2 = tmp2 + (tmp1 << 2) */
|
||||||
l32i a1, \tmp2, 0 /* a1 = *tmp2 */
|
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
|
.endm
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,12 @@
|
|||||||
#include "hardware/esp32s3_soc.h"
|
#include "hardware/esp32s3_soc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define XTENSA_INSTUCTION_REGION 0x40000000
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Inline Functions
|
* Inline Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -51,7 +57,7 @@ extern "C"
|
|||||||
|
|
||||||
static inline bool xtensa_sp_sane(uint32_t sp)
|
static inline bool xtensa_sp_sane(uint32_t sp)
|
||||||
{
|
{
|
||||||
return (esp32s3_sp_dram(sp) && ((sp & 0x0f) == 0));
|
return esp32s3_sp_dram(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -48,4 +48,3 @@ CONFIG_START_YEAR=2011
|
|||||||
CONFIG_SYSLOG_BUFFER=y
|
CONFIG_SYSLOG_BUFFER=y
|
||||||
CONFIG_SYSTEM_NSH=y
|
CONFIG_SYSTEM_NSH=y
|
||||||
CONFIG_UART0_SERIAL_CONSOLE=y
|
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||||
CONFIG_XTENSA_INTBACKTRACE=y
|
|
||||||
|
|||||||
Reference in New Issue
Block a user