+
+ while (breakpoint) {
+ if ((breakpoint->asid == asid) && (breakpoint->address == address)) {
+ /* FIXME don't assume "same address" means "same
+ * breakpoint" ... check all the parameters before
+ * succeeding.
+ */
+ LOG_TARGET_ERROR(target, "Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
+ asid, breakpoint->unique_id);
+ return ERROR_TARGET_DUPLICATE_BREAKPOINT;
+ } else if ((breakpoint->address == address) && (breakpoint->asid == 0)) {
+ LOG_TARGET_ERROR(target, "Duplicate Breakpoint IVA: " TARGET_ADDR_FMT " (BP %" PRIu32 ")",
+ address, breakpoint->unique_id);
+ return ERROR_TARGET_DUPLICATE_BREAKPOINT;
+
+ }
+ breakpoint_p = &breakpoint->next;
+ breakpoint = breakpoint->next;
+ }
+ (*breakpoint_p) = malloc(sizeof(struct breakpoint));
+ (*breakpoint_p)->address = address;
+ (*breakpoint_p)->asid = asid;
+ (*breakpoint_p)->length = length;
+ (*breakpoint_p)->type = type;
+ (*breakpoint_p)->is_set = false;
+ (*breakpoint_p)->orig_instr = malloc(length);
+ (*breakpoint_p)->next = NULL;
+ (*breakpoint_p)->unique_id = bpwp_unique_id++;
+
+
+ retval = target_add_hybrid_breakpoint(target, *breakpoint_p);
+ if (retval != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "could not add breakpoint");
+ free((*breakpoint_p)->orig_instr);
+ free(*breakpoint_p);
+ *breakpoint_p = NULL;
+ return retval;
+ }
+ LOG_TARGET_DEBUG(target,
+ "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")",
+ breakpoint_type_strings[(*breakpoint_p)->type],
+ (*breakpoint_p)->address,
+ (*breakpoint_p)->length,
+ (*breakpoint_p)->unique_id);
+
+ return ERROR_OK;
+}
+
+int breakpoint_add(struct target *target,
+ target_addr_t address,
+ uint32_t length,
+ enum breakpoint_type type)
+{
+ if (target->smp) {
+ struct target_list *head;
+
+ if (type == BKPT_SOFT) {
+ head = list_first_entry(target->smp_targets, struct target_list, lh);
+ return breakpoint_add_internal(head->target, 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;
+ }
+
+ return ERROR_OK;
+ } else {
+ return breakpoint_add_internal(target, address, length, type);
+ }
+}
+
+int context_breakpoint_add(struct target *target,
+ uint32_t asid,
+ uint32_t length,
+ enum breakpoint_type type)
+{
+ if (target->smp) {
+ struct target_list *head;
+
+ 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;
+ }
+
+ return ERROR_OK;
+ } else {
+ return context_breakpoint_add_internal(target, asid, length, type);
+ }
+}
+
+int hybrid_breakpoint_add(struct target *target,
+ target_addr_t address,
+ uint32_t asid,
+ uint32_t length,
+ enum breakpoint_type type)
+{
+ if (target->smp) {
+ struct target_list *head;
+
+ 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;
+ }
+
+ return ERROR_OK;
+ } else
+ return hybrid_breakpoint_add_internal(target, address, asid, length, type);
+}
+
+/* free up a breakpoint */
+static int breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove)
+{
+ struct breakpoint *breakpoint = target->breakpoints;
+ struct breakpoint **breakpoint_p = &target->breakpoints;
+ int retval;
+
+ while (breakpoint) {
+ if (breakpoint == breakpoint_to_remove)