From 13b55386bf5c20bd906e79e0e7aee261f6afe0fc Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Sat, 20 Jan 2024 00:21:18 +0400 Subject: [PATCH 1/3] feat(system): esp32p4: support hw stack guard --- components/esp_system/hw_stack_guard.c | 46 +++--- components/esp_system/linker.lf | 2 +- .../esp_system/port/arch/riscv/panic_arch.c | 18 ++- .../private/esp_private/hw_stack_guard.h | 40 ++--- components/esp_system/port/panic_handler.c | 41 +++-- .../hal/esp32c2/include/hal/assist_debug_ll.h | 16 +- .../hal/esp32c3/include/hal/assist_debug_ll.h | 16 +- .../hal/esp32c6/include/hal/assist_debug_ll.h | 16 +- .../hal/esp32h2/include/hal/assist_debug_ll.h | 16 +- .../hal/esp32p4/include/hal/assist_debug_ll.h | 143 ++++++++++++++++++ components/riscv/vectors_clic.S | 10 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + .../esp32p4/include/soc/assist_debug_reg.h | 1 - .../soc/esp32p4/include/soc/periph_defs.h | 1 + components/soc/esp32p4/include/soc/soc.h | 1 + components/soc/esp32p4/include/soc/soc_caps.h | 2 +- 16 files changed, 299 insertions(+), 74 deletions(-) create mode 100644 components/hal/esp32p4/include/hal/assist_debug_ll.h diff --git a/components/esp_system/hw_stack_guard.c b/components/esp_system/hw_stack_guard.c index 3cd73a4d9e..06040d85fa 100644 --- a/components/esp_system/hw_stack_guard.c +++ b/components/esp_system/hw_stack_guard.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,15 +15,20 @@ ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES { uint32_t core_id = esp_cpu_get_core_id(); - if (core_id == 0) { - /* initialize the peripheral only when running on core 0 */ - periph_module_enable(PERIPH_ASSIST_DEBUG_MODULE); - periph_module_reset(PERIPH_ASSIST_DEBUG_MODULE); + ESP_INTR_DISABLE(ETS_ASSIST_DEBUG_INUM); + +#if SOC_CPU_CORES_NUM > 1 + PERIPH_RCC_ATOMIC() +#endif + { + assist_debug_ll_enable_bus_clock(true); + assist_debug_ll_reset_register(); } - /* just in case, disable the interrupt and clear pending status */ - assist_debug_hal_sp_int_disable(core_id); - assist_debug_hal_sp_int_clear(core_id); + /* set interrupt to matrix */ + esp_rom_route_intr_matrix(core_id, ETS_ASSIST_DEBUG_INTR_SOURCE, ETS_ASSIST_DEBUG_INUM); + esprv_int_set_type(ETS_ASSIST_DEBUG_INUM, INTR_TYPE_LEVEL); + esprv_int_set_priority(ETS_ASSIST_DEBUG_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); /* * enable interrupt @@ -37,12 +42,6 @@ ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES */ assist_debug_hal_sp_int_enable(core_id); - /* enable interrup routine */ - esp_rom_route_intr_matrix(core_id, ETS_ASSIST_DEBUG_INTR_SOURCE, ETS_ASSIST_DEBUG_INUM); - - esprv_int_set_type(ETS_ASSIST_DEBUG_INUM, INTR_TYPE_LEVEL); - esprv_int_set_priority(ETS_ASSIST_DEBUG_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); - ESP_INTR_ENABLE(ETS_ASSIST_DEBUG_INUM); return ESP_OK; } @@ -72,23 +71,22 @@ void esp_hw_stack_guard_set_bounds(uint32_t sp_min, uint32_t sp_max) assist_debug_hal_set_sp_bounds(core_id, sp_min, sp_max); } -void esp_hw_stack_guard_get_bounds(uint32_t *sp_min, uint32_t *sp_max) +void esp_hw_stack_guard_get_bounds(uint32_t core_id, uint32_t *sp_min, uint32_t *sp_max) { - uint32_t core_id = esp_cpu_get_core_id(); - assist_debug_hal_get_sp_bounds(core_id, sp_min, sp_max); } -bool esp_hw_stack_guard_is_fired(void) +uint32_t esp_hw_stack_guard_get_fired_cpu(void) { - uint32_t core_id = esp_cpu_get_core_id(); - - return assist_debug_hal_is_sp_ovf_fired(core_id); + for (uint32_t i = 0; i < SOC_CPU_CORES_NUM; i++) { + if (assist_debug_hal_is_sp_ovf_fired(i)) { + return i; + } + } + return ESP_HW_STACK_GUARD_NOT_FIRED; } -uint32_t esp_hw_stack_guard_get_pc(void) +uint32_t esp_hw_stack_guard_get_pc(uint32_t core_id) { - uint32_t core_id = esp_cpu_get_core_id(); - return assist_debug_hal_get_sp_ovf_pc(core_id); } diff --git a/components/esp_system/linker.lf b/components/esp_system/linker.lf index f512f550a9..f3eac77bc0 100644 --- a/components/esp_system/linker.lf +++ b/components/esp_system/linker.lf @@ -9,7 +9,7 @@ entries: reset_reason:esp_reset_reason_get_hint (noflash) if ESP_SYSTEM_HW_STACK_GUARD = y: hw_stack_guard:esp_hw_stack_guard_get_bounds (noflash) - hw_stack_guard:esp_hw_stack_guard_is_fired (noflash) + hw_stack_guard:esp_hw_stack_guard_get_fired_cpu (noflash) hw_stack_guard:esp_hw_stack_guard_get_pc (noflash) esp_err (noflash) diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c index e7c8ee1fce..d2e25b2f01 100644 --- a/components/esp_system/port/arch/riscv/panic_arch.c +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -60,20 +60,21 @@ static inline void print_cache_err_details(const void *frame) #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD static inline void print_assist_debug_details(const void *frame) { - uint32_t core_id = esp_cpu_get_core_id(); + uint32_t core_id = esp_hw_stack_guard_get_fired_cpu(); + if (core_id == ESP_HW_STACK_GUARD_NOT_FIRED) { + panic_print_str("ASSIST_DEBUG is not triggered BUT interrupt occured!\r\n\r\n"); + core_id = 0; + } uint32_t sp_min, sp_max; const char *task_name = pcTaskGetName(xTaskGetCurrentTaskHandleForCore(core_id)); - esp_hw_stack_guard_get_bounds(&sp_min, &sp_max); + esp_hw_stack_guard_get_bounds(core_id, &sp_min, &sp_max); panic_print_str("\r\n"); - if (!esp_hw_stack_guard_is_fired()) { - panic_print_str("ASSIST_DEBUG is not triggered BUT interrupt occured!\r\n\r\n"); - } panic_print_str("Detected in task \""); panic_print_str(task_name); panic_print_str("\" at 0x"); - panic_print_hex((int) esp_hw_stack_guard_get_pc()); + panic_print_hex((int) esp_hw_stack_guard_get_pc(core_id)); panic_print_str("\r\n"); panic_print_str("Stack pointer: 0x"); panic_print_hex((int)((RvExcFrame *)frame)->sp); @@ -250,7 +251,10 @@ void panic_soc_fill_info(void *f, panic_info_t *info) #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD else if (frame->mcause == ETS_ASSIST_DEBUG_INUM) { - info->core = esp_cache_err_get_cpuid(); + info->core = esp_hw_stack_guard_get_fired_cpu(); + if (info->core == ESP_HW_STACK_GUARD_NOT_FIRED) { + info->core = 0; + } info->reason = "Stack protection fault"; info->details = print_assist_debug_details; } diff --git a/components/esp_system/port/include/private/esp_private/hw_stack_guard.h b/components/esp_system/port/include/private/esp_private/hw_stack_guard.h index 3757ae02bc..ed6b64ec7c 100644 --- a/components/esp_system/port/include/private/esp_private/hw_stack_guard.h +++ b/components/esp_system/port/include/private/esp_private/hw_stack_guard.h @@ -14,15 +14,17 @@ extern "C" { #endif +#define ESP_HW_STACK_GUARD_NOT_FIRED UINT32_MAX + /* The functions below are designed to be used in interrupt/panic handler * In case using them in user's code put them into critical section.*/ void esp_hw_stack_guard_monitor_start(void); void esp_hw_stack_guard_monitor_stop(void); void esp_hw_stack_guard_set_bounds(uint32_t sp_min, uint32_t sp_max); -void esp_hw_stack_guard_get_bounds(uint32_t *sp_min, uint32_t *sp_max); -bool esp_hw_stack_guard_is_fired(void); -uint32_t esp_hw_stack_guard_get_pc(void); +void esp_hw_stack_guard_get_bounds(uint32_t core_id, uint32_t *sp_min, uint32_t *sp_max); +uint32_t esp_hw_stack_guard_get_fired_cpu(void); +uint32_t esp_hw_stack_guard_get_pc(uint32_t core_id); #ifdef __cplusplus }; @@ -33,8 +35,9 @@ uint32_t esp_hw_stack_guard_get_pc(void); #include "hal/assist_debug_ll.h" #define ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM (ASSIST_DEBUG_CORE_0_INTR_ENA_REG >> 12) -#define ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_0_SP_MIN_REG - ASSIST_DEBUG_CORE_0_INTR_ENA_REG) -#define ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_0_SP_MAX_REG - ASSIST_DEBUG_CORE_0_INTR_ENA_REG) +#define ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_0_SP_MIN_REG - DR_REG_ASSIST_DEBUG_BASE) +#define ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_0_SP_MAX_REG - DR_REG_ASSIST_DEBUG_BASE) +#define ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET (ASSIST_DEBUG_CORE_0_INTR_ENA_REG - DR_REG_ASSIST_DEBUG_BASE) .macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0 reg1 lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM @@ -44,23 +47,24 @@ sw a1, ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET(\reg1) .macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0 reg1 reg2 lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM -lw \reg2, 0(\reg1) +lw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1) andi \reg2, \reg2, ~ASSIST_DEBUG_SP_SPILL_BITS -sw \reg2, 0(\reg1) +sw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1) .endm .macro ESP_HW_STACK_GUARD_MONITOR_START_CPU0 reg1 reg2 lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM -lw \reg2, 0(\reg1) +lw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1) ori \reg2, \reg2, ASSIST_DEBUG_SP_SPILL_BITS -sw \reg2, 0(\reg1) +sw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1) .endm #if SOC_CPU_CORES_NUM > 1 #define ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM (ASSIST_DEBUG_CORE_1_INTR_ENA_REG >> 12) -#define ASSIST_DEBUG_CORE_1_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_1_SP_MIN_REG - ASSIST_DEBUG_CORE_1_INTR_ENA_REG) -#define ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_1_SP_MAX_REG - ASSIST_DEBUG_CORE_1_INTR_ENA_REG) +#define ASSIST_DEBUG_CORE_1_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_1_SP_MIN_REG - DR_REG_ASSIST_DEBUG_BASE) +#define ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_1_SP_MAX_REG - DR_REG_ASSIST_DEBUG_BASE) +#define ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET (ASSIST_DEBUG_CORE_1_INTR_ENA_REG - DR_REG_ASSIST_DEBUG_BASE) .macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU1 reg1 lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM @@ -70,22 +74,22 @@ sw a1, ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET(\reg1) .macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU1 reg1 reg2 lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM -lw \reg2, 0(\reg1) +lw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1) andi \reg2, \reg2, ~ASSIST_DEBUG_SP_SPILL_BITS -sw \reg2, 0(\reg1) +sw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1) .endm .macro ESP_HW_STACK_GUARD_MONITOR_START_CPU1 reg1 reg2 lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM -lw \reg2, 0(\reg1) +lw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1) ori \reg2, \reg2, ASSIST_DEBUG_SP_SPILL_BITS -sw \reg2, 0(\reg1) +sw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1) .endm .macro ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE reg1 /* Check the current core ID */ csrr \reg1, mhartid -beqz \reg1, @1f +beqz \reg1, 1f /* Core 1 */ ESP_HW_STACK_GUARD_SET_BOUNDS_CPU1 \reg1 j 2f @@ -98,7 +102,7 @@ ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0 \reg1 .macro ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE reg1 reg2 /* Check the current core ID */ csrr \reg1, mhartid -beqz \reg1, @1f +beqz \reg1, 1f /* Core 1 */ ESP_HW_STACK_GUARD_MONITOR_START_CPU1 \reg1 \reg2 j 2f @@ -111,7 +115,7 @@ ESP_HW_STACK_GUARD_MONITOR_START_CPU0 \reg1 \reg2 .macro ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE reg1 reg2 /* Check the current core ID */ csrr \reg1, mhartid -beqz \reg1, @1f +beqz \reg1, 1f /* Core 1 */ ESP_HW_STACK_GUARD_MONITOR_STOP_CPU1 \reg1 \reg2 j 2f diff --git a/components/esp_system/port/panic_handler.c b/components/esp_system/port/panic_handler.c index a8ccce4a8c..6a1af168bd 100644 --- a/components/esp_system/port/panic_handler.c +++ b/components/esp_system/port/panic_handler.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -37,6 +37,10 @@ #include "hal/wdt_types.h" #include "hal/wdt_hal.h" +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD +#include "esp_private/hw_stack_guard.h" +#endif + extern int _invalid_pc_placeholder; extern void esp_panic_handler_reconfigure_wdts(uint32_t timeout_ms); @@ -117,6 +121,14 @@ static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_exc info->frame = frame; } +#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE +FORCE_INLINE_ATTR __attribute__((__noreturn__)) +void busy_wait(void) +{ + while (1) {;} // infinite loop +} +#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE + static void panic_handler(void *frame, bool pseudo_excause) { panic_info_t info = { 0 }; @@ -134,19 +146,24 @@ static void panic_handler(void *frame, bool pseudo_excause) // These are cases where both CPUs both go into panic handler. The following code ensures // only one core proceeds to the system panic handler. if (pseudo_excause) { -#define BUSY_WAIT_IF_TRUE(b) { if (b) while(1); } - // For WDT expiry, pause the non-offending core - offending core handles panic - BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 && core_id == 1); - BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 && core_id == 0); - // For cache error, pause the non-offending core - offending core handles panic - if (panic_get_cause(frame) == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) { - // Only print the backtrace for the offending core in case of the cache error - g_exc_frames[core_id] = NULL; - while (1) { - ; - } + // For WDT expiry, pause the non-offending core - offending core handles panic + if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 && core_id == 1) { + busy_wait(); + } else if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 && core_id == 0) { + busy_wait(); + } else if (panic_get_cause(frame) == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) { + g_exc_frames[core_id] = NULL; // Only print the backtrace for the offending core + busy_wait(); } +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD + else if (panic_get_cause(frame) == ETS_ASSIST_DEBUG_INUM && + esp_hw_stack_guard_get_fired_cpu() != core_id && + esp_hw_stack_guard_get_fired_cpu() != ESP_HW_STACK_GUARD_NOT_FIRED) { + g_exc_frames[core_id] = NULL; // Only print the backtrace for the offending core + busy_wait(); + } +#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD } // Need to reconfigure WDTs before we stall any other CPU diff --git a/components/hal/esp32c2/include/hal/assist_debug_ll.h b/components/hal/esp32c2/include/hal/assist_debug_ll.h index 02c7e4089a..ce98af9292 100644 --- a/components/hal/esp32c2/include/hal/assist_debug_ll.h +++ b/components/hal/esp32c2/include/hal/assist_debug_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "hal/assert.h" +#include "soc/system_struct.h" #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ extern "C" { * interrupt, instead of "ENA". */ - /* These functions are optimazed and designed for internal usage. + /* These functions are optimized and designed for internal usage. * So, the API may differ from general ll layer pattern */ FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id) @@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG); } +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + SYSTEM.cpu_peri_clk_en.clk_en_assist_debug = enable; +} + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + SYSTEM.cpu_peri_rst_en.rst_en_assist_debug = true; + SYSTEM.cpu_peri_rst_en.rst_en_assist_debug = false; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/assist_debug_ll.h b/components/hal/esp32c3/include/hal/assist_debug_ll.h index 02c7e4089a..128b35d903 100644 --- a/components/hal/esp32c3/include/hal/assist_debug_ll.h +++ b/components/hal/esp32c3/include/hal/assist_debug_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "hal/assert.h" +#include "soc/system_struct.h" #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ extern "C" { * interrupt, instead of "ENA". */ - /* These functions are optimazed and designed for internal usage. + /* These functions are optimized and designed for internal usage. * So, the API may differ from general ll layer pattern */ FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id) @@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG); } +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + SYSTEM.cpu_peri_clk_en.reg_clk_en_assist_debug = enable; +} + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + SYSTEM.cpu_peri_rst_en.reg_rst_en_assist_debug = true; + SYSTEM.cpu_peri_rst_en.reg_rst_en_assist_debug = false; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c6/include/hal/assist_debug_ll.h b/components/hal/esp32c6/include/hal/assist_debug_ll.h index 02c7e4089a..2a83bb0c14 100644 --- a/components/hal/esp32c6/include/hal/assist_debug_ll.h +++ b/components/hal/esp32c6/include/hal/assist_debug_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "hal/assert.h" +#include "soc/pcr_struct.h" #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ extern "C" { * interrupt, instead of "ENA". */ - /* These functions are optimazed and designed for internal usage. + /* These functions are optimized and designed for internal usage. * So, the API may differ from general ll layer pattern */ FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id) @@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG); } +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + PCR.assist_conf.assist_clk_en = enable; +} + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + PCR.assist_conf.assist_rst_en = true; + PCR.assist_conf.assist_rst_en = false; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h2/include/hal/assist_debug_ll.h b/components/hal/esp32h2/include/hal/assist_debug_ll.h index 02c7e4089a..2a83bb0c14 100644 --- a/components/hal/esp32h2/include/hal/assist_debug_ll.h +++ b/components/hal/esp32h2/include/hal/assist_debug_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "hal/assert.h" +#include "soc/pcr_struct.h" #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ extern "C" { * interrupt, instead of "ENA". */ - /* These functions are optimazed and designed for internal usage. + /* These functions are optimized and designed for internal usage. * So, the API may differ from general ll layer pattern */ FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id) @@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG); } +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + PCR.assist_conf.assist_clk_en = enable; +} + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + PCR.assist_conf.assist_rst_en = true; + PCR.assist_conf.assist_rst_en = false; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/assist_debug_ll.h b/components/hal/esp32p4/include/hal/assist_debug_ll.h new file mode 100644 index 0000000000..34f6bb6c01 --- /dev/null +++ b/components/hal/esp32p4/include/hal/assist_debug_ll.h @@ -0,0 +1,143 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for DEBUG_ASSIST peripheral + +#pragma once + +#include "soc/assist_debug_reg.h" +#define ASSIST_DEBUG_SP_SPILL_BITS (ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA | ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_ENA) + +#ifndef __ASSEMBLER__ + +#include +#include +#include "esp_attr.h" +#include "hal/assert.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Most other peripherals have 4 interrupt-related registers: INT_ENA_REG, INT_CLR_REG, INT_RAW_REG, INT_ST_REG, the + * meaning of which is well-understood. + * + * Assist_debug peripheral uses a different structure of interrupt registers: + * INT_ENA_REG, INT_RLS_REG, INT_CLR_REG, INT_RAW_REG. + * + * Their behavior can be explained using the following (verilog-like) pseudo-code: + * reg sp_spill_max_st + * assign sp_spill_max = (sp > SP_MAX_REG) + * assign SP_SPILL_MAX_RAW = sp_spill_max & SPILL_MAX_ENA + * always (@posedge clk) begin + * if (reset) then sp_spill_max_st <= 0 + * elif SP_SPILL_MAX_CLR then sp_spill_max_st <= 0 + * else sp_spill_max_st <= SP_SPILL_MAX_RAW & SP_SPILL_MAX_RLS + * end + * // ...same for sp_spill_min and other things dsoc/hp_sys_clkrst_struct.hebug_assist can check. + * + * // this is the final interrupt line coming out of the peripheral: + * assign DEBUG_ASSIST_INT = sp_spill_max_st | sp_spill_min_st | ... + * + * Basically, there is no "ST" register showing the final (latched) interrupt state, and there is an additional + * "RLS" register which just like "ENA" can be used to mask the interrupt. + * Note that writing to CLR clears the (internal) latched interrupt state 'sp_spill_max_st', + * but doesn't affect the software-readable RAW register. + * + * In this code, we use "ENA" to enable monitoring of a particular condition, and "RLS" to enable the interrupt. + * This allows checking whether the condition (e.g. sp > SP_MAX) has occurred by reading the RAW register, without + * actually triggering the interrupt. Hence you will see the somewhat counter-intuitive use of "RLS" to enable the + * interrupt, instead of "ENA". + */ + + /* These functions are optimized and designed for internal usage. + * So, the API may differ from general ll layer pattern */ + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(uint32_t core_id) +{ + REG_SET_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_ENA_REG : ASSIST_DEBUG_CORE_0_INTR_ENA_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_disable(uint32_t core_id) +{ + REG_CLR_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_ENA_REG : ASSIST_DEBUG_CORE_0_INTR_ENA_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_enable(uint32_t core_id) +{ + REG_SET_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_RLS_REG : ASSIST_DEBUG_CORE_0_INTR_RLS_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_disable(uint32_t core_id) +{ + REG_CLR_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_RLS_REG : ASSIST_DEBUG_CORE_0_INTR_RLS_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR bool assist_debug_ll_sp_spill_is_fired(uint32_t core_id) +{ + return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_INTR_RAW_REG : ASSIST_DEBUG_CORE_0_INTR_RAW_REG) & ASSIST_DEBUG_SP_SPILL_BITS; +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_clear(uint32_t core_id) +{ + REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_INTR_CLR_REG : ASSIST_DEBUG_CORE_0_INTR_CLR_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_set_min(uint32_t core_id, uint32_t min) +{ + REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_SP_MIN_REG : ASSIST_DEBUG_CORE_0_SP_MIN_REG, min); +} + +FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_min(uint32_t core_id) +{ + return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_MIN_REG : ASSIST_DEBUG_CORE_0_SP_MIN_REG); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_set_max(uint32_t core_id, uint32_t max) +{ + REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_SP_MAX_REG : ASSIST_DEBUG_CORE_0_SP_MAX_REG, max); +} + +FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_max(uint32_t core_id) +{ + return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_MAX_REG : ASSIST_DEBUG_CORE_0_SP_MAX_REG); +} + +FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(uint32_t core_id) +{ + return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_PC_REG : ASSIST_DEBUG_CORE_0_SP_PC_REG); +} + +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + HP_SYS_CLKRST.soc_clk_ctrl0.reg_busmon_cpu_clk_en = enable; +} +#define assist_debug_ll_enable_bus_clock(...) \ + (void)__DECLARE_RCC_ATOMIC_ENV; assist_debug_ll_enable_bus_clock(__VA_ARGS__) + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + /* esp32p4 has no assist_debug reset register: disable & clear interrupts manually. */ + for (int i = 0; i < CONFIG_SOC_CPU_CORES_NUM; i++) { + assist_debug_ll_sp_spill_monitor_disable(i); + assist_debug_ll_sp_spill_interrupt_clear(i); + assist_debug_ll_sp_spill_set_min(i, 0); + assist_debug_ll_sp_spill_set_max(i, 0xffffffff); + /* Enable PC register storing when trigger stack monitor. */ + REG_WRITE(i ? ASSIST_DEBUG_CORE_1_RCD_EN_REG : ASSIST_DEBUG_CORE_0_RCD_EN_REG, ASSIST_DEBUG_CORE_1_RCD_PDEBUGEN | ASSIST_DEBUG_CORE_1_RCD_RECORDEN); + } +} +#define assist_debug_ll_reset_register(...) \ + (void)__DECLARE_RCC_ATOMIC_ENV; assist_debug_ll_reset_register(__VA_ARGS__) + +#ifdef __cplusplus +} +#endif + +#endif // __ASSEMBLER__ diff --git a/components/riscv/vectors_clic.S b/components/riscv/vectors_clic.S index e1b2ad0e35..543c868762 100644 --- a/components/riscv/vectors_clic.S +++ b/components/riscv/vectors_clic.S @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,12 @@ #define MEMPROT_ISR _interrupt_handler #endif // CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD + #define ASTDBG_ISR _panic_handler +#else + #define ASTDBG_ISR _interrupt_handler +#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD + #if CONFIG_ESP_IPC_ISR_ENABLE #define IPC_ISR_HANDLER esp_ipc_isr_handler #else @@ -109,7 +115,7 @@ _mtvt_table: .word _panic_handler /* 40: ETS_INT_WDT_INUM (+16) panic-interrupt (soc-level panic) */ .word _panic_handler /* 41: ETS_CACHEERR_INUM (+16) panic-interrupt (soc-level panic) */ .word MEMPROT_ISR /* 42: ETS_MEMPROT_ERR_INUM (+16) handler (soc-level panic) */ - .word _interrupt_handler /* 43: Free interrupt number */ + .word ASTDBG_ISR /* 43: ETS_ASSIST_DEBUG_INUM (+16) handler (soc-level panic) */ .word IPC_ISR_HANDLER /* 44: ETS_IPC_ISR_INUM (+16) handler*/ .word _interrupt_handler /* 45: Free interrupt number */ .word _interrupt_handler /* 46: Free interrupt number */ diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 4da0a19281..06f6053582 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -211,6 +211,10 @@ config SOC_CLK_TREE_SUPPORTED bool default y +config SOC_ASSIST_DEBUG_SUPPORTED + bool + default y + config SOC_WDT_SUPPORTED bool default y diff --git a/components/soc/esp32p4/include/soc/assist_debug_reg.h b/components/soc/esp32p4/include/soc/assist_debug_reg.h index 6eda629f77..89c49a9cc6 100644 --- a/components/soc/esp32p4/include/soc/assist_debug_reg.h +++ b/components/soc/esp32p4/include/soc/assist_debug_reg.h @@ -5,7 +5,6 @@ */ #pragma once -#include #include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32p4/include/soc/periph_defs.h b/components/soc/esp32p4/include/soc/periph_defs.h index 8be5b45219..cadf54fdf7 100644 --- a/components/soc/esp32p4/include/soc/periph_defs.h +++ b/components/soc/esp32p4/include/soc/periph_defs.h @@ -68,6 +68,7 @@ typedef enum { PERIPH_AXI_PDMA_MODULE, PERIPH_UHCI_MODULE, PERIPH_PCNT_MODULE, + PERIPH_ASSIST_DEBUG_MODULE, /* LP peripherals */ PERIPH_LP_I2C0_MODULE, PERIPH_LP_UART0_MODULE, diff --git a/components/soc/esp32p4/include/soc/soc.h b/components/soc/esp32p4/include/soc/soc.h index 3f729140fe..a6653173c9 100644 --- a/components/soc/esp32p4/include/soc/soc.h +++ b/components/soc/esp32p4/include/soc/soc.h @@ -231,6 +231,7 @@ #define ETS_T1_WDT_INUM 24 #define ETS_CACHEERR_INUM 25 #define ETS_MEMPROT_ERR_INUM 26 +#define ETS_ASSIST_DEBUG_INUM 27 // Note: this interrupt can be combined with others (e.g., CACHEERR), as we can identify its trigger is activated #define ETS_IPC_ISR_INUM 28 //CPU0 Max valid interrupt number #define ETS_MAX_INUM 31 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index fce0f67512..1f79bbc93f 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -80,7 +80,7 @@ // #define SOC_ULP_SUPPORTED 1 //TODO: IDF-7534 #define SOC_SDMMC_HOST_SUPPORTED 1 #define SOC_CLK_TREE_SUPPORTED 1 -// #define SOC_ASSIST_DEBUG_SUPPORTED 1 //TODO: IDF-7565 +#define SOC_ASSIST_DEBUG_SUPPORTED 1 #define SOC_WDT_SUPPORTED 1 #define SOC_SPI_FLASH_SUPPORTED 1 // #define SOC_TOUCH_SENSOR_SUPPORTED 1 //TODO: IDF-7477 From cb82161dae72821b0cd19f9ba50b0692abfcbeb0 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Fri, 19 Jan 2024 11:51:57 +0400 Subject: [PATCH 2/3] feat(system): esp32p4: support panic tests --- tools/test_apps/.build-test-rules.yml | 6 +- .../system/build_test/sdkconfig.ci.no_hwsg | 1 + tools/test_apps/system/panic/README.md | 4 +- .../system/panic/main/include/test_panic.h | 5 ++ .../system/panic/main/test_app_main.c | 25 +++++-- .../test_apps/system/panic/main/test_panic.c | 14 ++++ tools/test_apps/system/panic/pytest_panic.py | 66 +++++++++++++++---- .../system/panic/test_panic_util/panic_dut.py | 17 +++-- 8 files changed, 107 insertions(+), 31 deletions(-) create mode 100644 tools/test_apps/system/build_test/sdkconfig.ci.no_hwsg diff --git a/tools/test_apps/.build-test-rules.yml b/tools/test_apps/.build-test-rules.yml index 70dfa01002..58c9378d86 100644 --- a/tools/test_apps/.build-test-rules.yml +++ b/tools/test_apps/.build-test-rules.yml @@ -208,10 +208,8 @@ tools/test_apps/system/no_embedded_paths: reason: the other targets are not tested yet tools/test_apps/system/panic: - disable: - - if: IDF_TARGET in ["esp32p4"] - temporary: true - reason: target(s) not supported yet # TODO: IDF-7511 + enable: + - if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["esp32p4"] # preview targets tools/test_apps/system/ram_loadable_app: disable_test: diff --git a/tools/test_apps/system/build_test/sdkconfig.ci.no_hwsg b/tools/test_apps/system/build_test/sdkconfig.ci.no_hwsg new file mode 100644 index 0000000000..eb3631ffbe --- /dev/null +++ b/tools/test_apps/system/build_test/sdkconfig.ci.no_hwsg @@ -0,0 +1 @@ +CONFIG_ESP_SYSTEM_HW_STACK_GUARD=n diff --git a/tools/test_apps/system/panic/README.md b/tools/test_apps/system/panic/README.md index 87ef04a8a6..fae6b93717 100644 --- a/tools/test_apps/system/panic/README.md +++ b/tools/test_apps/system/panic/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | # Introduction diff --git a/tools/test_apps/system/panic/main/include/test_panic.h b/tools/test_apps/system/panic/main/include/test_panic.h index 68715152c9..09ba97fc88 100644 --- a/tools/test_apps/system/panic/main/include/test_panic.h +++ b/tools/test_apps/system/panic/main/include/test_panic.h @@ -24,7 +24,12 @@ void test_int_wdt(void); void test_task_wdt_cpu0(void); +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD void test_hw_stack_guard_cpu0(void); +#if !CONFIG_FREERTOS_UNICORE +void test_hw_stack_guard_cpu1(void); +#endif // CONFIG_FREERTOS_UNICORE +#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY void test_panic_extram_stack(void); diff --git a/tools/test_apps/system/panic/main/test_app_main.c b/tools/test_apps/system/panic/main/test_app_main.c index aecd9f0836..98be5a7d70 100644 --- a/tools/test_apps/system/panic/main/test_app_main.c +++ b/tools/test_apps/system/panic/main/test_app_main.c @@ -31,9 +31,7 @@ static const char* get_test_name(void) { static char test_name_str[BOOT_CMD_MAX_LEN] = {0}; - - printf("Enter test name: "); - fflush(stdout); + bool print_prompt = true; /* Not using blocking fgets(stdin) here, as QEMU doesn't yet implement RX timeout interrupt, * which is required for the UART driver and blocking stdio to work. @@ -42,16 +40,24 @@ static const char* get_test_name(void) char *p = test_name_str; const char *end = test_name_str + sizeof(test_name_str) - 1; while (p < end) { + if (print_prompt) { + printf("Enter test name: "); + fflush(stdout); + print_prompt = false; + } c = getchar(); if (c == EOF) { vTaskDelay(pdMS_TO_TICKS(10)); - } else if ((c == '\r' || c == '\n') && p != test_name_str) { + } else if (c == '\r' || c == '\n') { /* terminate the line */ puts("\n\r"); fflush(stdout); - *p = '\0'; - break; - } else { + print_prompt = true; + if (p != test_name_str) { + *p = '\0'; + break; + } + } else if (c >= '0' && c <= 'z') { /* echo the received character */ putchar(c); fflush(stdout); @@ -83,7 +89,12 @@ void app_main(void) HANDLE_TEST(test_name, test_abort_cache_disabled); HANDLE_TEST(test_name, test_int_wdt); HANDLE_TEST(test_name, test_task_wdt_cpu0); +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD HANDLE_TEST(test_name, test_hw_stack_guard_cpu0); +#if !CONFIG_FREERTOS_UNICORE + HANDLE_TEST(test_name, test_hw_stack_guard_cpu1); +#endif // CONFIG_FREERTOS_UNICORE +#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY HANDLE_TEST(test_name, test_panic_extram_stack); #endif diff --git a/tools/test_apps/system/panic/main/test_panic.c b/tools/test_apps/system/panic/main/test_panic.c index adb9b3eff3..158bc3cf58 100644 --- a/tools/test_apps/system/panic/main/test_panic.c +++ b/tools/test_apps/system/panic/main/test_panic.c @@ -63,6 +63,8 @@ void test_task_wdt_cpu0(void) } } +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD + __attribute__((optimize("-O0"))) static void test_hw_stack_guard_cpu(void* arg) { @@ -78,6 +80,18 @@ void test_hw_stack_guard_cpu0(void) } } +#if !CONFIG_FREERTOS_UNICORE +void test_hw_stack_guard_cpu1(void) +{ + xTaskCreatePinnedToCore(test_hw_stack_guard_cpu, "HWSG1", 512, NULL, 1, NULL, 1); + while (true) { + vTaskDelay(100); + } +} + +#endif // CONFIG_FREERTOS_UNICORE +#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD + #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY static void stack_in_extram(void* arg) { diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index 08da655338..5017640194 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -17,7 +17,8 @@ TARGETS_TESTED = [ pytest.mark.esp32s3, pytest.mark.esp32c2, pytest.mark.esp32c6, - pytest.mark.esp32h2 + pytest.mark.esp32h2, + pytest.mark.esp32p4, ] # Most tests run on all targets and with all configs. @@ -34,7 +35,11 @@ CONFIGS = [ ] # Some tests only run on dual-core targets, they use the config below. -TARGETS_DUAL_CORE = [pytest.mark.esp32, pytest.mark.esp32s3] +TARGETS_DUAL_CORE = [ + pytest.mark.esp32, + pytest.mark.esp32s3, + pytest.mark.esp32p4, +] CONFIGS_DUAL_CORE = [ pytest.param('coredump_flash_bin_crc', marks=TARGETS_DUAL_CORE), pytest.param('coredump_flash_elf_sha', marks=TARGETS_DUAL_CORE), @@ -58,6 +63,7 @@ TARGETS_HW_STACK_GUARD = [ pytest.mark.esp32c3, pytest.mark.esp32c6, pytest.mark.esp32h2, + pytest.mark.esp32p4, ] CONFIGS_HW_STACK_GUARD = [ @@ -68,6 +74,14 @@ CONFIGS_HW_STACK_GUARD = [ pytest.param('panic', marks=TARGETS_HW_STACK_GUARD), ] +CONFIGS_HW_STACK_GUARD_DUAL_CORE = [ + pytest.param('coredump_flash_bin_crc', marks=[pytest.mark.esp32p4]), + pytest.param('coredump_uart_bin_crc', marks=[pytest.mark.esp32p4]), + pytest.param('coredump_uart_elf_crc', marks=[pytest.mark.esp32p4]), + pytest.param('gdbstub', marks=[pytest.mark.esp32p4]), + pytest.param('panic', marks=[pytest.mark.esp32p4]), +] + # Panic abort information will start with this string. PANIC_ABORT_PREFIX = 'Panic reason: ' @@ -148,15 +162,16 @@ def test_task_wdt_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> N 'Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:' ) dut.expect_exact('CPU 1: Infinite loop') + expected_backtrace = ['infinite_loop', 'vPortTaskWrapper'] if dut.is_xtensa: # see comment in test_task_wdt_cpu0 dut.expect_none('register dump:') dut.expect_exact('Print CPU 1 backtrace') dut.expect_backtrace() - # On Xtensa, we get incorrect backtrace from GDB in this test - expected_backtrace = ['infinite_loop', 'vPortTaskWrapper'] else: - assert False, 'No dual-core RISC-V chips yet, check this test case later' + # on RISC-V, need to dump both registers and stack memory to reconstruct the backtrace + dut.expect_reg_dump(core=1) + dut.expect_stack_dump() dut.expect_elf_sha256() dut.expect_none('Guru Meditation') @@ -204,9 +219,9 @@ def test_int_wdt( dut.expect_stack_dump() if target in TARGETS_DUAL_CORE_NAMES: - assert dut.is_xtensa, 'No dual-core RISC-V chips yet, check the test case' dut.expect_reg_dump(1) - dut.expect_backtrace() + if dut.is_xtensa: + dut.expect_backtrace() dut.expect_elf_sha256() dut.expect_none('Guru Meditation') @@ -228,9 +243,9 @@ def test_int_wdt_cache_disabled( dut.expect_stack_dump() if target in TARGETS_DUAL_CORE_NAMES: - assert dut.is_xtensa, 'No dual-core RISC-V chips yet, check the test case' dut.expect_reg_dump(1) - dut.expect_backtrace() + if dut.is_xtensa: + dut.expect_backtrace() dut.expect_elf_sha256() dut.expect_none('Guru Meditation') @@ -251,6 +266,8 @@ def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> Non elif dut.target in ['esp32s2']: # Cache error interrupt is not enabled, IDF-1558 dut.expect_gme('IllegalInstruction') + elif dut.target in ['esp32p4']: # TODO IDF-7515 + dut.expect_gme('Instruction access fault') else: dut.expect_gme('Cache disabled but cached memory region accessed') dut.expect_reg_dump(0) @@ -832,15 +849,36 @@ def test_gdbstub_coredump(dut: PanicTestDut) -> None: return # don't expect "Rebooting" output below +def test_hw_stack_guard_cpu(dut: PanicTestDut, cpu: int) -> None: + dut.expect_exact(f'Guru Meditation Error: Core {cpu} panic\'ed (Stack protection fault).') + dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occured!') + dut.expect_exact(f'Detected in task "HWSG{cpu}"') + addr = dut.expect('at 0x([0-9a-fA-F]{8})') + assert addr.group(1) != b'00000000' + addr = dut.expect('Stack pointer: 0x([0-9a-fA-F]{8})') + assert addr.group(1) != b'00000000' + addr = dut.expect(r'Stack bounds: 0x([0-9a-fA-F]{8})') + assert addr.group(1) != b'00000000' + start_addr = int(addr.group(1), 16) + addr = dut.expect(r' - 0x([0-9a-fA-F]{8})') + assert addr.group(1) != b'00000000' + end_addr = int(addr.group(1), 16) + assert end_addr > start_addr + + @pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD, indirect=True) @pytest.mark.generic def test_hw_stack_guard_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) - dut.expect_exact('Guru Meditation Error: Core 0 panic\'ed (Stack protection fault).') - dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occured!') - dut.expect(r'Detected in task(.*)at 0x') - dut.expect_exact('Stack pointer: 0x') - dut.expect(r'Stack bounds: 0x(.*) - 0x') + test_hw_stack_guard_cpu(dut, 0) + common_test(dut, config) + + +@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD_DUAL_CORE, indirect=True) +@pytest.mark.generic +def test_hw_stack_guard_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> None: + dut.run_test_func(test_func_name) + test_hw_stack_guard_cpu(dut, 1) common_test(dut, config) diff --git a/tools/test_apps/system/panic/test_panic_util/panic_dut.py b/tools/test_apps/system/panic/test_panic_util/panic_dut.py index 61a5d134b0..8600754c67 100644 --- a/tools/test_apps/system/panic/test_panic_util/panic_dut.py +++ b/tools/test_apps/system/panic/test_panic_util/panic_dut.py @@ -1,14 +1,23 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import logging import os import re import subprocess import sys -from typing import Any, Dict, List, Optional, TextIO, Union +from typing import Any +from typing import Dict +from typing import List +from typing import Optional +from typing import TextIO +from typing import Union import pexpect -from panic_utils import NoGdbProcessError, attach_logger, quote_string, sha256, verify_valid_gdb_subprocess +from panic_utils import attach_logger +from panic_utils import NoGdbProcessError +from panic_utils import quote_string +from panic_utils import sha256 +from panic_utils import verify_valid_gdb_subprocess from pygdbmi.gdbcontroller import GdbController from pytest_embedded_idf.app import IdfApp from pytest_embedded_idf.dut import IdfDut @@ -53,7 +62,7 @@ class PanicTestDut(IdfDut): @property def is_multi_core(self) -> bool: - return self.target in ['esp32', 'esp32s3'] + return self.target in ['esp32', 'esp32s3', 'esp32p4'] def run_test_func(self, test_func_name: str) -> None: self.expect_exact('Enter test name:') From e845d9e0eb0d705a01936d3de94d12b2991dcce7 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Thu, 21 Mar 2024 12:16:43 +0400 Subject: [PATCH 3/3] feat(esp_system): allow .data to spill over into L2MEM above 0x4ff40000 It may be usefull when .rodata placed into .dram1.data --- components/esp_system/ld/esp32p4/sections.ld.in | 13 +++++++++++-- components/heap/port/esp32p4/memory_layout.c | 6 +++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/components/esp_system/ld/esp32p4/sections.ld.in b/components/esp_system/ld/esp32p4/sections.ld.in index 318b068875..8a1c5fc5f2 100644 --- a/components/esp_system/ld/esp32p4/sections.ld.in +++ b/components/esp_system/ld/esp32p4/sections.ld.in @@ -217,7 +217,7 @@ SECTIONS .dram0.data : { - _data_start = ABSOLUTE(.); + _data_start_low = ABSOLUTE(.); *(.gnu.linkonce.d.*) *(.data1) __global_pointer$ = . + 0x800; @@ -230,9 +230,18 @@ SECTIONS arrays[dram0_data] mapping[dram0_data] - _data_end = ABSOLUTE(.); + _data_end_low = ABSOLUTE(.); } > sram_low + .dram1.data : + { + _data_start_high = ABSOLUTE(.); + + mapping[dram0_data] + + _data_end_high = ABSOLUTE(.); + } > sram_high + /** * This section holds data that should not be initialized at power up. * The section located in Internal SRAM memory region. The macro _NOINIT diff --git a/components/heap/port/esp32p4/memory_layout.c b/components/heap/port/esp32p4/memory_layout.c index 04e5a9dfe6..9b5135f814 100644 --- a/components/heap/port/esp32p4/memory_layout.c +++ b/components/heap/port/esp32p4/memory_layout.c @@ -89,7 +89,7 @@ const soc_memory_region_t soc_memory_regions[] = { const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_memory_region_t); -extern int _data_start, _bss_start_high, _heap_start_low, _heap_start_high, _iram_start, _iram_end, _rtc_force_slow_end; +extern int _data_start_low, _data_start_high, _heap_start_low, _heap_start_high, _iram_start, _iram_end, _rtc_force_slow_end; extern int _tcm_text_start, _tcm_data_end; extern int _rtc_reserved_start, _rtc_reserved_end; @@ -100,8 +100,8 @@ extern int _rtc_reserved_start, _rtc_reserved_end; */ // Static data region. DRAM used by data+bss and possibly rodata -SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start_low, dram_data_low); -SOC_RESERVE_MEMORY_REGION((intptr_t)&_bss_start_high, (intptr_t)&_heap_start_high, dram_data_high); +SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start_low, (intptr_t)&_heap_start_low, dram_data_low); +SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start_high, (intptr_t)&_heap_start_high, dram_data_high); // Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code);