target/esp_xtensa: add xtensa on_halt handler
[openocd.git] / src / target / espressif / esp_xtensa_smp.c
index 6060662475d64976b4e2f0d1d36936f610fa707a..93c53f15b79efd7bd1b63ba6cf2ae9603bcfed01 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+// SPDX-License-Identifier: GPL-2.0-or-later
 
 /***************************************************************************
  *   ESP Xtensa SMP target API for OpenOCD                                 *
@@ -13,7 +13,9 @@
 #include <target/target.h>
 #include <target/target_type.h>
 #include <target/smp.h>
+#include <target/semihosting_common.h>
 #include "esp_xtensa_smp.h"
+#include "esp_xtensa_semihosting.h"
 
 /*
 Multiprocessor stuff common:
@@ -110,6 +112,21 @@ int esp_xtensa_smp_soft_reset_halt(struct target *target)
        return ERROR_OK;
 }
 
+int esp_xtensa_smp_on_halt(struct target *target)
+{
+       struct target_list *head;
+
+       if (!target->smp)
+               return esp_xtensa_on_halt(target);
+
+       foreach_smp_target(head, target->smp_targets) {
+               int res = esp_xtensa_on_halt(head->target);
+               if (res != ERROR_OK)
+                       return res;
+       }
+       return ERROR_OK;
+}
+
 static struct target *get_halted_esp_xtensa_smp(struct target *target, int32_t coreid)
 {
        struct target_list *head;
@@ -128,6 +145,7 @@ int esp_xtensa_smp_poll(struct target *target)
 {
        enum target_state old_state = target->state;
        struct esp_xtensa_smp_common *esp_xtensa_smp = target_to_esp_xtensa_smp(target);
+       struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
        struct target_list *head;
        struct target *curr;
        bool other_core_resume_req = false;
@@ -180,6 +198,19 @@ int esp_xtensa_smp_poll(struct target *target)
                if (old_state == TARGET_DEBUG_RUNNING) {
                        target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
                } else {
+                       if (esp_xtensa_semihosting(target, &ret) == SEMIHOSTING_HANDLED) {
+                               if (ret == ERROR_OK && esp_xtensa->semihost.need_resume &&
+                                       !esp_xtensa_smp->other_core_does_resume) {
+                                       esp_xtensa->semihost.need_resume = false;
+                                       /* Resume xtensa_resume will handle BREAK instruction. */
+                                       ret = target_resume(target, 1, 0, 1, 0);
+                                       if (ret != ERROR_OK) {
+                                               LOG_ERROR("Failed to resume target");
+                                               return ret;
+                                       }
+                               }
+                               return ret;
+                       }
                        /* check whether any core polled by esp_xtensa_smp_update_halt_gdb() requested resume */
                        if (target->smp && other_core_resume_req) {
                                /* Resume xtensa_resume will handle BREAK instruction. */
@@ -253,6 +284,11 @@ static int esp_xtensa_smp_update_halt_gdb(struct target *target, bool *need_resu
                if (ret != ERROR_OK)
                        return ret;
                esp_xtensa_smp->other_core_does_resume = false;
+               struct esp_xtensa_common *curr_esp_xtensa = target_to_esp_xtensa(curr);
+               if (curr_esp_xtensa->semihost.need_resume) {
+                       curr_esp_xtensa->semihost.need_resume = false;
+                       *need_resume = true;
+               }
        }
 
        /* after all targets were updated, poll the gdb serving target */
@@ -450,11 +486,11 @@ int esp_xtensa_smp_watchpoint_remove(struct target *target, struct watchpoint *w
 
 int esp_xtensa_smp_init_arch_info(struct target *target,
        struct esp_xtensa_smp_common *esp_xtensa_smp,
-       const struct xtensa_config *xtensa_cfg,
        struct xtensa_debug_module_config *dm_cfg,
-       const struct esp_xtensa_smp_chip_ops *chip_ops)
+       const struct esp_xtensa_smp_chip_ops *chip_ops,
+       const struct esp_semihost_ops *semihost_ops)
 {
-       int ret = esp_xtensa_init_arch_info(target, &esp_xtensa_smp->esp_xtensa, xtensa_cfg, dm_cfg);
+       int ret = esp_xtensa_init_arch_info(target, &esp_xtensa_smp->esp_xtensa, dm_cfg, semihost_ops);
        if (ret != ERROR_OK)
                return ret;
        esp_xtensa_smp->chip_ops = chip_ops;
@@ -464,7 +500,157 @@ int esp_xtensa_smp_init_arch_info(struct target *target,
 
 int esp_xtensa_smp_target_init(struct command_context *cmd_ctx, struct target *target)
 {
-       return esp_xtensa_target_init(cmd_ctx, target);
+       int ret = esp_xtensa_target_init(cmd_ctx, target);
+       if (ret != ERROR_OK)
+               return ret;
+
+       if (target->smp) {
+               struct target_list *head;
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       ret = esp_xtensa_semihosting_init(curr);
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+       } else {
+               ret = esp_xtensa_semihosting_init(target);
+               if (ret != ERROR_OK)
+                       return ret;
+       }
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(esp_xtensa_smp_cmd_xtdef)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       if (target->smp && CMD_ARGC > 0) {
+               struct target_list *head;
+               struct target *curr;
+               foreach_smp_target(head, target->smp_targets) {
+                       curr = head->target;
+                       int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtdef_do,
+                               target_to_xtensa(curr));
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+               return ERROR_OK;
+       }
+       return CALL_COMMAND_HANDLER(xtensa_cmd_xtdef_do,
+               target_to_xtensa(target));
+}
+
+COMMAND_HANDLER(esp_xtensa_smp_cmd_xtopt)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       if (target->smp && CMD_ARGC > 0) {
+               struct target_list *head;
+               struct target *curr;
+               foreach_smp_target(head, target->smp_targets) {
+                       curr = head->target;
+                       int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtopt_do,
+                               target_to_xtensa(curr));
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+               return ERROR_OK;
+       }
+       return CALL_COMMAND_HANDLER(xtensa_cmd_xtopt_do,
+               target_to_xtensa(target));
+}
+
+COMMAND_HANDLER(esp_xtensa_smp_cmd_xtmem)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       if (target->smp && CMD_ARGC > 0) {
+               struct target_list *head;
+               struct target *curr;
+               foreach_smp_target(head, target->smp_targets) {
+                       curr = head->target;
+                       int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtmem_do,
+                               target_to_xtensa(curr));
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+               return ERROR_OK;
+       }
+       return CALL_COMMAND_HANDLER(xtensa_cmd_xtmem_do,
+               target_to_xtensa(target));
+}
+
+COMMAND_HANDLER(esp_xtensa_smp_cmd_xtmpu)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       if (target->smp && CMD_ARGC > 0) {
+               struct target_list *head;
+               struct target *curr;
+               foreach_smp_target(head, target->smp_targets) {
+                       curr = head->target;
+                       int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtmpu_do,
+                               target_to_xtensa(curr));
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+               return ERROR_OK;
+       }
+       return CALL_COMMAND_HANDLER(xtensa_cmd_xtmpu_do,
+               target_to_xtensa(target));
+}
+
+COMMAND_HANDLER(esp_xtensa_smp_cmd_xtmmu)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       if (target->smp && CMD_ARGC > 0) {
+               struct target_list *head;
+               struct target *curr;
+               foreach_smp_target(head, target->smp_targets) {
+                       curr = head->target;
+                       int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtmmu_do,
+                               target_to_xtensa(curr));
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+               return ERROR_OK;
+       }
+       return CALL_COMMAND_HANDLER(xtensa_cmd_xtmmu_do,
+               target_to_xtensa(target));
+}
+
+COMMAND_HANDLER(esp_xtensa_smp_cmd_xtreg)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       if (target->smp && CMD_ARGC > 0) {
+               struct target_list *head;
+               struct target *curr;
+               foreach_smp_target(head, target->smp_targets) {
+                       curr = head->target;
+                       int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtreg_do,
+                               target_to_xtensa(curr));
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+               return ERROR_OK;
+       }
+       return CALL_COMMAND_HANDLER(xtensa_cmd_xtreg_do,
+               target_to_xtensa(target));
+}
+
+COMMAND_HANDLER(esp_xtensa_smp_cmd_xtregfmt)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       if (target->smp && CMD_ARGC > 0) {
+               struct target_list *head;
+               struct target *curr;
+               foreach_smp_target(head, target->smp_targets) {
+                       curr = head->target;
+                       int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtregfmt_do,
+                               target_to_xtensa(curr));
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+               return ERROR_OK;
+       }
+       return CALL_COMMAND_HANDLER(xtensa_cmd_xtregfmt_do,
+               target_to_xtensa(target));
 }
 
 COMMAND_HANDLER(esp_xtensa_smp_cmd_permissive_mode)
@@ -632,6 +818,62 @@ COMMAND_HANDLER(esp_xtensa_smp_cmd_tracedump)
 }
 
 const struct command_registration esp_xtensa_smp_xtensa_command_handlers[] = {
+       {
+               .name = "xtdef",
+               .handler = esp_xtensa_smp_cmd_xtdef,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure Xtensa core type",
+               .usage = "<type>",
+       },
+       {
+               .name = "xtopt",
+               .handler = esp_xtensa_smp_cmd_xtopt,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure Xtensa core option",
+               .usage = "<name> <value>",
+       },
+       {
+               .name = "xtmem",
+               .handler = esp_xtensa_smp_cmd_xtmem,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure Xtensa memory/cache option",
+               .usage = "<type> [parameters]",
+       },
+       {
+               .name = "xtmmu",
+               .handler = esp_xtensa_smp_cmd_xtmmu,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure Xtensa MMU option",
+               .usage = "<NIREFILLENTRIES> <NDREFILLENTRIES> <IVARWAY56> <DVARWAY56>",
+       },
+       {
+               .name = "xtmpu",
+               .handler = esp_xtensa_smp_cmd_xtmpu,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure Xtensa MPU option",
+               .usage = "<num FG seg> <min seg size> <lockable> <executeonly>",
+       },
+       {
+               .name = "xtreg",
+               .handler = esp_xtensa_smp_cmd_xtreg,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure Xtensa register",
+               .usage = "<regname> <regnum>",
+       },
+       {
+               .name = "xtregs",
+               .handler = esp_xtensa_smp_cmd_xtreg,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure number of Xtensa registers",
+               .usage = "<numregs>",
+       },
+       {
+               .name = "xtregfmt",
+               .handler = esp_xtensa_smp_cmd_xtregfmt,
+               .mode = COMMAND_CONFIG,
+               .help = "Configure format of Xtensa register map",
+               .usage = "<numgregs>",
+       },
        {
                .name = "set_permissive",
                .handler = esp_xtensa_smp_cmd_permissive_mode,

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)