openocd: src/target: replace the GPL-2.0-or-later license tag
[fw/openocd] / src / target / breakpoints.c
index c060c7cde7d577ef94f74c8f0a30d9c72db9a3af..b03136786390b7b2925e05701d4e7e502e2e9c93 100644 (file)
@@ -1,22 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
  *   Copyright (C) ST-Ericsson SA 2011                                     *
  *   michel.jaouen@stericsson.com : smp minimum support                    *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -26,6 +15,7 @@
 #include "target.h"
 #include <helper/log.h>
 #include "breakpoints.h"
+#include "smp.h"
 
 static const char * const breakpoint_type_strings[] = {
        "hardware",
@@ -50,11 +40,8 @@ static int breakpoint_add_internal(struct target *target,
        struct breakpoint **breakpoint_p = &target->breakpoints;
        const char *reason;
        int retval;
-       int n;
 
-       n = 0;
        while (breakpoint) {
-               n++;
                if (breakpoint->address == address) {
                        /* FIXME don't assume "same address" means "same
                         * breakpoint" ... check all the parameters before
@@ -73,7 +60,7 @@ static int breakpoint_add_internal(struct target *target,
        (*breakpoint_p)->asid = 0;
        (*breakpoint_p)->length = length;
        (*breakpoint_p)->type = type;
-       (*breakpoint_p)->set = 0;
+       (*breakpoint_p)->is_set = false;
        (*breakpoint_p)->orig_instr = malloc(length);
        (*breakpoint_p)->next = NULL;
        (*breakpoint_p)->unique_id = bpwp_unique_id++;
@@ -98,7 +85,9 @@ fail:
                        return retval;
        }
 
-       LOG_DEBUG("added %s breakpoint at " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")",
+       LOG_DEBUG("[%d] added %s breakpoint at " TARGET_ADDR_FMT
+                       " of length 0x%8.8x, (BPID: %" PRIu32 ")",
+               target->coreid,
                breakpoint_type_strings[(*breakpoint_p)->type],
                (*breakpoint_p)->address, (*breakpoint_p)->length,
                (*breakpoint_p)->unique_id);
@@ -114,11 +103,8 @@ static int context_breakpoint_add_internal(struct target *target,
        struct breakpoint *breakpoint = target->breakpoints;
        struct breakpoint **breakpoint_p = &target->breakpoints;
        int retval;
-       int n;
 
-       n = 0;
        while (breakpoint) {
-               n++;
                if (breakpoint->asid == asid) {
                        /* FIXME don't assume "same address" means "same
                         * breakpoint" ... check all the parameters before
@@ -137,7 +123,7 @@ static int context_breakpoint_add_internal(struct target *target,
        (*breakpoint_p)->asid = asid;
        (*breakpoint_p)->length = length;
        (*breakpoint_p)->type = type;
-       (*breakpoint_p)->set = 0;
+       (*breakpoint_p)->is_set = false;
        (*breakpoint_p)->orig_instr = malloc(length);
        (*breakpoint_p)->next = NULL;
        (*breakpoint_p)->unique_id = bpwp_unique_id++;
@@ -167,10 +153,8 @@ static int hybrid_breakpoint_add_internal(struct target *target,
        struct breakpoint *breakpoint = target->breakpoints;
        struct breakpoint **breakpoint_p = &target->breakpoints;
        int retval;
-       int n;
-       n = 0;
+
        while (breakpoint) {
-               n++;
                if ((breakpoint->asid == asid) && (breakpoint->address == address)) {
                        /* FIXME don't assume "same address" means "same
                         * breakpoint" ... check all the parameters before
@@ -193,7 +177,7 @@ static int hybrid_breakpoint_add_internal(struct target *target,
        (*breakpoint_p)->asid = asid;
        (*breakpoint_p)->length = length;
        (*breakpoint_p)->type = type;
-       (*breakpoint_p)->set = 0;
+       (*breakpoint_p)->is_set = false;
        (*breakpoint_p)->orig_instr = malloc(length);
        (*breakpoint_p)->next = NULL;
        (*breakpoint_p)->unique_id = bpwp_unique_id++;
@@ -222,24 +206,25 @@ int breakpoint_add(struct target *target,
        uint32_t length,
        enum breakpoint_type type)
 {
-       int retval = ERROR_OK;
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               if (type == BKPT_SOFT)
+
+               if (type == BKPT_SOFT) {
+                       head = list_first_entry(target->smp_targets, struct target_list, lh);
                        return breakpoint_add_internal(head->target, address, length, type);
+               }
 
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       retval = breakpoint_add_internal(curr, address, length, type);
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       int retval = breakpoint_add_internal(curr, address, length, type);
                        if (retval != ERROR_OK)
                                return retval;
-                       head = head->next;
                }
-               return retval;
-       } else
+
+               return ERROR_OK;
+       } else {
                return breakpoint_add_internal(target, address, length, type);
+       }
 }
 
 int context_breakpoint_add(struct target *target,
@@ -247,21 +232,20 @@ int context_breakpoint_add(struct target *target,
        uint32_t length,
        enum breakpoint_type type)
 {
-       int retval = ERROR_OK;
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       retval = context_breakpoint_add_internal(curr, asid, length, type);
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       int retval = context_breakpoint_add_internal(curr, asid, length, type);
                        if (retval != ERROR_OK)
                                return retval;
-                       head = head->next;
                }
-               return retval;
-       } else
+
+               return ERROR_OK;
+       } else {
                return context_breakpoint_add_internal(target, asid, length, type);
+       }
 }
 
 int hybrid_breakpoint_add(struct target *target,
@@ -270,19 +254,17 @@ int hybrid_breakpoint_add(struct target *target,
        uint32_t length,
        enum breakpoint_type type)
 {
-       int retval = ERROR_OK;
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       int retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
                        if (retval != ERROR_OK)
                                return retval;
-                       head = head->next;
                }
-               return retval;
+
+               return ERROR_OK;
        } else
                return hybrid_breakpoint_add_internal(target, address, asid, length, type);
 }
@@ -301,7 +283,7 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint
                breakpoint = breakpoint->next;
        }
 
-       if (breakpoint == NULL)
+       if (!breakpoint)
                return;
 
        retval = target_remove_breakpoint(target, breakpoint);
@@ -346,32 +328,29 @@ static void breakpoint_remove_all_internal(struct target *target)
 
 void breakpoint_remove(struct target *target, target_addr_t address)
 {
-       int found = 0;
        if (target->smp) {
+               unsigned int num_breakpoints = 0;
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       found += breakpoint_remove_internal(curr, address);
-                       head = head->next;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       num_breakpoints += breakpoint_remove_internal(curr, address);
                }
-               if (found == 0)
+               if (!num_breakpoints)
                        LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address);
-       } else
+       } else {
                breakpoint_remove_internal(target, address);
+       }
 }
 
 void breakpoint_remove_all(struct target *target)
 {
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
                        breakpoint_remove_all_internal(curr);
-                       head = head->next;
                }
        } else {
                breakpoint_remove_all_internal(target);
@@ -382,7 +361,7 @@ static void breakpoint_clear_target_internal(struct target *target)
 {
        LOG_DEBUG("Delete all breakpoints for target: %s",
                target_name(target));
-       while (target->breakpoints != NULL)
+       while (target->breakpoints)
                breakpoint_free(target, target->breakpoints);
 }
 
@@ -390,16 +369,14 @@ void breakpoint_clear_target(struct target *target)
 {
        if (target->smp) {
                struct target_list *head;
-               struct target *curr;
-               head = target->head;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
                        breakpoint_clear_target_internal(curr);
-                       head = head->next;
                }
-       } else
+       } else {
                breakpoint_clear_target_internal(target);
-
+       }
 }
 
 struct breakpoint *breakpoint_find(struct target *target, target_addr_t address)
@@ -415,8 +392,8 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address)
        return NULL;
 }
 
-int watchpoint_add(struct target *target, target_addr_t address, uint32_t length,
-       enum watchpoint_rw rw, uint32_t value, uint32_t mask)
+int watchpoint_add_internal(struct target *target, target_addr_t address,
+               uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
 {
        struct watchpoint *watchpoint = target->watchpoints;
        struct watchpoint **watchpoint_p = &target->watchpoints;
@@ -471,8 +448,9 @@ bye:
                        return retval;
        }
 
-       LOG_DEBUG("added %s watchpoint at " TARGET_ADDR_FMT
-               " of length 0x%8.8" PRIx32 " (WPID: %d)",
+       LOG_DEBUG("[%d] added %s watchpoint at " TARGET_ADDR_FMT
+                       " of length 0x%8.8" PRIx32 " (WPID: %d)",
+               target->coreid,
                watchpoint_rw_strings[(*watchpoint_p)->rw],
                (*watchpoint_p)->address,
                (*watchpoint_p)->length,
@@ -481,6 +459,26 @@ bye:
        return ERROR_OK;
 }
 
+int watchpoint_add(struct target *target, target_addr_t address,
+               uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
+{
+       if (target->smp) {
+               struct target_list *head;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       int retval = watchpoint_add_internal(curr, address, length, rw, value, mask);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+
+               return ERROR_OK;
+       } else {
+               return watchpoint_add_internal(target, address, length, rw, value,
+                               mask);
+       }
+}
+
 static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
 {
        struct watchpoint *watchpoint = target->watchpoints;
@@ -494,7 +492,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint
                watchpoint = watchpoint->next;
        }
 
-       if (watchpoint == NULL)
+       if (!watchpoint)
                return;
        retval = target_remove_watchpoint(target, watchpoint);
        LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
@@ -502,7 +500,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint
        free(watchpoint);
 }
 
-void watchpoint_remove(struct target *target, target_addr_t address)
+int watchpoint_remove_internal(struct target *target, target_addr_t address)
 {
        struct watchpoint *watchpoint = target->watchpoints;
 
@@ -512,17 +510,38 @@ void watchpoint_remove(struct target *target, target_addr_t address)
                watchpoint = watchpoint->next;
        }
 
-       if (watchpoint)
+       if (watchpoint) {
                watchpoint_free(target, watchpoint);
-       else
-               LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address);
+               return 1;
+       } else {
+               if (!target->smp)
+                       LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address);
+               return 0;
+       }
+}
+
+void watchpoint_remove(struct target *target, target_addr_t address)
+{
+       if (target->smp) {
+               unsigned int num_watchpoints = 0;
+               struct target_list *head;
+
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       num_watchpoints += watchpoint_remove_internal(curr, address);
+               }
+               if (num_watchpoints == 0)
+                       LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address);
+       } else {
+               watchpoint_remove_internal(target, address);
+       }
 }
 
 void watchpoint_clear_target(struct target *target)
 {
        LOG_DEBUG("Delete all watchpoints for target: %s",
                target_name(target));
-       while (target->watchpoints != NULL)
+       while (target->watchpoints)
                watchpoint_free(target, target->watchpoints);
 }