target/smp: use a struct list_head to hold the smp targets

Instead of reinventing a simply linked list, reuse the list helper
for the list of targets in a smp cluster.
Using the existing helper, that implements a double linked list,
makes trivial going through the list in reverse order.

Change-Id: Ib36ad2955f15cd2a601b0b9e36ca6d948b12d00f
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6783
Tested-by: jenkins
This commit is contained in:
Antonio Borneo 2021-12-16 01:59:14 +01:00
parent 5ab74bde06
commit 16cc853bcf
16 changed files with 136 additions and 178 deletions

View File

@ -23,6 +23,7 @@
#include "target/target.h" #include "target/target.h"
#include "target/target_type.h" #include "target/target_type.h"
#include "target/register.h" #include "target/register.h"
#include <target/smp.h>
#include "rtos.h" #include "rtos.h"
#include "helper/log.h" #include "helper/log.h"
#include "helper/types.h" #include "helper/types.h"
@ -107,7 +108,7 @@ static int hwthread_update_threads(struct rtos *rtos)
/* determine the number of "threads" */ /* determine the number of "threads" */
if (target->smp) { if (target->smp) {
for (head = target->head; head; head = head->next) { foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target; struct target *curr = head->target;
if (!target_was_examined(curr)) if (!target_was_examined(curr))
@ -123,7 +124,7 @@ static int hwthread_update_threads(struct rtos *rtos)
if (target->smp) { if (target->smp) {
/* loop over all threads */ /* loop over all threads */
for (head = target->head; head; head = head->next) { foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target; struct target *curr = head->target;
if (!target_was_examined(curr)) if (!target_was_examined(curr))
@ -218,7 +219,8 @@ static struct target *hwthread_find_thread(struct target *target, int64_t thread
if (!target) if (!target)
return NULL; return NULL;
if (target->smp) { if (target->smp) {
for (struct target_list *head = target->head; head; head = head->next) { struct target_list *head;
foreach_smp_target(head, target->smp_targets) {
if (thread_id == threadid_from_target(head->target)) if (thread_id == threadid_from_target(head->target))
return head->target; return head->target;
} }

View File

@ -30,6 +30,7 @@
#include "rtos.h" #include "rtos.h"
#include "rtos_standard_stackings.h" #include "rtos_standard_stackings.h"
#include <target/register.h> #include <target/register.h>
#include <target/smp.h>
#include "server/gdb_server.h" #include "server/gdb_server.h"
#define LINUX_USER_KERNEL_BORDER 0xc0000000 #define LINUX_USER_KERNEL_BORDER 0xc0000000
@ -191,16 +192,14 @@ static int linux_os_thread_reg_list(struct rtos *rtos,
/* search target to perform the access */ /* search target to perform the access */
struct reg **gdb_reg_list; struct reg **gdb_reg_list;
struct target_list *head; struct target_list *head;
head = target->head;
found = 0; found = 0;
do { foreach_smp_target(head, target->smp_targets) {
if (head->target->coreid == next->core_id) { if (head->target->coreid == next->core_id) {
target = head->target; target = head->target;
found = 1; found = 1;
break; break;
} }
head = head->next; }
} while (head);
if (found == 0) { if (found == 0) {
LOG_ERROR LOG_ERROR
@ -397,7 +396,6 @@ static int get_name(struct target *target, struct threads *t)
static int get_current(struct target *target, int create) static int get_current(struct target *target, int create)
{ {
struct target_list *head; struct target_list *head;
head = target->head;
uint8_t *buf; uint8_t *buf;
uint32_t val; uint32_t val;
uint32_t ti_addr; uint32_t ti_addr;
@ -413,7 +411,7 @@ static int get_current(struct target *target, int create)
ctt = ctt->next; ctt = ctt->next;
} }
while (head) { foreach_smp_target(head, target->smp_targets) {
struct reg **reg_list; struct reg **reg_list;
int reg_list_size; int reg_list_size;
int retval; int retval;
@ -474,7 +472,6 @@ static int get_current(struct target *target, int create)
} }
free(reg_list); free(reg_list);
head = head->next;
} }
free(buffer); free(buffer);
@ -1394,9 +1391,8 @@ static int linux_os_smp_init(struct target *target)
struct linux_os *os_linux = struct linux_os *os_linux =
(struct linux_os *)rtos->rtos_specific_params; (struct linux_os *)rtos->rtos_specific_params;
struct current_thread *ct; struct current_thread *ct;
head = target->head;
while (head) { foreach_smp_target(head, target->smp_targets) {
if (head->target->rtos != rtos) { if (head->target->rtos != rtos) {
struct linux_os *smp_os_linux = struct linux_os *smp_os_linux =
(struct linux_os *)head->target->rtos->rtos_specific_params; (struct linux_os *)head->target->rtos->rtos_specific_params;
@ -1413,8 +1409,6 @@ static int linux_os_smp_init(struct target *target)
os_linux->nr_cpus++; os_linux->nr_cpus++;
free(smp_os_linux); free(smp_os_linux);
} }
head = head->next;
} }
return ERROR_OK; return ERROR_OK;

View File

@ -2280,7 +2280,7 @@ static int smp_reg_list_noread(struct target *target,
*combined_list_size = 0; *combined_list_size = 0;
struct target_list *head; struct target_list *head;
foreach_smp_target(head, target->head) { foreach_smp_target(head, target->smp_targets) {
struct reg **reg_list = NULL; struct reg **reg_list = NULL;
int reg_list_size; int reg_list_size;
int result = target_get_gdb_reg_list_noread(head->target, &reg_list, int result = target_get_gdb_reg_list_noread(head->target, &reg_list,
@ -2330,7 +2330,7 @@ static int smp_reg_list_noread(struct target *target,
} }
/* Now warn the user about any registers that weren't found in every target. */ /* Now warn the user about any registers that weren't found in every target. */
foreach_smp_target(head, target->head) { foreach_smp_target(head, target->smp_targets) {
struct reg **reg_list = NULL; struct reg **reg_list = NULL;
int reg_list_size; int reg_list_size;
int result = target_get_gdb_reg_list_noread(head->target, &reg_list, int result = target_get_gdb_reg_list_noread(head->target, &reg_list,
@ -3659,13 +3659,10 @@ static int gdb_target_start(struct target *target, const char *port)
/* initialize all targets gdb service with the same pointer */ /* initialize all targets gdb service with the same pointer */
{ {
struct target_list *head; struct target_list *head;
struct target *curr; foreach_smp_target(head, target->smp_targets) {
head = target->head; struct target *curr = head->target;
while (head) {
curr = head->target;
if (curr != target) if (curr != target)
curr->gdb_service = gdb_service; curr->gdb_service = gdb_service;
head = head->next;
} }
} }
return ret; return ret;

View File

@ -333,15 +333,14 @@ static int aarch64_wait_halt_one(struct target *target)
static int aarch64_prepare_halt_smp(struct target *target, bool exc_target, struct target **p_first) static int aarch64_prepare_halt_smp(struct target *target, bool exc_target, struct target **p_first)
{ {
int retval = ERROR_OK; int retval = ERROR_OK;
struct target_list *head = target->head; struct target_list *head;
struct target *first = NULL; struct target *first = NULL;
LOG_DEBUG("target %s exc %i", target_name(target), exc_target); LOG_DEBUG("target %s exc %i", target_name(target), exc_target);
while (head) { foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target; struct target *curr = head->target;
struct armv8_common *armv8 = target_to_armv8(curr); struct armv8_common *armv8 = target_to_armv8(curr);
head = head->next;
if (exc_target && curr == target) if (exc_target && curr == target)
continue; continue;
@ -430,7 +429,7 @@ static int aarch64_halt_smp(struct target *target, bool exc_target)
struct target_list *head; struct target_list *head;
struct target *curr; struct target *curr;
foreach_smp_target(head, target->head) { foreach_smp_target(head, target->smp_targets) {
int halted; int halted;
curr = head->target; curr = head->target;
@ -480,7 +479,7 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug
} }
/* poll all targets in the group, but skip the target that serves GDB */ /* poll all targets in the group, but skip the target that serves GDB */
foreach_smp_target(head, target->head) { foreach_smp_target(head, target->smp_targets) {
curr = head->target; curr = head->target;
/* skip calling context */ /* skip calling context */
if (curr == target) if (curr == target)
@ -745,7 +744,7 @@ static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoint
struct target *first = NULL; struct target *first = NULL;
uint64_t address; uint64_t address;
foreach_smp_target(head, target->head) { foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target; struct target *curr = head->target;
/* skip calling target */ /* skip calling target */
@ -800,7 +799,7 @@ static int aarch64_step_restart_smp(struct target *target)
struct target *curr = target; struct target *curr = target;
bool all_resumed = true; bool all_resumed = true;
foreach_smp_target(head, target->head) { foreach_smp_target(head, target->smp_targets) {
uint32_t prsr; uint32_t prsr;
int resumed; int resumed;
@ -888,7 +887,7 @@ static int aarch64_resume(struct target *target, int current,
struct target_list *head; struct target_list *head;
bool all_resumed = true; bool all_resumed = true;
foreach_smp_target(head, target->head) { foreach_smp_target(head, target->smp_targets) {
uint32_t prsr; uint32_t prsr;
int resumed; int resumed;

View File

@ -38,6 +38,7 @@
#include "arm_opcodes.h" #include "arm_opcodes.h"
#include "target.h" #include "target.h"
#include "target_type.h" #include "target_type.h"
#include "smp.h"
static void armv7a_show_fault_registers(struct target *target) static void armv7a_show_fault_registers(struct target *target)
{ {
@ -193,8 +194,7 @@ done:
static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way) static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
{ {
struct armv7a_l2x_cache *l2x_cache; struct armv7a_l2x_cache *l2x_cache;
struct target_list *head = target->head; struct target_list *head;
struct target *curr;
struct armv7a_common *armv7a = target_to_armv7a(target); struct armv7a_common *armv7a = target_to_armv7a(target);
l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache)); l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache));
@ -207,15 +207,14 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
/* initialize all target in this cluster (smp target) /* initialize all target in this cluster (smp target)
* l2 cache must be configured after smp declaration */ * l2 cache must be configured after smp declaration */
while (head) { foreach_smp_target(head, target->smp_targets) {
curr = head->target; struct target *curr = head->target;
if (curr != target) { if (curr != target) {
armv7a = target_to_armv7a(curr); armv7a = target_to_armv7a(curr);
if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) if (armv7a->armv7a_mmu.armv7a_cache.outer_cache)
LOG_ERROR("smp target : outer cache already initialized\n"); LOG_ERROR("smp target : outer cache already initialized\n");
armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
} }
head = head->next;
} }
return JIM_OK; return JIM_OK;
} }

View File

@ -26,6 +26,7 @@
#include "armv7a_cache.h" #include "armv7a_cache.h"
#include <helper/time_support.h> #include <helper/time_support.h>
#include "arm_opcodes.h" #include "arm_opcodes.h"
#include "smp.h"
static int armv7a_l1_d_cache_sanity_check(struct target *target) static int armv7a_l1_d_cache_sanity_check(struct target *target)
{ {
@ -138,14 +139,10 @@ int armv7a_cache_auto_flush_all_data(struct target *target)
if (target->smp) { if (target->smp) {
struct target_list *head; struct target_list *head;
struct target *curr; foreach_smp_target(head, target->smp_targets) {
head = target->head; struct target *curr = head->target;
while (head) {
curr = head->target;
if (curr->state == TARGET_HALTED) if (curr->state == TARGET_HALTED)
retval = armv7a_l1_d_cache_clean_inval_all(curr); retval = armv7a_l1_d_cache_clean_inval_all(curr);
head = head->next;
} }
} else } else
retval = armv7a_l1_d_cache_clean_inval_all(target); retval = armv7a_l1_d_cache_clean_inval_all(target);

View File

@ -27,6 +27,7 @@
#include <helper/time_support.h> #include <helper/time_support.h>
#include "target.h" #include "target.h"
#include "target_type.h" #include "target_type.h"
#include "smp.h"
static int arm7a_l2x_sanity_check(struct target *target) static int arm7a_l2x_sanity_check(struct target *target)
{ {
@ -194,8 +195,7 @@ static int arm7a_handle_l2x_cache_info_command(struct command_invocation *cmd,
static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way) static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
{ {
struct armv7a_l2x_cache *l2x_cache; struct armv7a_l2x_cache *l2x_cache;
struct target_list *head = target->head; struct target_list *head;
struct target *curr;
struct armv7a_common *armv7a = target_to_armv7a(target); struct armv7a_common *armv7a = target_to_armv7a(target);
if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) { if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) {
@ -210,8 +210,8 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
/* initialize all targets in this cluster (smp target) /* initialize all targets in this cluster (smp target)
* l2 cache must be configured after smp declaration */ * l2 cache must be configured after smp declaration */
while (head) { foreach_smp_target(head, target->smp_targets) {
curr = head->target; struct target *curr = head->target;
if (curr != target) { if (curr != target) {
armv7a = target_to_armv7a(curr); armv7a = target_to_armv7a(curr);
if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) { if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) {
@ -220,7 +220,6 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
} }
armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
} }
head = head->next;
} }
return ERROR_OK; return ERROR_OK;
} }

View File

@ -23,6 +23,7 @@
#include "armv8_cache.h" #include "armv8_cache.h"
#include "armv8_dpm.h" #include "armv8_dpm.h"
#include "armv8_opcodes.h" #include "armv8_opcodes.h"
#include "smp.h"
/* CLIDR cache types */ /* CLIDR cache types */
#define CACHE_LEVEL_HAS_UNIFIED_CACHE 0x4 #define CACHE_LEVEL_HAS_UNIFIED_CACHE 0x4
@ -250,15 +251,12 @@ static int armv8_flush_all_data(struct target *target)
/* look if all the other target have been flushed in order to flush level /* look if all the other target have been flushed in order to flush level
* 2 */ * 2 */
struct target_list *head; struct target_list *head;
struct target *curr; foreach_smp_target(head, target->smp_targets) {
head = target->head; struct target *curr = head->target;
while (head) {
curr = head->target;
if (curr->state == TARGET_HALTED) { if (curr->state == TARGET_HALTED) {
LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid); LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid);
retval = _armv8_flush_all_data(curr); retval = _armv8_flush_all_data(curr);
} }
head = head->next;
} }
} else } else
retval = _armv8_flush_all_data(target); retval = _armv8_flush_all_data(target);

View File

@ -26,6 +26,7 @@
#include "target.h" #include "target.h"
#include <helper/log.h> #include <helper/log.h>
#include "breakpoints.h" #include "breakpoints.h"
#include "smp.h"
static const char * const breakpoint_type_strings[] = { static const char * const breakpoint_type_strings[] = {
"hardware", "hardware",
@ -216,22 +217,22 @@ int breakpoint_add(struct target *target,
uint32_t length, uint32_t length,
enum breakpoint_type type) enum breakpoint_type type)
{ {
int retval = ERROR_OK;
if (target->smp) { if (target->smp) {
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head;
if (type == BKPT_SOFT)
return breakpoint_add_internal(head->target, address, length, type);
while (head) { if (type == BKPT_SOFT) {
curr = head->target; head = list_first_entry(target->smp_targets, struct target_list, lh);
retval = breakpoint_add_internal(curr, address, length, type); 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) if (retval != ERROR_OK)
return retval; return retval;
head = head->next;
} }
return retval;
return ERROR_OK;
} else { } else {
return breakpoint_add_internal(target, address, length, type); return breakpoint_add_internal(target, address, length, type);
} }
@ -242,19 +243,17 @@ int context_breakpoint_add(struct target *target,
uint32_t length, uint32_t length,
enum breakpoint_type type) enum breakpoint_type type)
{ {
int retval = ERROR_OK;
if (target->smp) { if (target->smp) {
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target; int retval = context_breakpoint_add_internal(curr, asid, length, type);
retval = context_breakpoint_add_internal(curr, asid, length, type);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
head = head->next;
} }
return retval;
return ERROR_OK;
} else { } else {
return context_breakpoint_add_internal(target, asid, length, type); return context_breakpoint_add_internal(target, asid, length, type);
} }
@ -266,19 +265,17 @@ int hybrid_breakpoint_add(struct target *target,
uint32_t length, uint32_t length,
enum breakpoint_type type) enum breakpoint_type type)
{ {
int retval = ERROR_OK;
if (target->smp) { if (target->smp) {
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target; int retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
head = head->next;
} }
return retval;
return ERROR_OK;
} else } else
return hybrid_breakpoint_add_internal(target, address, asid, length, type); return hybrid_breakpoint_add_internal(target, address, asid, length, type);
} }
@ -345,12 +342,10 @@ void breakpoint_remove(struct target *target, target_addr_t address)
if (target->smp) { if (target->smp) {
unsigned int num_breakpoints = 0; unsigned int num_breakpoints = 0;
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target;
num_breakpoints += breakpoint_remove_internal(curr, address); num_breakpoints += breakpoint_remove_internal(curr, address);
head = head->next;
} }
if (!num_breakpoints) if (!num_breakpoints)
LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address); LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address);
@ -363,12 +358,10 @@ void breakpoint_remove_all(struct target *target)
{ {
if (target->smp) { if (target->smp) {
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target;
breakpoint_remove_all_internal(curr); breakpoint_remove_all_internal(curr);
head = head->next;
} }
} else { } else {
breakpoint_remove_all_internal(target); breakpoint_remove_all_internal(target);
@ -387,12 +380,10 @@ void breakpoint_clear_target(struct target *target)
{ {
if (target->smp) { if (target->smp) {
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target;
breakpoint_clear_target_internal(curr); breakpoint_clear_target_internal(curr);
head = head->next;
} }
} else { } else {
breakpoint_clear_target_internal(target); breakpoint_clear_target_internal(target);
@ -482,21 +473,17 @@ bye:
int watchpoint_add(struct target *target, target_addr_t address, int watchpoint_add(struct target *target, target_addr_t address,
uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
{ {
int retval = ERROR_OK;
if (target->smp) { if (target->smp) {
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head;
while (head != (struct target_list *)NULL) { foreach_smp_target(head, target->smp_targets) {
curr = head->target; struct target *curr = head->target;
retval = watchpoint_add_internal(curr, address, length, rw, value, int retval = watchpoint_add_internal(curr, address, length, rw, value, mask);
mask);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
head = head->next;
} }
return retval;
return ERROR_OK;
} else { } else {
return watchpoint_add_internal(target, address, length, rw, value, return watchpoint_add_internal(target, address, length, rw, value,
mask); mask);
@ -549,12 +536,10 @@ void watchpoint_remove(struct target *target, target_addr_t address)
if (target->smp) { if (target->smp) {
unsigned int num_watchpoints = 0; unsigned int num_watchpoints = 0;
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target;
num_watchpoints += watchpoint_remove_internal(curr, address); num_watchpoints += watchpoint_remove_internal(curr, address);
head = head->next;
} }
if (num_watchpoints == 0) if (num_watchpoints == 0)
LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address); LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address);

View File

@ -639,14 +639,11 @@ static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
static struct target *get_cortex_a(struct target *target, int32_t coreid) static struct target *get_cortex_a(struct target *target, int32_t coreid)
{ {
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target;
if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
return curr; return curr;
head = head->next;
} }
return target; return target;
} }
@ -656,14 +653,12 @@ static int cortex_a_halt_smp(struct target *target)
{ {
int retval = 0; int retval = 0;
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target;
if ((curr != target) && (curr->state != TARGET_HALTED) if ((curr != target) && (curr->state != TARGET_HALTED)
&& target_was_examined(curr)) && target_was_examined(curr))
retval += cortex_a_halt(curr); retval += cortex_a_halt(curr);
head = head->next;
} }
return retval; return retval;
} }
@ -684,7 +679,7 @@ static int update_halt_gdb(struct target *target)
if (target->gdb_service) if (target->gdb_service)
gdb_target = target->gdb_service->target; gdb_target = target->gdb_service->target;
foreach_smp_target(head, target->head) { foreach_smp_target(head, target->smp_targets) {
curr = head->target; curr = head->target;
/* skip calling context */ /* skip calling context */
if (curr == target) if (curr == target)
@ -951,11 +946,10 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints)
{ {
int retval = 0; int retval = 0;
struct target_list *head; struct target_list *head;
struct target *curr;
target_addr_t address; target_addr_t address;
head = target->head;
while (head) { foreach_smp_target(head, target->smp_targets) {
curr = head->target; struct target *curr = head->target;
if ((curr != target) && (curr->state != TARGET_RUNNING) if ((curr != target) && (curr->state != TARGET_RUNNING)
&& target_was_examined(curr)) { && target_was_examined(curr)) {
/* resume current address , not in step mode */ /* resume current address , not in step mode */
@ -963,8 +957,6 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints)
handle_breakpoints, 0); handle_breakpoints, 0);
retval += cortex_a_internal_restart(curr); retval += cortex_a_internal_restart(curr);
} }
head = head->next;
} }
return retval; return retval;
} }

View File

@ -128,14 +128,11 @@ static int mips_m4k_debug_entry(struct target *target)
static struct target *get_mips_m4k(struct target *target, int32_t coreid) static struct target *get_mips_m4k(struct target *target, int32_t coreid)
{ {
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) { struct target *curr = head->target;
curr = head->target;
if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
return curr; return curr;
head = head->next;
} }
return target; return target;
} }
@ -144,11 +141,10 @@ static int mips_m4k_halt_smp(struct target *target)
{ {
int retval = ERROR_OK; int retval = ERROR_OK;
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) {
int ret = ERROR_OK; int ret = ERROR_OK;
curr = head->target; struct target *curr = head->target;
if ((curr != target) && (curr->state != TARGET_HALTED)) if ((curr != target) && (curr->state != TARGET_HALTED))
ret = mips_m4k_halt(curr); ret = mips_m4k_halt(curr);
@ -156,7 +152,6 @@ static int mips_m4k_halt_smp(struct target *target)
LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid); LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid);
retval = ret; retval = ret;
} }
head = head->next;
} }
return retval; return retval;
} }
@ -414,12 +409,10 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han
{ {
int retval = ERROR_OK; int retval = ERROR_OK;
struct target_list *head; struct target_list *head;
struct target *curr;
head = target->head; foreach_smp_target(head, target->smp_targets) {
while (head) {
int ret = ERROR_OK; int ret = ERROR_OK;
curr = head->target; struct target *curr = head->target;
if ((curr != target) && (curr->state != TARGET_RUNNING)) { if ((curr != target) && (curr->state != TARGET_RUNNING)) {
/* resume current address , not in step mode */ /* resume current address , not in step mode */
ret = mips_m4k_internal_restore(curr, 1, address, ret = mips_m4k_internal_restore(curr, 1, address,
@ -431,7 +424,6 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han
retval = ret; retval = ret;
} }
} }
head = head->next;
} }
return retval; return retval;
} }

View File

@ -13,6 +13,7 @@
#include "target/target.h" #include "target/target.h"
#include "target/algorithm.h" #include "target/algorithm.h"
#include "target/target_type.h" #include "target/target_type.h"
#include <target/smp.h>
#include "jtag/jtag.h" #include "jtag/jtag.h"
#include "target/register.h" #include "target/register.h"
#include "target/breakpoints.h" #include "target/breakpoints.h"
@ -1232,13 +1233,14 @@ int riscv_halt(struct target *target)
int result = ERROR_OK; int result = ERROR_OK;
if (target->smp) { if (target->smp) {
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { struct target_list *tlist;
foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target; struct target *t = tlist->target;
if (halt_prep(t) != ERROR_OK) if (halt_prep(t) != ERROR_OK)
result = ERROR_FAIL; result = ERROR_FAIL;
} }
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target; struct target *t = tlist->target;
riscv_info_t *i = riscv_info(t); riscv_info_t *i = riscv_info(t);
if (i->prepped) { if (i->prepped) {
@ -1247,7 +1249,7 @@ int riscv_halt(struct target *target)
} }
} }
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target; struct target *t = tlist->target;
if (halt_finish(t) != ERROR_OK) if (halt_finish(t) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
@ -1469,14 +1471,15 @@ int riscv_resume(
LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints); LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints);
int result = ERROR_OK; int result = ERROR_OK;
if (target->smp && !single_hart) { if (target->smp && !single_hart) {
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { struct target_list *tlist;
foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target; struct target *t = tlist->target;
if (resume_prep(t, current, address, handle_breakpoints, if (resume_prep(t, current, address, handle_breakpoints,
debug_execution) != ERROR_OK) debug_execution) != ERROR_OK)
result = ERROR_FAIL; result = ERROR_FAIL;
} }
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target; struct target *t = tlist->target;
riscv_info_t *i = riscv_info(t); riscv_info_t *i = riscv_info(t);
if (i->prepped) { if (i->prepped) {
@ -1486,7 +1489,7 @@ int riscv_resume(
} }
} }
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target; struct target *t = tlist->target;
if (resume_finish(t) != ERROR_OK) if (resume_finish(t) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
@ -2180,9 +2183,8 @@ int riscv_openocd_poll(struct target *target)
unsigned halts_discovered = 0; unsigned halts_discovered = 0;
unsigned should_remain_halted = 0; unsigned should_remain_halted = 0;
unsigned should_resume = 0; unsigned should_resume = 0;
unsigned i = 0; struct target_list *list;
for (struct target_list *list = target->head; list; foreach_smp_target(list, target->smp_targets) {
list = list->next, i++) {
struct target *t = list->target; struct target *t = list->target;
riscv_info_t *r = riscv_info(t); riscv_info_t *r = riscv_info(t);
enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid); enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid);
@ -2242,8 +2244,7 @@ int riscv_openocd_poll(struct target *target)
} }
/* Sample memory if any target is running. */ /* Sample memory if any target is running. */
for (struct target_list *list = target->head; list; foreach_smp_target(list, target->smp_targets) {
list = list->next, i++) {
struct target *t = list->target; struct target *t = list->target;
if (t->state == TARGET_RUNNING) { if (t->state == TARGET_RUNNING) {
sample_memory(target); sample_memory(target);

View File

@ -111,18 +111,18 @@ COMMAND_HANDLER(default_handle_smp_command)
} }
if (!strcmp(CMD_ARGV[0], "on")) { if (!strcmp(CMD_ARGV[0], "on")) {
foreach_smp_target(head, target->head) foreach_smp_target(head, target->smp_targets)
head->target->smp = 1; head->target->smp = 1;
return ERROR_OK; return ERROR_OK;
} }
if (!strcmp(CMD_ARGV[0], "off")) { if (!strcmp(CMD_ARGV[0], "off")) {
foreach_smp_target(head, target->head) foreach_smp_target(head, target->smp_targets)
head->target->smp = 0; head->target->smp = 0;
/* fixes the target display to the debugger */ /* fixes the target display to the debugger */
if (target->head) if (!list_empty(target->smp_targets))
target->gdb_service->target = target; target->gdb_service->target = target;
return ERROR_OK; return ERROR_OK;
@ -135,9 +135,7 @@ COMMAND_HANDLER(handle_smp_gdb_command)
{ {
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
int retval = ERROR_OK; int retval = ERROR_OK;
struct target_list *head; if (!list_empty(target->smp_targets)) {
head = target->head;
if (head) {
if (CMD_ARGC == 1) { if (CMD_ARGC == 1) {
int coreid = 0; int coreid = 0;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);

View File

@ -19,10 +19,11 @@
#ifndef OPENOCD_TARGET_SMP_H #ifndef OPENOCD_TARGET_SMP_H
#define OPENOCD_TARGET_SMP_H #define OPENOCD_TARGET_SMP_H
#include <helper/list.h>
#include "server/server.h" #include "server/server.h"
#define foreach_smp_target(pos, head) \ #define foreach_smp_target(pos, head) \
for (pos = head; (pos); pos = pos->next) list_for_each_entry(pos, head, lh)
extern const struct command_registration smp_command_handlers[]; extern const struct command_registration smp_command_handlers[];

View File

@ -56,6 +56,7 @@
#include "rtos/rtos.h" #include "rtos/rtos.h"
#include "transport/transport.h" #include "transport/transport.h"
#include "arm_cti.h" #include "arm_cti.h"
#include "smp.h"
/* default halt wait timeout (ms) */ /* default halt wait timeout (ms) */
#define DEFAULT_HALT_TIMEOUT 5000 #define DEFAULT_HALT_TIMEOUT 5000
@ -159,6 +160,7 @@ static int64_t target_timer_next_event_value;
static LIST_HEAD(target_reset_callback_list); static LIST_HEAD(target_reset_callback_list);
static LIST_HEAD(target_trace_callback_list); static LIST_HEAD(target_trace_callback_list);
static const int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL; static const int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL;
static LIST_HEAD(empty_smp_targets);
static const struct jim_nvp nvp_assert[] = { static const struct jim_nvp nvp_assert[] = {
{ .name = "assert", NVP_ASSERT }, { .name = "assert", NVP_ASSERT },
@ -2272,13 +2274,15 @@ static void target_destroy(struct target *target)
/* release the targets SMP list */ /* release the targets SMP list */
if (target->smp) { if (target->smp) {
struct target_list *head = target->head; struct target_list *head, *tmp;
while (head) {
struct target_list *pos = head->next; list_for_each_entry_safe(head, tmp, target->smp_targets, lh) {
list_del(&head->lh);
head->target->smp = 0; head->target->smp = 0;
free(head); free(head);
head = pos;
} }
if (target->smp_targets != &empty_smp_targets)
free(target->smp_targets);
target->smp = 0; target->smp = 0;
} }
@ -5786,6 +5790,9 @@ static int target_create(struct jim_getopt_info *goi)
return JIM_ERR; return JIM_ERR;
} }
/* set empty smp cluster */
target->smp_targets = &empty_smp_targets;
/* set target number */ /* set target number */
target->target_number = new_target_number(); target->target_number = new_target_number();
@ -5998,9 +6005,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
const char *targetname; const char *targetname;
int retval, len; int retval, len;
struct target *target = NULL; struct target *target = NULL;
struct target_list *head, *curr, *new; struct target_list *head, *new;
curr = NULL;
head = NULL;
retval = 0; retval = 0;
LOG_DEBUG("%d", argc); LOG_DEBUG("%d", argc);
@ -6009,6 +6014,13 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
* argv[3] ... * argv[3] ...
*/ */
struct list_head *lh = malloc(sizeof(*lh));
if (!lh) {
LOG_ERROR("Out of memory");
return JIM_ERR;
}
INIT_LIST_HEAD(lh);
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
targetname = Jim_GetString(argv[i], &len); targetname = Jim_GetString(argv[i], &len);
@ -6017,24 +6029,14 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (target) { if (target) {
new = malloc(sizeof(struct target_list)); new = malloc(sizeof(struct target_list));
new->target = target; new->target = target;
new->next = NULL; list_add_tail(&new->lh, lh);
if (!head) {
head = new;
curr = head;
} else {
curr->next = new;
curr = new;
}
} }
} }
/* now parse the list of cpu and put the target in smp mode*/ /* now parse the list of cpu and put the target in smp mode*/
curr = head; foreach_smp_target(head, lh) {
target = head->target;
while (curr) {
target = curr->target;
target->smp = 1; target->smp = 1;
target->head = head; target->smp_targets = lh;
curr = curr->next;
} }
if (target && target->rtos) if (target && target->rtos)

View File

@ -201,7 +201,9 @@ struct target {
* and must be detected when symbols are offered */ * and must be detected when symbols are offered */
struct backoff_timer backoff; struct backoff_timer backoff;
int smp; /* add some target attributes for smp support */ int smp; /* add some target attributes for smp support */
struct target_list *head; struct list_head *smp_targets; /* list all targets in this smp group/cluster
* The head of the list is shared between the
* cluster, thus here there is a pointer */
/* the gdb service is there in case of smp, we have only one gdb server /* the gdb service is there in case of smp, we have only one gdb server
* for all smp target * for all smp target
* the target attached to the gdb is changing dynamically by changing * the target attached to the gdb is changing dynamically by changing
@ -220,8 +222,8 @@ struct target {
}; };
struct target_list { struct target_list {
struct list_head lh;
struct target *target; struct target *target;
struct target_list *next;
}; };
struct gdb_fileio_info { struct gdb_fileio_info {