This is an automated email from Gerrit.

"Erhan Kurubas <erhan.kuru...@espressif.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7758

-- gerrit

commit 7a8b1129e6a6a8c4a49a72d197682bb2eb97c8bf
Author: Erhan Kurubas <erhan.kuru...@espressif.com>
Date:   Mon Jul 3 23:16:52 2023 +0200

    target/espressif: read entry addresses of pre-defined stub functions
    
    Debug stubs functionality provided by ESP IDF allows executing
    target function in any address. e.g; esp32_cmd_gcov()
    
    Checkpatch-ignore: MACRO_ARG_REUSE
    
    Signed-off-by: Erhan Kurubas <erhan.kuru...@espressif.com>
    Change-Id: I56d844e5a862c9bf33fdb991b01abb7a76047ca7

diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am
index 14625d4b36..776818ff4d 100644
--- a/src/target/espressif/Makefile.am
+++ b/src/target/espressif/Makefile.am
@@ -2,21 +2,23 @@
 
 noinst_LTLIBRARIES += %D%/libespressif.la
 %C%_libespressif_la_SOURCES = \
-       %D%/esp_xtensa.c \
-       %D%/esp_xtensa.h \
-       %D%/esp_xtensa_smp.c \
-       %D%/esp_xtensa_smp.h \
-       %D%/esp_xtensa_semihosting.c \
-       %D%/esp_xtensa_semihosting.h \
-       %D%/esp_xtensa_apptrace.c \
-       %D%/esp_xtensa_apptrace.h \
-       %D%/esp32_apptrace.c \
-       %D%/esp32_apptrace.h \
-       %D%/esp32.c \
-       %D%/esp32s2.c \
-       %D%/esp32s3.c \
-       %D%/esp32_sysview.c \
-       %D%/esp32_sysview.h \
-       %D%/segger_sysview.h \
-       %D%/esp_semihosting.c \
-       %D%/esp_semihosting.h
+       %D%/esp_xtensa.c \
+       %D%/esp_xtensa.h \
+       %D%/esp_xtensa_smp.c \
+       %D%/esp_xtensa_smp.h \
+       %D%/esp_xtensa_semihosting.c \
+       %D%/esp_xtensa_semihosting.h \
+       %D%/esp_xtensa_apptrace.c \
+       %D%/esp_xtensa_apptrace.h \
+       %D%/esp32_apptrace.c \
+       %D%/esp32_apptrace.h \
+       %D%/esp32.c \
+       %D%/esp32s2.c \
+       %D%/esp32s3.c \
+       %D%/esp.c \
+       %D%/esp.h \
+       %D%/esp32_sysview.c \
+       %D%/esp32_sysview.h \
+       %D%/segger_sysview.h \
+       %D%/esp_semihosting.c \
+       %D%/esp_semihosting.h
diff --git a/src/target/espressif/esp.c b/src/target/espressif/esp.c
new file mode 100644
index 0000000000..e7257a7bf4
--- /dev/null
+++ b/src/target/espressif/esp.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ *   Espressif chips common target API for OpenOCD                         *
+ *   Copyright (C) 2021 Espressif Systems Ltd.                             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+#include <helper/binarybuffer.h>
+#include "target/target.h"
+#include "esp.h"
+
+int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs 
*dbg_stubs)
+{
+       uint32_t table_size, table_start_id, desc_entry_id, gcov_entry_id;
+       uint32_t entries[ESP_DBG_STUB_ENTRY_MAX];
+       uint8_t entry_buff[sizeof(entries)]; /* to avoid endiannes issues */
+
+       LOG_TARGET_DEBUG(target, "Read debug stubs info %" PRIx32 " / %d", 
dbg_stubs->base, dbg_stubs->entries_count);
+
+       /* First of, read 2 entries to get magic num and table size */
+       int res = target_read_buffer(target, dbg_stubs->base, sizeof(uint32_t) 
* 2, entry_buff);
+       if (res != ERROR_OK) {
+               LOG_ERROR("%s: Failed to read first debug stub entry!", 
target_name(target));
+               return res;
+       }
+       entries[0] = target_buffer_get_u32(target, entry_buff);
+       entries[1] = target_buffer_get_u32(target, entry_buff + 
sizeof(uint32_t));
+
+       if (entries[0] != ESP_DBG_STUB_MAGIC_NUM_VAL) {
+               /* idf with the old table entry structure */
+               table_size = 2;
+               table_start_id = 0;
+               desc_entry_id = 0;
+               gcov_entry_id = 1;
+       } else {
+               table_size = entries[1];
+               table_start_id = ESP_DBG_STUB_TABLE_START;
+               desc_entry_id = ESP_DBG_STUB_TABLE_START;
+               gcov_entry_id = ESP_DBG_STUB_ENTRY_FIRST;
+
+               if (table_size < 2) {
+                       LOG_ERROR("Invalid stub table entry size (%x)", 
table_size);
+                       return ERROR_FAIL;
+               }
+               /* discard unsupported entries */
+               if (table_size > ESP_DBG_STUB_ENTRY_MAX)
+                       table_size = ESP_DBG_STUB_ENTRY_MAX;
+
+               /* now read the remaining entries */
+               res = target_read_buffer(target, dbg_stubs->base + 2 * 
sizeof(uint32_t), sizeof(uint32_t) * table_size - 2,
+                       entry_buff + sizeof(uint32_t) * 2);
+               if (res != ERROR_OK) {
+                       LOG_TARGET_ERROR(target, "Failed to read debug stubs 
info!");
+                       return res;
+               }
+               for (unsigned int i = 2; i < table_size; ++i)
+                       entries[i] = target_buffer_get_u32(target, entry_buff + 
sizeof(uint32_t) * i);
+
+               dbg_stubs->entries[ESP_DBG_STUB_CAPABILITIES] = 
entries[ESP_DBG_STUB_CAPABILITIES];
+       }
+
+       dbg_stubs->entries[ESP_DBG_STUB_DESC] = entries[desc_entry_id];
+       dbg_stubs->entries[ESP_DBG_STUB_ENTRY_GCOV] = entries[gcov_entry_id];
+
+       for (enum esp_dbg_stub_id i = ESP_DBG_STUB_DESC; i < 
ESP_DBG_STUB_ENTRY_MAX; i++) {
+               LOG_DEBUG("Check dbg stub %d - %x", i, dbg_stubs->entries[i]);
+               if (dbg_stubs->entries[i]) {
+                       LOG_DEBUG("New dbg stub %d at %x", 
dbg_stubs->entries_count, dbg_stubs->entries[i]);
+                       dbg_stubs->entries_count++;
+               }
+       }
+       if (dbg_stubs->entries_count < table_size - table_start_id)
+               LOG_WARNING("Not full dbg stub table %d of %d", 
dbg_stubs->entries_count, table_size - table_start_id);
+
+       return ERROR_OK;
+}
diff --git a/src/target/espressif/esp.h b/src/target/espressif/esp.h
new file mode 100644
index 0000000000..3ba2b8bcfa
--- /dev/null
+++ b/src/target/espressif/esp.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ *   Espressif chips common target API for OpenOCD                         *
+ *   Copyright (C) 2021 Espressif Systems Ltd.                             *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_ESP_H
+#define OPENOCD_TARGET_ESP_H
+
+#include <stdint.h>
+#include <helper/bits.h>
+
+/* must be in sync with ESP-IDF version */
+/** Size of the pre-compiled target buffer for stub trampoline.
+ * @note Must be in sync with ESP-IDF version */
+#define ESP_DBG_STUBS_CODE_BUF_SIZE         32 /* TODO: move this info to 
esp_dbg_stubs_desc */
+/** Size of the pre-compiled target buffer for stack.
+ * @note Must be in sync with ESP-IDF version */
+#define ESP_DBG_STUBS_STACK_MIN_SIZE        2048/* TODO: move this info to 
esp_dbg_stubs_desc */
+
+/**
+ * Debug stubs table entries IDs
+ *
+ * @note Must be in sync with ESP-IDF version
+ */
+enum esp_dbg_stub_id {
+       ESP_DBG_STUB_ENTRY_MAGIC_NUM,
+       ESP_DBG_STUB_TABLE_SIZE,
+       ESP_DBG_STUB_TABLE_START,
+       ESP_DBG_STUB_DESC = ESP_DBG_STUB_TABLE_START,   /*< Stubs descriptor ID 
*/
+       ESP_DBG_STUB_ENTRY_FIRST,
+       ESP_DBG_STUB_ENTRY_GCOV = ESP_DBG_STUB_ENTRY_FIRST,     /*< GCOV stub 
ID */
+       ESP_DBG_STUB_CAPABILITIES,
+       /* add new stub entries here */
+       ESP_DBG_STUB_ENTRY_MAX,
+};
+
+#define ESP_DBG_STUB_MAGIC_NUM_VAL      0xFEEDBEEF
+#define ESP_DBG_STUB_CAP_GCOV_THREAD    BIT(0)
+
+/**
+ * Debug stubs descriptor. ID: ESP_DBG_STUB_DESC
+ *
+ * @note Must be in sync with ESP-IDF version
+ */
+struct esp_dbg_stubs_desc {
+       /** Address of pre-compiled target buffer for stub trampoline.
+        * Size of the buffer is ESP_DBG_STUBS_CODE_BUF_SIZE
+        */
+       uint32_t tramp_addr;
+       /** Pre-compiled target buffer's addr for stack. The size of the buffer 
is ESP_DBG_STUBS_STACK_MIN_SIZE.
+        * Target has the buffer which is used for the stack of onboard 
algorithms.
+        * If stack size required by algorithm exceeds 
ESP_DBG_STUBS_STACK_MIN_SIZE,
+        * it should be allocated using onboard function pointed by 
'data_alloc' and
+        * freed by 'data_free'. They fit to the minimal stack. See below.
+        */
+       uint32_t min_stack_addr;
+       /** Address of malloc-like function to allocate buffer on target. */
+       uint32_t data_alloc;
+       /** Address of free-like function to free buffer allocated with 
data_alloc. */
+       uint32_t data_free;
+};
+
+/**
+ * Debug stubs info.
+ */
+struct esp_dbg_stubs {
+       /** Address. */
+       uint32_t base;
+       /** Table contents. */
+       uint32_t entries[ESP_DBG_STUB_ENTRY_MAX];
+       /** Number of table entries. */
+       uint32_t entries_count;
+       /** Debug stubs decsriptor. */
+       struct esp_dbg_stubs_desc desc;
+};
+
+struct esp_common {
+       struct esp_dbg_stubs dbg_stubs;
+};
+
+int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs 
*dbg_stubs);
+
+#endif /* OPENOCD_TARGET_ESP_H */
diff --git a/src/target/espressif/esp_xtensa.c 
b/src/target/espressif/esp_xtensa.c
index 3dfcc0fb2c..72d6c202f6 100644
--- a/src/target/espressif/esp_xtensa.c
+++ b/src/target/espressif/esp_xtensa.c
@@ -17,9 +17,44 @@
 #include "esp_xtensa.h"
 #include "esp_semihosting.h"
 
+#define ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(_e_) \
+       do { \
+               if (!xtensa_data_addr_valid(target, (_e_))) { \
+                       LOG_ERROR("No valid stub data entry found (0x%x)!", 
(uint32_t)(_e_)); \
+                       return; \
+               } \
+       } while (0)
+
+#define ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(_e_) \
+       do { \
+               if ((_e_) == 0) { \
+                       LOG_ERROR("No valid stub code entry found (0x%x)!", 
(uint32_t)(_e_)); \
+                       return; \
+               } \
+       } while (0)
+
+static void esp_xtensa_dbgstubs_info_update(struct target *target);
+static void esp_xtensa_dbgstubs_addr_check(struct target *target);
+
+static int esp_xtensa_dbgstubs_restore(struct target *target)
+{
+       struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
+
+       if (esp_xtensa->esp.dbg_stubs.base == 0)
+               return ERROR_OK;
+
+       LOG_TARGET_INFO(target, "Restore debug stubs address %x", 
esp_xtensa->esp.dbg_stubs.base);
+       int res = esp_xtensa_apptrace_status_reg_write(target, 
esp_xtensa->esp.dbg_stubs.base);
+       if (res != ERROR_OK) {
+               LOG_ERROR("Failed to write trace status (%d)!", res);
+               return res;
+       }
+       return ERROR_OK;
+}
 int esp_xtensa_on_halt(struct target *target)
 {
-       /* will be used in the next patches */
+       /* debug stubs can be used in HALTED state only, so it is OK to get 
info about them here */
+       esp_xtensa_dbgstubs_info_update(target);
        return ERROR_OK;
 }
 
@@ -45,6 +80,11 @@ void esp_xtensa_target_deinit(struct target *target)
 {
        LOG_DEBUG("start");
 
+       if (target_was_examined(target)) {
+               int ret = esp_xtensa_dbgstubs_restore(target);
+               if (ret != ERROR_OK)
+                       return;
+       }
        xtensa_target_deinit(target);
        free(target_to_esp_xtensa(target));     /* same as free(xtensa) */
 }
@@ -56,7 +96,68 @@ int esp_xtensa_arch_state(struct target *target)
 
 int esp_xtensa_poll(struct target *target)
 {
-       return xtensa_poll(target);
+       struct xtensa *xtensa = target_to_xtensa(target);
+       struct esp_xtensa_common *esp_xtensa_common = 
target_to_esp_xtensa(target);
+
+       int ret = xtensa_poll(target);
+
+       if (xtensa_dm_power_status_get(&xtensa->dbg_mod) & 
PWRSTAT_COREWASRESET(xtensa)) {
+               LOG_TARGET_DEBUG(target, "Clear debug stubs info");
+               memset(&esp_xtensa_common->esp.dbg_stubs, 0, 
sizeof(esp_xtensa_common->esp.dbg_stubs));
+       }
+       if (target->state != TARGET_DEBUG_RUNNING)
+               esp_xtensa_dbgstubs_addr_check(target);
+       return ret;
+}
+
+static void esp_xtensa_dbgstubs_addr_check(struct target *target)
+{
+       struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
+       uint32_t vec_addr = 0;
+
+       if (esp_xtensa->esp.dbg_stubs.base != 0)
+               return;
+
+       int res = esp_xtensa_apptrace_status_reg_read(target, &vec_addr);
+       if (res != ERROR_OK) {
+               LOG_ERROR("Failed to read debug stubs address location (%d)!", 
res);
+               return;
+       }
+       if (xtensa_data_addr_valid(target, vec_addr)) {
+               LOG_TARGET_INFO(target, "Detected debug stubs @ %x", vec_addr);
+               res = esp_xtensa_apptrace_status_reg_write(target, 0);
+               if (res != ERROR_OK)
+                       LOG_ERROR("Failed to clear debug stubs address location 
(%d)!", res);
+               esp_xtensa->esp.dbg_stubs.base = vec_addr;
+       }
+}
+
+static void esp_xtensa_dbgstubs_info_update(struct target *target)
+{
+       struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
+
+       if (esp_xtensa->esp.dbg_stubs.base == 0 || 
esp_xtensa->esp.dbg_stubs.entries_count != 0)
+               return;
+
+       int res = esp_dbgstubs_table_read(target, &esp_xtensa->esp.dbg_stubs);
+       if (res != ERROR_OK)
+               return;
+       if (esp_xtensa->esp.dbg_stubs.entries_count == 0)
+               return;
+
+       /* read debug stubs descriptor */
+       
ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(esp_xtensa->esp.dbg_stubs.entries[ESP_DBG_STUB_DESC]);
+       res = target_read_buffer(target, 
esp_xtensa->esp.dbg_stubs.entries[ESP_DBG_STUB_DESC],
+               sizeof(struct esp_dbg_stubs_desc),
+               (uint8_t *)&esp_xtensa->esp.dbg_stubs.desc);
+       if (res != ERROR_OK) {
+               LOG_ERROR("Failed to read debug stubs descriptor (%d)!", res);
+               return;
+       }
+       
ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.tramp_addr);
+       
ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(esp_xtensa->esp.dbg_stubs.desc.min_stack_addr);
+       
ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.data_alloc);
+       
ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.data_free);
 }
 
 int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint 
*breakpoint)
diff --git a/src/target/espressif/esp_xtensa.h 
b/src/target/espressif/esp_xtensa.h
index 0b06b0395c..00f67a3706 100644
--- a/src/target/espressif/esp_xtensa.h
+++ b/src/target/espressif/esp_xtensa.h
@@ -10,12 +10,13 @@
 
 #include <target/target.h>
 #include <target/xtensa/xtensa.h>
-#include "esp_xtensa.h"
 #include "esp_semihosting.h"
+#include "esp.h"
 #include "esp_xtensa_apptrace.h"
 
 struct esp_xtensa_common {
        struct xtensa xtensa;   /* must be the first element */
+       struct esp_common esp;
        struct esp_semihost_data semihost;
        struct esp_xtensa_apptrace_info apptrace;
 };

-- 

Reply via email to