From c57443c2b644761e4f8aee60db6cc7bba5b5799d Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Tue, 13 Jan 2026 11:26:30 +0700 Subject: [PATCH] fix(gdbstub): xtensa: fix FPU registers read and write Closes https://github.com/espressif/esp-idf/issues/17944 --- .../private_include/esp_gdbstub_common.h | 9 +- components/esp_gdbstub/src/gdbstub.c | 21 +- .../src/port/riscv/gdbstub_riscv.c | 23 +- .../src/port/xtensa/gdbstub_xtensa.c | 350 ++++++++++-------- .../port/xtensa/include/esp_gdbstub_arch.h | 28 +- .../esp32/include/xtensa/config/tie-asm.h | 72 ++-- .../esp32s3/include/xtensa/config/tie-asm.h | 72 ++-- .../gdbstub_runtime/main/CMakeLists.txt | 10 +- .../system/gdbstub_runtime/main/coproc_regs.c | 42 ++- .../gdbstub_runtime/main/test_app_main.c | 2 +- .../gdbstub_runtime/pytest_gdbstub_runtime.py | 73 ++-- 11 files changed, 408 insertions(+), 294 deletions(-) diff --git a/components/esp_gdbstub/private_include/esp_gdbstub_common.h b/components/esp_gdbstub/private_include/esp_gdbstub_common.h index a16857118a..04abcf9b97 100644 --- a/components/esp_gdbstub/private_include/esp_gdbstub_common.h +++ b/components/esp_gdbstub/private_include/esp_gdbstub_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -91,6 +91,13 @@ void gdbstub_handle_uart_int(esp_gdbstub_frame_t *regs_frame); * @param dst pointer to the GDB register file */ void esp_gdbstub_tcb_to_regfile(TaskHandle_t tcb, esp_gdbstub_gdb_regfile_t *dst); + +/** + * Find the TCB that owns the given exception frame + * @param frame pointer to the exception frame + * @return pointer to the TCB, or NULL if not found + */ +const StaticTask_t *esp_gdbstub_find_tcb_by_frame(const esp_gdbstub_frame_t *frame); #endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS diff --git a/components/esp_gdbstub/src/gdbstub.c b/components/esp_gdbstub/src/gdbstub.c index 9cb9dfeb78..0f5b65454f 100644 --- a/components/esp_gdbstub/src/gdbstub.c +++ b/components/esp_gdbstub/src/gdbstub.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -381,6 +381,25 @@ void esp_gdbstub_init(void) #ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +const StaticTask_t *esp_gdbstub_find_tcb_by_frame(const esp_gdbstub_frame_t *frame) +{ + /* + * Determine which task owns the current frame. + * Perform a search across all tasks, as GDBstub may not include task information + * if configured with ESP_GDBSTUB_SUPPORT_TASKS disabled. + */ + TaskIterator_t xTaskIter = {0}; /* Point to the first task list */ + + while (xTaskGetNext(&xTaskIter) != -1) { + StaticTask_t *tcb = (StaticTask_t *)xTaskIter.pxTaskHandle; + if (tcb->pxDummy1 /* pxTopOfStack */ == frame) { + return tcb; + } + } + + return NULL; /* Task not found. */ +} + /** Send string as a het to uart */ static void esp_gdbstub_send_str_as_hex(const char *str) { diff --git a/components/esp_gdbstub/src/port/riscv/gdbstub_riscv.c b/components/esp_gdbstub/src/port/riscv/gdbstub_riscv.c index 4880efa709..0c7c5e4284 100644 --- a/components/esp_gdbstub/src/port/riscv/gdbstub_riscv.c +++ b/components/esp_gdbstub/src/port/riscv/gdbstub_riscv.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -100,27 +100,6 @@ static void esp_gdbstub_pie_regs_to_regfile (esp_gdbstub_gdb_regfile_t *dst) #endif #if SOC_CPU_HAS_FPU || SOC_CPU_HAS_PIE -const StaticTask_t *esp_gdbstub_find_tcb_by_frame(const esp_gdbstub_frame_t *frame) -{ - /* - * Determine which task owns the current frame. - * Perform a search across all tasks, as GDBstub may not include task information - * if configured with ESP_GDBSTUB_SUPPORT_TASKS disabled. - */ - - TaskIterator_t xTaskIter = {0}; /* Point to the first task list */ - - while(xTaskGetNext(&xTaskIter) != -1) - { - StaticTask_t *tcb = (StaticTask_t *)xTaskIter.pxTaskHandle; - if (tcb->pxDummy1 /* pxTopOfStack */ == frame) { - return tcb; - } - } - - return NULL; /* Task not found. */ -} - static void *esp_gdbstub_coproc_saved_area(const StaticTask_t *tcb, int coproc, bool is_read) { /* * Coprocessors have lazy register saving mechanism: diff --git a/components/esp_gdbstub/src/port/xtensa/gdbstub_xtensa.c b/components/esp_gdbstub/src/port/xtensa/gdbstub_xtensa.c index e049cbd31e..f62886c7de 100644 --- a/components/esp_gdbstub/src/port/xtensa/gdbstub_xtensa.c +++ b/components/esp_gdbstub/src/port/xtensa/gdbstub_xtensa.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -42,43 +42,135 @@ static void update_regfile_common(esp_gdbstub_gdb_regfile_t *dst) #if XCHAL_HAVE_FP /** @brief Read FPU registers to memory */ -static void gdbstub_read_fpu_regs(void *data) +static void gdbstub_read_fpu_regs(xtensa_fpu_regs_t *fpu) { - float *ptr0; - void *ptr1; + uint32_t tmp; - asm volatile ("mov %0, %1" : "=a" (ptr0) : "a" (data)); + /* Read FPU registers from memory */ + asm volatile ("ssi f0, %0, 0" :: "a" (&fpu->f[0])); + asm volatile ("ssi f1, %0, 0" :: "a" (&fpu->f[1])); + asm volatile ("ssi f2, %0, 0" :: "a" (&fpu->f[2])); + asm volatile ("ssi f3, %0, 0" :: "a" (&fpu->f[3])); + asm volatile ("ssi f4, %0, 0" :: "a" (&fpu->f[4])); + asm volatile ("ssi f5, %0, 0" :: "a" (&fpu->f[5])); + asm volatile ("ssi f6, %0, 0" :: "a" (&fpu->f[6])); + asm volatile ("ssi f7, %0, 0" :: "a" (&fpu->f[7])); + asm volatile ("ssi f8, %0, 0" :: "a" (&fpu->f[8])); + asm volatile ("ssi f9, %0, 0" :: "a" (&fpu->f[9])); + asm volatile ("ssi f10, %0, 0" :: "a" (&fpu->f[10])); + asm volatile ("ssi f11, %0, 0" :: "a" (&fpu->f[11])); + asm volatile ("ssi f12, %0, 0" :: "a" (&fpu->f[12])); + asm volatile ("ssi f13, %0, 0" :: "a" (&fpu->f[13])); + asm volatile ("ssi f14, %0, 0" :: "a" (&fpu->f[14])); + asm volatile ("ssi f15, %0, 0" :: "a" (&fpu->f[15])); - asm volatile ("rur.FCR %0" : "=a" (ptr1)); - asm volatile ("s32i %0, %1, 64" : "=a" (ptr1) : "a" (ptr0)); - asm volatile ("rur.FSR %0" : "=a" (ptr1)); - asm volatile ("s32i %0, %1, 68" : "=a" (ptr1) : "a" (ptr0)); + /* Read FCR and FSR from CPU registers */ + asm volatile ("rur.FCR %0" : "=a" (tmp)); + asm volatile ("s32i %0, %1, 0" : "=a" (tmp) : "a" (&fpu->fcr)); + asm volatile ("rur.FSR %0" : "=a" (tmp)); + asm volatile ("s32i %0, %1, 0" : "=a" (tmp) : "a" (&fpu->fsr)); +} - asm volatile ("ssi f0, %0, 0" :: "a" (ptr0)); //*(ptr0 + 0) = f0; - asm volatile ("ssi f1, %0, 4" :: "a" (ptr0)); //*(ptr0 + 4) = f1; - asm volatile ("ssi f2, %0, 8" :: "a" (ptr0)); //... - asm volatile ("ssi f3, %0, 12" :: "a" (ptr0)); - asm volatile ("ssi f4, %0, 16" :: "a" (ptr0)); - asm volatile ("ssi f5, %0, 20" :: "a" (ptr0)); - asm volatile ("ssi f6, %0, 24" :: "a" (ptr0)); - asm volatile ("ssi f7, %0, 28" :: "a" (ptr0)); - asm volatile ("ssi f8, %0, 32" :: "a" (ptr0)); - asm volatile ("ssi f9, %0, 36" :: "a" (ptr0)); - asm volatile ("ssi f10, %0, 40" :: "a" (ptr0)); - asm volatile ("ssi f11, %0, 44" :: "a" (ptr0)); - asm volatile ("ssi f12, %0, 48" :: "a" (ptr0)); - asm volatile ("ssi f13, %0, 52" :: "a" (ptr0)); - asm volatile ("ssi f14, %0, 56" :: "a" (ptr0)); - asm volatile ("ssi f15, %0, 60" :: "a" (ptr0)); +static void *esp_gdbstub_coproc_saved_area(void *tcb, int coproc) +{ + /** + * Offset to start of the CPSA area on the stack. See uxInitialiseStackCPSA(). + */ + extern const uint32_t offset_cpsa; + extern const uint32_t offset_pxEndOfStack; + extern uintptr_t _xt_coproc_owner_sa[portNUM_PROCESSORS][XCHAL_CP_MAX]; + uint32_t core = esp_cpu_get_core_id(); + uint16_t coproc_bit = 1 << coproc; + /* + * Calculate CP save area header pointer (same as get_cpsa_from_tcb macro): + * 1. Get pxEndOfStack from TCB + * 2. Subtract offset_cpsa + * 3. Align down to 16 bytes + * + * For more details refer to comments in uxInitialiseStackCPSA() in port.c. + */ + void *cpsa_header_ptr = *(void **)((char *)tcb + offset_pxEndOfStack); + cpsa_header_ptr = (char *)cpsa_header_ptr - offset_cpsa; + cpsa_header_ptr = (void *)((uintptr_t)cpsa_header_ptr & ~0xF); + /* For more details about fields, refer to comments in xtensa_context.h */ + typedef struct { + uint16_t xt_cpenable; + uint16_t xt_cpstored; + uint16_t xt_cp_cs_st; + uint16_t dummy; + void *xt_cp_asa; + } cpsa_header_t; + cpsa_header_t *cpsa_header = (cpsa_header_t *)cpsa_header_ptr; + + /* TODO: IDF-12550. Provide correct read access for coprocessor owned by another CPU. + * Accessing registers in stack-frame is not correct in this case. + */ + for (uint32_t i = 0; i < portNUM_PROCESSORS; i++) { + if (i == core) { + continue; + } + if (_xt_coproc_owner_sa[i][coproc] == (uintptr_t)cpsa_header) { + return cpsa_header->xt_cp_asa; + } + } + + /* TODO IDF-15054: + * - Handle case when coprocessor instructions have not been called yet for this task + */ + if ((cpsa_header->xt_cpstored & coproc_bit) || + (cpsa_header->xt_cp_cs_st & coproc_bit)) { + return cpsa_header->xt_cp_asa; + } + + return NULL; +} + +static uint32_t enable_coproc(int coproc) +{ + bool fpu_enabled = false; + uint32_t cp_enabled; + + RSR(XT_REG_CPENABLE, cp_enabled); + if (cp_enabled & (1 << coproc)) { + fpu_enabled = true; + } + + if (!fpu_enabled) { + uint32_t new_cp_enabled = cp_enabled | (1 << coproc); + WSR(XT_REG_CPENABLE, new_cp_enabled); + } + + return cp_enabled; +} + +static void write_fpu_regs_to_regfile(void *tcb, esp_gdbstub_gdb_regfile_t *dst) +{ + xtensa_fpu_regs_t *fpu_save_area = esp_gdbstub_coproc_saved_area(tcb, XCHAL_CP_ID_FPU); + + /* + * In case of current thread is the owner of FPU, that means FPU registers was not stored to thread TCB. + * According to the lazy saving of FPU registers, we have to read from CPU registers. + * + * NOTE: FPU must be enabled before reading from CPU registers to avoid triggering exception. + */ + if (fpu_save_area == NULL) { + /* enable FPU first to avoid triggering exception */ + uint32_t cp_enabled = enable_coproc(XCHAL_CP_ID_FPU); + + /* Read FPU registers from CPU registers */ + gdbstub_read_fpu_regs(&dst->fpu); + + /* Restore FPU enabled state */ + WSR(XT_REG_CPENABLE, cp_enabled); + } else { + /* FPU registers was stored to thread TCB, copy them to the register file */ + memcpy (&dst->fpu, fpu_save_area, sizeof(dst->fpu)); + } } #endif // XCHAL_HAVE_FP -extern const uint32_t offset_pxEndOfStack; -extern const uint32_t offset_cpsa; /* Offset to start of the CPSA area on the stack. See uxInitialiseStackCPSA(). */ -extern uint32_t _xt_coproc_owner_sa[2]; - void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_gdb_regfile_t *dst) { init_regfile(dst); @@ -102,34 +194,8 @@ void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_ } #if XCHAL_HAVE_FP - - extern void *pxCurrentTCBs[2]; - void *current_tcb_ptr = pxCurrentTCBs[0]; - uint32_t *current_fpu_ptr = NULL; - -#if !CONFIG_FREERTOS_UNICORE - current_tcb_ptr = pxCurrentTCBs[esp_cpu_get_core_id()]; -#endif - uint32_t cp_enabled; - RSR(XT_REG_CPENABLE, cp_enabled); - - // Check if the co-processor is enabled - if (cp_enabled) { - gdbstub_read_fpu_regs(dst->f); - } else { - current_tcb_ptr += offset_pxEndOfStack; - current_tcb_ptr = *(void **)current_tcb_ptr; - current_tcb_ptr -= offset_cpsa; - // Operation (&~0xf) required in .macro get_cpsa_from_tcb reg_A reg_B - current_tcb_ptr = (void*)((uint32_t)current_tcb_ptr&~0xf); - current_fpu_ptr = *(uint32_t **)(current_tcb_ptr + XT_CP_ASA); - - dst->fcr = current_fpu_ptr[0]; - dst->fsr = current_fpu_ptr[1]; - for (int i = 0; i < 16; i++) { - dst->f[i] = current_fpu_ptr[i + 2]; - } - } + extern void *pxCurrentTCBs[portNUM_PROCESSORS]; + write_fpu_regs_to_regfile(pxCurrentTCBs[esp_cpu_get_core_id()], dst); #endif //XCHAL_HAVE_FP #if XCHAL_HAVE_LOOPS dst->lbeg = frame->lbeg; @@ -175,40 +241,7 @@ void esp_gdbstub_tcb_frame_to_regfile(dummy_tcb_t *tcb, esp_gdbstub_gdb_regfile_ } #if XCHAL_HAVE_FP - uint32_t *current_xt_coproc_owner_sa = (uint32_t *)_xt_coproc_owner_sa[0]; - -#if !CONFIG_FREERTOS_UNICORE - current_xt_coproc_owner_sa = (uint32_t *)_xt_coproc_owner_sa[esp_cpu_get_core_id()]; -#endif - - uint32_t cp_enabled; - RSR(XT_REG_CPENABLE, cp_enabled); - - void *current_tcb_ptr = tcb; - uint32_t *current_fpu_ptr = NULL; - { - current_tcb_ptr += offset_pxEndOfStack; - current_tcb_ptr = *(void **)current_tcb_ptr; - current_tcb_ptr -= offset_cpsa; - // Operation (&~0xf) required in .macro get_cpsa_from_tcb reg_A reg_B - current_tcb_ptr = (void*)((uint32_t)current_tcb_ptr&~0xf); - current_fpu_ptr = *(uint32_t **)(current_tcb_ptr + XT_CP_ASA); - - bool use_fpu_regs = ((false == cp_enabled) && (current_xt_coproc_owner_sa[0] == 1) && (current_fpu_ptr == (uint32_t*)current_xt_coproc_owner_sa[2])); - - dst->fcr = current_fpu_ptr[0]; - dst->fsr = current_fpu_ptr[1]; - for (int i = 0; i < 16; i++) { - dst->f[i] = current_fpu_ptr[i + 2]; - } - - /* We have situation when FPU is in use, but the context not stored - to the memory, and we have to read from CPU registers. - */ - if (use_fpu_regs) { - gdbstub_read_fpu_regs(dst->f); - } - } + write_fpu_regs_to_regfile(tcb, dst); #endif // XCHAL_HAVE_FP #if XCHAL_HAVE_LOOPS @@ -344,11 +377,84 @@ void esp_gdbstub_trigger_cpu(void) #endif } +#if XCHAL_HAVE_FP +static void gdbstub_set_fpu_register(uint32_t fpu_reg_index, float *value_ptr) +{ + if (fpu_reg_index == 0) { + asm volatile ("lsi f0, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 1) { + asm volatile ("lsi f1, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 2) { + asm volatile ("lsi f2, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 3) { + asm volatile ("lsi f3, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 4) { + asm volatile ("lsi f4, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 5) { + asm volatile ("lsi f5, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 6) { + asm volatile ("lsi f6, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 7) { + asm volatile ("lsi f7, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 8) { + asm volatile ("lsi f8, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 9) { + asm volatile ("lsi f9, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 10) { + asm volatile ("lsi f10, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 11) { + asm volatile ("lsi f11, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 12) { + asm volatile ("lsi f12, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 13) { + asm volatile ("lsi f13, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 14) { + asm volatile ("lsi f14, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 15) { + asm volatile ("lsi f15, %0, 0" :: "a" (value_ptr)); + } else if (fpu_reg_index == 16) { + asm volatile ("wur.FCR %0" :: "a" (*value_ptr)); + } else if (fpu_reg_index == 17) { + asm volatile ("wur.FSR %0" :: "a" (*value_ptr)); + } +} + +static void gdbstub_write_fpu_regs(esp_gdbstub_frame_t *frame, uint32_t reg_index, uint32_t *value_ptr) +{ +#if CONFIG_IDF_TARGET_ESP32 + const uint32_t fpu_start_register = 87; +#elif CONFIG_IDF_TARGET_ESP32S3 + const uint32_t fpu_start_register = 84; +#else +#error "Unknown Xtensa chip" +#endif + const StaticTask_t *tcb; + uint32_t *fpu_save_area; + + uint32_t fpu_reg_index = reg_index - fpu_start_register; + if (fpu_reg_index >= (16 + 2)) { + return; + } + + tcb = esp_gdbstub_find_tcb_by_frame(frame); + fpu_save_area = esp_gdbstub_coproc_saved_area((void *)tcb, XCHAL_CP_ID_FPU); + + if (fpu_save_area == NULL) { + uint32_t cp_enabled = enable_coproc(XCHAL_CP_ID_FPU); + + gdbstub_set_fpu_register(fpu_reg_index, (float *)value_ptr); + + WSR(XT_REG_CPENABLE, cp_enabled); + } else { + fpu_save_area[fpu_reg_index] = *value_ptr; + } +} +#endif // XCHAL_HAVE_FP + /** @brief GDB set register in frame * Set register in frame with address to value * * */ - void esp_gdbstub_set_register(esp_gdbstub_frame_t *frame, uint32_t reg_index, uint32_t *value_ptr) { uint32_t value = *value_ptr; @@ -358,65 +464,7 @@ void esp_gdbstub_set_register(esp_gdbstub_frame_t *frame, uint32_t reg_index, ui } else if (reg_index > 0 && (reg_index <= 27)) { (&frame->a0)[reg_index - 1] = value; } - #if XCHAL_HAVE_FP - uint32_t cp_enabled; - RSR(XT_REG_CPENABLE, cp_enabled); - if (cp_enabled != 0) { - if (reg_index == 87) { - asm volatile ("lsi f0, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 88) { - asm volatile ("lsi f1, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 89) { - asm volatile ("lsi f2, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 90) { - asm volatile ("lsi f3, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 91) { - asm volatile ("lsi f4, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 92) { - asm volatile ("lsi f5, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 93) { - asm volatile ("lsi f6, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 94) { - asm volatile ("lsi f7, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 95) { - asm volatile ("lsi f8, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 96) { - asm volatile ("lsi f9, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 97) { - asm volatile ("lsi f10, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 98) { - asm volatile ("lsi f11, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 99) { - asm volatile ("lsi f12, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 100) { - asm volatile ("lsi f13, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 101) { - asm volatile ("lsi f14, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 102) { - asm volatile ("lsi f15, %0, 0" :: "a" (value_ptr)); - } - if (reg_index == 103) { - asm volatile ("wur.FCR %0" : "=a" (value)); - } - if (reg_index == 104) { - asm volatile ("wur.FSR %0" : "=a" (value)); - } - } + gdbstub_write_fpu_regs(frame, reg_index, value_ptr); #endif // XCHAL_HAVE_FP } diff --git a/components/esp_gdbstub/src/port/xtensa/include/esp_gdbstub_arch.h b/components/esp_gdbstub/src/port/xtensa/include/esp_gdbstub_arch.h index 1efe761cef..d0b9095aba 100644 --- a/components/esp_gdbstub/src/port/xtensa/include/esp_gdbstub_arch.h +++ b/components/esp_gdbstub/src/port/xtensa/include/esp_gdbstub_arch.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,20 +9,20 @@ #include "xtensa_context.h" #include "sdkconfig.h" -#if CONFIG_IDF_TARGET_ESP32 -#define GDBSTUB_EXTRA_TIE_SIZE 0 -#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) -#define GDBSTUB_EXTRA_TIE_SIZE 1 -#else -#error "Unknown Xtensa chip" -#endif - #ifdef __cplusplus extern "C" { #endif typedef XtExcFrame esp_gdbstub_frame_t; +#if XCHAL_HAVE_FP +typedef struct { + uint32_t f[16]; + uint32_t fcr; + uint32_t fsr; +} xtensa_fpu_regs_t; +#endif + /* GDB regfile structure, configuration dependent */ typedef struct { uint32_t pc; @@ -73,14 +73,12 @@ typedef struct { uint32_t f64s; #endif -#if XCHAL_HAVE_FP - uint32_t f[16]; - uint32_t fcr; - uint32_t fsr; +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + uint32_t gpio_out; #endif -#if GDBSTUB_EXTRA_TIE_SIZE > 0 - uint32_t tie[GDBSTUB_EXTRA_TIE_SIZE]; +#if XCHAL_HAVE_FP + xtensa_fpu_regs_t fpu; #endif } esp_gdbstub_gdb_regfile_t; diff --git a/components/xtensa/esp32/include/xtensa/config/tie-asm.h b/components/xtensa/esp32/include/xtensa/config/tie-asm.h index 649a105806..740a832d04 100644 --- a/components/xtensa/esp32/include/xtensa/config/tie-asm.h +++ b/components/xtensa/esp32/include/xtensa/config/tie-asm.h @@ -231,26 +231,26 @@ // Custom caller-saved registers not used by default by the compiler: .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) xchal_sa_align \ptr, 0, 948, 4, 4 + ssi f0, \ptr, .Lxchal_ofs_+0 + ssi f1, \ptr, .Lxchal_ofs_+4 + ssi f2, \ptr, .Lxchal_ofs_+8 + ssi f3, \ptr, .Lxchal_ofs_+12 + ssi f4, \ptr, .Lxchal_ofs_+16 + ssi f5, \ptr, .Lxchal_ofs_+20 + ssi f6, \ptr, .Lxchal_ofs_+24 + ssi f7, \ptr, .Lxchal_ofs_+28 + ssi f8, \ptr, .Lxchal_ofs_+32 + ssi f9, \ptr, .Lxchal_ofs_+36 + ssi f10, \ptr, .Lxchal_ofs_+40 + ssi f11, \ptr, .Lxchal_ofs_+44 + ssi f12, \ptr, .Lxchal_ofs_+48 + ssi f13, \ptr, .Lxchal_ofs_+52 + ssi f14, \ptr, .Lxchal_ofs_+56 + ssi f15, \ptr, .Lxchal_ofs_+60 rur.FCR \at1 // ureg 232 - s32i \at1, \ptr, .Lxchal_ofs_+0 + s32i \at1, \ptr, .Lxchal_ofs_+64 rur.FSR \at1 // ureg 233 - s32i \at1, \ptr, .Lxchal_ofs_+4 - ssi f0, \ptr, .Lxchal_ofs_+8 - ssi f1, \ptr, .Lxchal_ofs_+12 - ssi f2, \ptr, .Lxchal_ofs_+16 - ssi f3, \ptr, .Lxchal_ofs_+20 - ssi f4, \ptr, .Lxchal_ofs_+24 - ssi f5, \ptr, .Lxchal_ofs_+28 - ssi f6, \ptr, .Lxchal_ofs_+32 - ssi f7, \ptr, .Lxchal_ofs_+36 - ssi f8, \ptr, .Lxchal_ofs_+40 - ssi f9, \ptr, .Lxchal_ofs_+44 - ssi f10, \ptr, .Lxchal_ofs_+48 - ssi f11, \ptr, .Lxchal_ofs_+52 - ssi f12, \ptr, .Lxchal_ofs_+56 - ssi f13, \ptr, .Lxchal_ofs_+60 - ssi f14, \ptr, .Lxchal_ofs_+64 - ssi f15, \ptr, .Lxchal_ofs_+68 + s32i \at1, \ptr, .Lxchal_ofs_+68 .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 xchal_sa_align \ptr, 0, 948, 4, 4 @@ -273,26 +273,26 @@ // Custom caller-saved registers not used by default by the compiler: .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) xchal_sa_align \ptr, 0, 948, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 + lsi f0, \ptr, .Lxchal_ofs_+0 + lsi f1, \ptr, .Lxchal_ofs_+4 + lsi f2, \ptr, .Lxchal_ofs_+8 + lsi f3, \ptr, .Lxchal_ofs_+12 + lsi f4, \ptr, .Lxchal_ofs_+16 + lsi f5, \ptr, .Lxchal_ofs_+20 + lsi f6, \ptr, .Lxchal_ofs_+24 + lsi f7, \ptr, .Lxchal_ofs_+28 + lsi f8, \ptr, .Lxchal_ofs_+32 + lsi f9, \ptr, .Lxchal_ofs_+36 + lsi f10, \ptr, .Lxchal_ofs_+40 + lsi f11, \ptr, .Lxchal_ofs_+44 + lsi f12, \ptr, .Lxchal_ofs_+48 + lsi f13, \ptr, .Lxchal_ofs_+52 + lsi f14, \ptr, .Lxchal_ofs_+56 + lsi f15, \ptr, .Lxchal_ofs_+60 + l32i \at1, \ptr, .Lxchal_ofs_+64 wur.FCR \at1 // ureg 232 - l32i \at1, \ptr, .Lxchal_ofs_+4 + l32i \at1, \ptr, .Lxchal_ofs_+68 wur.FSR \at1 // ureg 233 - lsi f0, \ptr, .Lxchal_ofs_+8 - lsi f1, \ptr, .Lxchal_ofs_+12 - lsi f2, \ptr, .Lxchal_ofs_+16 - lsi f3, \ptr, .Lxchal_ofs_+20 - lsi f4, \ptr, .Lxchal_ofs_+24 - lsi f5, \ptr, .Lxchal_ofs_+28 - lsi f6, \ptr, .Lxchal_ofs_+32 - lsi f7, \ptr, .Lxchal_ofs_+36 - lsi f8, \ptr, .Lxchal_ofs_+40 - lsi f9, \ptr, .Lxchal_ofs_+44 - lsi f10, \ptr, .Lxchal_ofs_+48 - lsi f11, \ptr, .Lxchal_ofs_+52 - lsi f12, \ptr, .Lxchal_ofs_+56 - lsi f13, \ptr, .Lxchal_ofs_+60 - lsi f14, \ptr, .Lxchal_ofs_+64 - lsi f15, \ptr, .Lxchal_ofs_+68 .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 xchal_sa_align \ptr, 0, 948, 4, 4 diff --git a/components/xtensa/esp32s3/include/xtensa/config/tie-asm.h b/components/xtensa/esp32s3/include/xtensa/config/tie-asm.h index 104dc10fd4..f49a5486aa 100644 --- a/components/xtensa/esp32s3/include/xtensa/config/tie-asm.h +++ b/components/xtensa/esp32s3/include/xtensa/config/tie-asm.h @@ -203,26 +203,26 @@ // Custom caller-saved registers not used by default by the compiler: .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) xchal_sa_align \ptr, 0, 948, 4, 4 + ssi f0, \ptr, .Lxchal_ofs_+0 + ssi f1, \ptr, .Lxchal_ofs_+4 + ssi f2, \ptr, .Lxchal_ofs_+8 + ssi f3, \ptr, .Lxchal_ofs_+12 + ssi f4, \ptr, .Lxchal_ofs_+16 + ssi f5, \ptr, .Lxchal_ofs_+20 + ssi f6, \ptr, .Lxchal_ofs_+24 + ssi f7, \ptr, .Lxchal_ofs_+28 + ssi f8, \ptr, .Lxchal_ofs_+32 + ssi f9, \ptr, .Lxchal_ofs_+36 + ssi f10, \ptr, .Lxchal_ofs_+40 + ssi f11, \ptr, .Lxchal_ofs_+44 + ssi f12, \ptr, .Lxchal_ofs_+48 + ssi f13, \ptr, .Lxchal_ofs_+52 + ssi f14, \ptr, .Lxchal_ofs_+56 + ssi f15, \ptr, .Lxchal_ofs_+60 rur.FCR \at1 // ureg 232 - s32i \at1, \ptr, .Lxchal_ofs_+0 + s32i \at1, \ptr, .Lxchal_ofs_+64 rur.FSR \at1 // ureg 233 - s32i \at1, \ptr, .Lxchal_ofs_+4 - ssi f0, \ptr, .Lxchal_ofs_+8 - ssi f1, \ptr, .Lxchal_ofs_+12 - ssi f2, \ptr, .Lxchal_ofs_+16 - ssi f3, \ptr, .Lxchal_ofs_+20 - ssi f4, \ptr, .Lxchal_ofs_+24 - ssi f5, \ptr, .Lxchal_ofs_+28 - ssi f6, \ptr, .Lxchal_ofs_+32 - ssi f7, \ptr, .Lxchal_ofs_+36 - ssi f8, \ptr, .Lxchal_ofs_+40 - ssi f9, \ptr, .Lxchal_ofs_+44 - ssi f10, \ptr, .Lxchal_ofs_+48 - ssi f11, \ptr, .Lxchal_ofs_+52 - ssi f12, \ptr, .Lxchal_ofs_+56 - ssi f13, \ptr, .Lxchal_ofs_+60 - ssi f14, \ptr, .Lxchal_ofs_+64 - ssi f15, \ptr, .Lxchal_ofs_+68 + s32i \at1, \ptr, .Lxchal_ofs_+68 .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 xchal_sa_align \ptr, 0, 948, 4, 4 @@ -245,26 +245,26 @@ // Custom caller-saved registers not used by default by the compiler: .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) xchal_sa_align \ptr, 0, 948, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 + lsi f0, \ptr, .Lxchal_ofs_+0 + lsi f1, \ptr, .Lxchal_ofs_+4 + lsi f2, \ptr, .Lxchal_ofs_+8 + lsi f3, \ptr, .Lxchal_ofs_+12 + lsi f4, \ptr, .Lxchal_ofs_+16 + lsi f5, \ptr, .Lxchal_ofs_+20 + lsi f6, \ptr, .Lxchal_ofs_+24 + lsi f7, \ptr, .Lxchal_ofs_+28 + lsi f8, \ptr, .Lxchal_ofs_+32 + lsi f9, \ptr, .Lxchal_ofs_+36 + lsi f10, \ptr, .Lxchal_ofs_+40 + lsi f11, \ptr, .Lxchal_ofs_+44 + lsi f12, \ptr, .Lxchal_ofs_+48 + lsi f13, \ptr, .Lxchal_ofs_+52 + lsi f14, \ptr, .Lxchal_ofs_+56 + lsi f15, \ptr, .Lxchal_ofs_+60 + l32i \at1, \ptr, .Lxchal_ofs_+64 wur.FCR \at1 // ureg 232 - l32i \at1, \ptr, .Lxchal_ofs_+4 + l32i \at1, \ptr, .Lxchal_ofs_+68 wur.FSR \at1 // ureg 233 - lsi f0, \ptr, .Lxchal_ofs_+8 - lsi f1, \ptr, .Lxchal_ofs_+12 - lsi f2, \ptr, .Lxchal_ofs_+16 - lsi f3, \ptr, .Lxchal_ofs_+20 - lsi f4, \ptr, .Lxchal_ofs_+24 - lsi f5, \ptr, .Lxchal_ofs_+28 - lsi f6, \ptr, .Lxchal_ofs_+32 - lsi f7, \ptr, .Lxchal_ofs_+36 - lsi f8, \ptr, .Lxchal_ofs_+40 - lsi f9, \ptr, .Lxchal_ofs_+44 - lsi f10, \ptr, .Lxchal_ofs_+48 - lsi f11, \ptr, .Lxchal_ofs_+52 - lsi f12, \ptr, .Lxchal_ofs_+56 - lsi f13, \ptr, .Lxchal_ofs_+60 - lsi f14, \ptr, .Lxchal_ofs_+64 - lsi f15, \ptr, .Lxchal_ofs_+68 .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 xchal_sa_align \ptr, 0, 948, 4, 4 diff --git a/tools/test_apps/system/gdbstub_runtime/main/CMakeLists.txt b/tools/test_apps/system/gdbstub_runtime/main/CMakeLists.txt index b21060ff71..570ce47bae 100644 --- a/tools/test_apps/system/gdbstub_runtime/main/CMakeLists.txt +++ b/tools/test_apps/system/gdbstub_runtime/main/CMakeLists.txt @@ -1,12 +1,12 @@ set(srcs "test_app_main.c") -if(CONFIG_IDF_TARGET_ARCH_RISCV) - if(CONFIG_SOC_CPU_HAS_HWLOOP) +if(CONFIG_SOC_CPU_HAS_HWLOOP) list(APPEND srcs "xesppie_loops.S") - endif() - if(CONFIG_SOC_CPU_HAS_FPU OR CONFIG_SOC_CPU_HAS_PIE) +endif() +if(CONFIG_SOC_CPU_HAS_FPU OR CONFIG_SOC_CPU_HAS_PIE) list(APPEND srcs "coproc_regs.c") +endif() +if(CONFIG_IDF_TARGET_ARCH_RISCV) set(ext_comp "riscv") - endif() endif() idf_component_register(SRCS ${srcs} diff --git a/tools/test_apps/system/gdbstub_runtime/main/coproc_regs.c b/tools/test_apps/system/gdbstub_runtime/main/coproc_regs.c index 603674a038..e8d1b765db 100644 --- a/tools/test_apps/system/gdbstub_runtime/main/coproc_regs.c +++ b/tools/test_apps/system/gdbstub_runtime/main/coproc_regs.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -7,7 +7,9 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" +#if CONFIG_IDF_TARGET_ARCH_RISCV #include "riscv/rvruntime-frames.h" +#endif #include "soc/soc_caps.h" static SemaphoreHandle_t sem = NULL; @@ -74,13 +76,27 @@ pie_start: #if SOC_CPU_HAS_FPU static void test_fpu(void * arg) { +#if CONFIG_IDF_TARGET_ARCH_XTENSA + struct { + float f[16]; + } fpu_regs_sample, fpu_regs; +#endif +#if CONFIG_IDF_TARGET_ARCH_RISCV RvFPUSaveArea fpu_regs_sample, fpu_regs; - +#endif uint32_t *ptr = (uint32_t *)&fpu_regs_sample; for (int i = 0; i < sizeof(fpu_regs_sample)/sizeof(uint32_t); i++) { - ptr[i] = i + (uintptr_t) arg; + ptr[i] = i + (int) arg; } + /* Set FPU owner to current task by calling an instruction */ +#if CONFIG_IDF_TARGET_ARCH_XTENSA + __asm__ volatile ("ssi f0, %0, 0" :: "a" (&fpu_regs)); +#endif +#if 0 // TODO IDF-15053: set CONFIG_IDF_TARGET_ARCH_RISCV + __asm__ volatile ("fsw ft0, %0" : "=m" (fpu_regs.ft0)); +#endif + fpu_start: asm volatile ("nop"); @@ -88,6 +104,25 @@ fpu_start: vTaskDelay(50 / portTICK_PERIOD_MS); } +#if CONFIG_IDF_TARGET_ARCH_XTENSA + __asm__ volatile ("ssi f0, %0, 0" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f1, %0, 4" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f2, %0, 8" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f3, %0, 12" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f4, %0, 16" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f5, %0, 20" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f6, %0, 24" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f7, %0, 28" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f8, %0, 32" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f9, %0, 36" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f10, %0, 40" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f11, %0, 44" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f12, %0, 48" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f13, %0, 52" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f14, %0, 56" :: "a" (&fpu_regs)); + __asm__ volatile ("ssi f15, %0, 60" :: "a" (&fpu_regs)); +#endif +#if CONFIG_IDF_TARGET_ARCH_RISCV __asm__ volatile ("fsw ft0, %0" : "=m" (fpu_regs.ft0)); __asm__ volatile ("fsw ft1, %0" : "=m" (fpu_regs.ft1)); __asm__ volatile ("fsw ft2, %0" : "=m" (fpu_regs.ft2)); @@ -121,6 +156,7 @@ fpu_start: __asm__ volatile ("fsw ft10, %0" : "=m" (fpu_regs.ft10)); __asm__ volatile ("fsw ft11, %0" : "=m" (fpu_regs.ft11)); __asm__ volatile ("csrr %0, fcsr" : "=r" (fpu_regs.fcsr)); +#endif if (!memcmp(&fpu_regs_sample, &fpu_regs, sizeof(fpu_regs))) { xSemaphoreGive((SemaphoreHandle_t) sem); diff --git a/tools/test_apps/system/gdbstub_runtime/main/test_app_main.c b/tools/test_apps/system/gdbstub_runtime/main/test_app_main.c index 06f05277f1..d1e76d93a0 100644 --- a/tools/test_apps/system/gdbstub_runtime/main/test_app_main.c +++ b/tools/test_apps/system/gdbstub_runtime/main/test_app_main.c @@ -10,7 +10,7 @@ #include "freertos/task.h" #include "sdkconfig.h" -#define TEST_COPROCESSOR_REGISTERS (__riscv && (SOC_CPU_HAS_FPU || SOC_CPU_HAS_PIE)) +#define TEST_COPROCESSOR_REGISTERS (SOC_CPU_HAS_FPU || SOC_CPU_HAS_PIE) #define TEST_HWLOOP_INSTRUCTIONS (__riscv && SOC_CPU_HAS_HWLOOP) int var_1; diff --git a/tools/test_apps/system/gdbstub_runtime/pytest_gdbstub_runtime.py b/tools/test_apps/system/gdbstub_runtime/pytest_gdbstub_runtime.py index feb22eab4b..6204059f93 100644 --- a/tools/test_apps/system/gdbstub_runtime/pytest_gdbstub_runtime.py +++ b/tools/test_apps/system/gdbstub_runtime/pytest_gdbstub_runtime.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import os import os.path as path @@ -147,7 +147,7 @@ def check_registers_numbers(dut: PanicTestDut) -> None: r_id += 1 -def set_float_registers(dut: PanicTestDut, t_id: int, addition: int) -> None: +def set_riscv_float_registers(dut: PanicTestDut, t_id: int, addition: int) -> None: cmd = f'-thread-select {t_id}' responses = dut.gdb_write(cmd) assert dut.find_gdb_response('done', 'result', responses) is not None @@ -157,13 +157,39 @@ def set_float_registers(dut: PanicTestDut, t_id: int, addition: int) -> None: responses = dut.gdb_write(cmd) assert dut.find_gdb_response('done', 'result', responses) is not None - # Note that it's a gap between the last floating register number and fcsr register number. - cmd = f'-data-write-register-values d 68 {32 + addition}' + # Note that it's a gap between the last floating register number and fcsr register number. + cmd = f'-data-write-register-values d 68 {32 + addition}' + responses = dut.gdb_write(cmd) + assert dut.find_gdb_response('done', 'result', responses) is not None + + +def set_xtensa_float_registers(dut: PanicTestDut, t_id: int, addition: int) -> None: + """Set Xtensa FPU registers via GDB. + + Xtensa FPU register numbers: + - f0-f15: registers 87-102 + - fcr: register 103 + - fsr: register 104 + """ + cmd = f'-thread-select {t_id}' + responses = dut.gdb_write(cmd) + assert dut.find_gdb_response('done', 'result', responses) is not None + + if dut.target == 'esp32': + fpu_current_register = 87 + elif dut.target == 'esp32s3': + fpu_current_register = 84 + else: + raise ValueError(f'Unsupported target: {dut.target}') + + for i in range(18): # 16 f* registers + fcr + fsr + cmd = f'-data-write-register-values d {fpu_current_register} {i + addition}' responses = dut.gdb_write(cmd) assert dut.find_gdb_response('done', 'result', responses) is not None + fpu_current_register += 1 -def set_pie_registers(dut: PanicTestDut, t_id: int, addition: int) -> None: +def set_riscv_pie_registers(dut: PanicTestDut, t_id: int, addition: int) -> None: cmd = f'-thread-select {t_id}' responses = dut.gdb_write(cmd) assert dut.find_gdb_response('done', 'result', responses) is not None @@ -212,15 +238,14 @@ def coproc_registers_test(dut: PanicTestDut, regs_type: str, set_registers: Call - Task coproc owner (direct registers write) - Other tasks (write registers to task's stack) """ - coproc_tasks = [f'test_{regs_type}_1', f'test_{regs_type}_2'] - found_tasks = [False] * len(coproc_tasks) + found_count = 0 for t in threads: - for index, test in enumerate(coproc_tasks): - if test in t['details']: - set_registers(dut, t['id'], index + 1) - found_tasks[index] = True + for task_num in [1, 2]: + if f'test_{regs_type}_{task_num}' in t['details']: + set_registers(dut, t['id'], task_num) + found_count += 1 - assert all(found_tasks) + assert found_count == 2, f'Expected 2 coproc tasks, found {found_count}' dut_set_variable(dut, f'test_{regs_type}_ready', 1) @@ -240,28 +265,30 @@ def coproc_registers_test(dut: PanicTestDut, regs_type: str, set_registers: Call threads = dut_get_threads(dut) - found_tasks = [False] * len(coproc_tasks) + found_count = 0 for t in threads: - for index, test in enumerate(coproc_tasks): - if test in t['details']: - found_tasks[index] = True + for task_num in [1, 2]: + if f'test_{regs_type}_{task_num}' in t['details']: + found_count += 1 - assert not any(found_tasks) + assert found_count == 0, f'Expected 0 coproc tasks, found {found_count}' @pytest.mark.generic -@idf_parametrize('target', ['esp32p4'], indirect=['target']) +@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target']) def test_coproc_registers(dut: PanicTestDut) -> None: start_gdb(dut) # enable coprocessors registers testing dut_enable_test(dut, 'coproc_regs') - check_registers_numbers(dut) - - coproc_registers_test(dut, 'fpu', set_float_registers) - if dut.target == 'esp32p4': - coproc_registers_test(dut, 'pie', set_pie_registers) + if dut.is_xtensa: + coproc_registers_test(dut, 'fpu', set_xtensa_float_registers) + else: + check_registers_numbers(dut) + coproc_registers_test(dut, 'fpu', set_riscv_float_registers) + if dut.target == 'esp32p4': + coproc_registers_test(dut, 'pie', set_riscv_pie_registers) @pytest.mark.generic