This is an automated email from Gerrit.

"Tomas Vanek <van...@fbl.cz>" just uploaded a new patch set to Gerrit, which 
you can find at https://review.openocd.org/c/openocd/+/7239

-- gerrit

commit 91434a191d593f9806af4824d0cfa7ea31bc2c04
Author: Tomas Vanek <van...@fbl.cz>
Date:   Sat Oct 1 17:10:31 2022 +0200

    target/cortex_m: add SMP support for Cortex-M
    
    Cortex-M support for SMP multicore targets.
    
    Obsolete gdb 'J' packet/smp_gdb command core switching is not implemented,
    use with rtos hwthread.
    
    Only one core is resumed if debug_execution is requested.
    
    Some ideas taken from Graham Sanderson's [4936]
    and src/target/aarch64.c
    
    Added error checking of armv7m_restore_context().
    
    Change-Id: I60f5b79e74b624dc2b5835ff10e38ac2ccb23792
    Link: [4936]: target/cortex_m: Add smp support for Cortex M | 
https://review.openocd.org/c/openocd/+/4936
    Signed-off-by: Tomas Vanek <van...@fbl.cz>

diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 23d9065e2a..018b8ff765 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -28,6 +28,7 @@
 #include "register.h"
 #include "arm_opcodes.h"
 #include "arm_semihosting.h"
+#include "smp.h"
 #include <helper/time_support.h>
 #include <rtt/rtt.h>
 
@@ -871,7 +872,57 @@ static int cortex_m_debug_entry(struct target *target)
        return ERROR_OK;
 }
 
-static int cortex_m_poll(struct target *target)
+static int cortex_m_halt_one(struct target *target);
+
+static int cortex_m_smp_halt_all(struct target *target, struct target *exclude)
+{
+       int retval = ERROR_OK;
+       struct target_list *head;
+       struct target *curr;
+
+       foreach_smp_target(head, target->smp_targets) {
+               curr = head->target;
+               if (curr == exclude)
+                       continue;
+               if (!target_was_examined(curr))
+                       continue;
+               if (curr->state == TARGET_HALTED)
+                       continue;
+
+               int ret2 = cortex_m_halt_one(curr);
+               if (retval == ERROR_OK)
+                       retval = ret2;  /* store the first error code ignore 
others */
+       }
+       return retval;
+}
+
+static int cortex_m_poll_smp(struct target *target, bool is_smp);
+
+static int cortex_m_smp_post_halt_poll(struct target *target)
+{
+       int retval = ERROR_OK;
+       struct target_list *head;
+       struct target *curr;
+
+       foreach_smp_target(head, target->smp_targets) {
+               curr = head->target;
+               /* skip calling target */
+               if (curr == target)
+                       continue;
+               if (!target_was_examined(curr))
+                       continue;
+               /* skip targets that were already halted */
+               if (curr->state == TARGET_HALTED)
+                       continue;
+
+               int ret2 = cortex_m_poll_smp(curr, false);
+               if (retval == ERROR_OK)
+                       retval = ret2;  /* store the first error code ignore 
others */
+       }
+       return retval;
+}
+
+static int cortex_m_poll_smp(struct target *target, bool is_smp)
 {
        int detected_failure = ERROR_OK;
        int retval = ERROR_OK;
@@ -944,21 +995,33 @@ static int cortex_m_poll(struct target *target)
 
                if ((prev_target_state == TARGET_RUNNING) || (prev_target_state 
== TARGET_RESET)) {
                        retval = cortex_m_debug_entry(target);
-                       if (retval != ERROR_OK)
-                               return retval;
 
-                       if (arm_semihosting(target, &retval) != 0)
+                       /* arm_semihosting needs to know registers, don't run 
if debug entry returned error */
+                       if (retval == ERROR_OK && arm_semihosting(target, 
&retval) != 0)
                                return retval;
 
+                       if (is_smp) {
+                               if (target->gdb_service)
+                                       target->gdb_service->target = target;
+
+                               int ret2 = cortex_m_smp_halt_all(target, 
target);
+                               if (retval == ERROR_OK)
+                                       retval = ret2;  /* store the first 
error code ignore others */
+
+                               ret2 = cortex_m_smp_post_halt_poll(target);
+                               if (retval == ERROR_OK)
+                                       retval = ret2;  /* store the first 
error code ignore others */
+                       }
+                       /* regardles of errors returned in previous code update 
state */
                        target_call_event_callbacks(target, 
TARGET_EVENT_HALTED);
                }
                if (prev_target_state == TARGET_DEBUG_RUNNING) {
                        retval = cortex_m_debug_entry(target);
-                       if (retval != ERROR_OK)
-                               return retval;
 
                        target_call_event_callbacks(target, 
TARGET_EVENT_DEBUG_HALTED);
                }
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        if (target->state == TARGET_UNKNOWN) {
@@ -991,7 +1054,12 @@ static int cortex_m_poll(struct target *target)
        return retval;
 }
 
-static int cortex_m_halt(struct target *target)
+static int cortex_m_poll(struct target *target)
+{
+       return cortex_m_poll_smp(target, target->smp != 0);
+}
+
+static int cortex_m_halt_one(struct target *target)
 {
        LOG_TARGET_DEBUG(target, "target->state: %s", 
target_state_name(target));
 
@@ -1029,6 +1097,14 @@ static int cortex_m_halt(struct target *target)
        return ERROR_OK;
 }
 
+static int cortex_m_halt(struct target *target)
+{
+       if (target->smp)
+               return cortex_m_smp_halt_all(target, NULL);
+       else
+               return cortex_m_halt_one(target);
+}
+
 static int cortex_m_soft_reset_halt(struct target *target)
 {
        struct cortex_m_common *cortex_m = target_to_cm(target);
@@ -1106,8 +1182,8 @@ void cortex_m_enable_breakpoints(struct target *target)
        }
 }
 
-static int cortex_m_resume(struct target *target, int current,
-       target_addr_t address, int handle_breakpoints, int debug_execution)
+static int cortex_m_restore_one(struct target *target, bool current,
+       target_addr_t *address, bool handle_breakpoints, bool debug_execution)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
        struct breakpoint *breakpoint = NULL;
@@ -1115,7 +1191,7 @@ static int cortex_m_resume(struct target *target, int 
current,
        struct reg *r;
 
        if (target->state != TARGET_HALTED) {
-               LOG_TARGET_WARNING(target, "target not halted");
+               LOG_TARGET_ERROR(target, "target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1157,7 +1233,7 @@ static int cortex_m_resume(struct target *target, int 
current,
        /* current = 1: continue on current pc, otherwise continue at <address> 
*/
        r = armv7m->arm.pc;
        if (!current) {
-               buf_set_u32(r->value, 0, 32, address);
+               buf_set_u32(r->value, 0, 32, *address);
                r->dirty = true;
                r->valid = true;
        }
@@ -1171,8 +1247,12 @@ static int cortex_m_resume(struct target *target, int 
current,
                armv7m_maybe_skip_bkpt_inst(target, NULL);
 
        resume_pc = buf_get_u32(r->value, 0, 32);
+       if (current)
+               *address = resume_pc;
 
-       armv7m_restore_context(target);
+       int retval = armv7m_restore_context(target);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* the front-end may request us not to handle breakpoints */
        if (handle_breakpoints) {
@@ -1182,34 +1262,100 @@ static int cortex_m_resume(struct target *target, int 
current,
                        LOG_TARGET_DEBUG(target, "unset breakpoint at " 
TARGET_ADDR_FMT " (ID: %" PRIu32 ")",
                                breakpoint->address,
                                breakpoint->unique_id);
-                       cortex_m_unset_breakpoint(target, breakpoint);
-                       cortex_m_single_step_core(target);
-                       cortex_m_set_breakpoint(target, breakpoint);
+                       retval = cortex_m_unset_breakpoint(target, breakpoint);
+                       if (retval == ERROR_OK)
+                               retval = cortex_m_single_step_core(target);
+                       int ret2 = cortex_m_set_breakpoint(target, breakpoint);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       if (ret2 != ERROR_OK)
+                               return ret2;
                }
        }
 
+       return ERROR_OK;
+}
+
+static int cortex_m_restart_one(struct target *target, bool debug_execution)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+
        /* Restart core */
        cortex_m_set_maskints_for_run(target);
        cortex_m_write_debug_halt_mask(target, 0, C_HALT);
 
        target->debug_reason = DBG_REASON_NOTHALTED;
-
        /* registers are now invalid */
        register_cache_invalidate(armv7m->arm.core_cache);
 
        if (!debug_execution) {
                target->state = TARGET_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-               LOG_TARGET_DEBUG(target, "target resumed at 0x%" PRIx32 "", 
resume_pc);
        } else {
                target->state = TARGET_DEBUG_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
-               LOG_TARGET_DEBUG(target, "target debug resumed at 0x%" PRIx32 
"", resume_pc);
        }
 
        return ERROR_OK;
 }
 
+static int cortex_m_restore_smp(struct target *target, bool handle_breakpoints)
+{
+       struct target_list *head;
+       struct target *curr;
+       target_addr_t address;
+       foreach_smp_target(head, target->smp_targets) {
+               curr = head->target;
+               /* skip calling target */
+               if (curr == target)
+                       continue;
+               if (!target_was_examined(curr))
+                       continue;
+               /* skip running targets */
+               if (curr->state == TARGET_RUNNING)
+                       continue;
+
+               int retval = cortex_m_restore_one(curr, 1, &address,
+                                                                               
handle_breakpoints, 0);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = cortex_m_restart_one(curr, 0);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               LOG_TARGET_DEBUG(curr, "SMP resumed at " TARGET_ADDR_FMT, 
address);
+       }
+       return ERROR_OK;
+}
+
+static int cortex_m_resume(struct target *target, int current,
+                                                  target_addr_t address, int 
handle_breakpoints, int debug_execution)
+{
+       int retval = cortex_m_restore_one(target, !!current, &address, 
!!handle_breakpoints, !!debug_execution);
+       if (retval != ERROR_OK) {
+               LOG_TARGET_ERROR(target, "context restore failed, aborting 
resume");
+               return retval;
+       }
+
+       if (target->smp && !debug_execution) {
+               retval = cortex_m_restore_smp(target, !!handle_breakpoints);
+               if (retval != ERROR_OK)
+                       LOG_WARNING("resume of a SMP target failed, trying to 
resume current one");
+       }
+
+       cortex_m_restart_one(target, !!debug_execution);
+       if (retval != ERROR_OK) {
+               LOG_TARGET_ERROR(target, "resume failed");
+               return retval;
+       }
+
+       LOG_TARGET_DEBUG(target, "%sresumed at " TARGET_ADDR_FMT,
+                                       debug_execution ? "debug " : "", 
address);
+
+       return ERROR_OK;
+}
+
 /* int irqstepcount = 0; */
 static int cortex_m_step(struct target *target, int current,
        target_addr_t address, int handle_breakpoints)
@@ -1227,6 +1373,11 @@ static int cortex_m_step(struct target *target, int 
current,
                return ERROR_TARGET_NOT_HALTED;
        }
 
+       /* Just one of SMP cores will step. Set the gdb control
+        * target to current one or gdb miss gdb-end event */
+       if (target->smp && target->gdb_service)
+               target->gdb_service->target = target;
+
        /* current = 1: continue on current pc, otherwise continue at <address> 
*/
        if (!current) {
                buf_set_u32(pc->value, 0, 32, address);
@@ -2829,6 +2980,9 @@ static const struct command_registration 
cortex_m_exec_command_handlers[] = {
                .help = "configure software reset handling",
                .usage = "['sysresetreq'|'vectreset']",
        },
+       {
+               .chain = smp_command_handlers,
+       },
        COMMAND_REGISTRATION_DONE
 };
 static const struct command_registration cortex_m_command_handlers[] = {

-- 

Reply via email to