smp : infra for smp minimum support
parent
36d60ee6c8
commit
b778b36f29
|
@ -11,6 +11,9 @@
|
||||||
* Copyright (C) 2011 by Broadcom Corporation *
|
* Copyright (C) 2011 by Broadcom Corporation *
|
||||||
* Evan Hunter - ehunter@broadcom.com *
|
* Evan Hunter - ehunter@broadcom.com *
|
||||||
* *
|
* *
|
||||||
|
* 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 *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
@ -39,6 +42,7 @@
|
||||||
#include <target/image.h>
|
#include <target/image.h>
|
||||||
#include <jtag/jtag.h>
|
#include <jtag/jtag.h>
|
||||||
#include "rtos/rtos.h"
|
#include "rtos/rtos.h"
|
||||||
|
#include "target/smp.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,7 +66,7 @@ struct gdb_connection
|
||||||
int closed;
|
int closed;
|
||||||
int busy;
|
int busy;
|
||||||
int noack_mode;
|
int noack_mode;
|
||||||
bool sync; /* set flag to true if you want the next stepi to return immediately.
|
bool sync; /* set flag to true if you want the next stepi to return immediately.
|
||||||
allowing GDB to pick up a fresh set of register values from the target
|
allowing GDB to pick up a fresh set of register values from the target
|
||||||
without modifying the target state. */
|
without modifying the target state. */
|
||||||
/* We delay reporting memory write errors until next step/continue or memory
|
/* We delay reporting memory write errors until next step/continue or memory
|
||||||
|
@ -2360,6 +2364,24 @@ static int gdb_input_inner(struct connection *connection)
|
||||||
"ocd_gdb_restart %s",
|
"ocd_gdb_restart %s",
|
||||||
target_name(target));
|
target_name(target));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'j':
|
||||||
|
/* packet supported only by smp target i.e cortex_a.c*/
|
||||||
|
/* handle smp packet replying coreid played to gbd */
|
||||||
|
gdb_read_smp_packet(
|
||||||
|
connection, target,
|
||||||
|
packet, packet_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'J':
|
||||||
|
/* packet supported only by smp target i.e cortex_a.c */
|
||||||
|
/* handle smp packet setting coreid to be played at next
|
||||||
|
* resume to gdb */
|
||||||
|
gdb_write_smp_packet(
|
||||||
|
connection, target,
|
||||||
|
packet, packet_size);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* ignore unknown packets */
|
/* ignore unknown packets */
|
||||||
LOG_DEBUG("ignoring 0x%2.2x packet", packet[0]);
|
LOG_DEBUG("ignoring 0x%2.2x packet", packet[0]);
|
||||||
|
@ -2411,21 +2433,43 @@ static int gdb_input(struct connection *connection)
|
||||||
|
|
||||||
static int gdb_target_start(struct target *target, const char *port)
|
static int gdb_target_start(struct target *target, const char *port)
|
||||||
{
|
{
|
||||||
struct gdb_service *gdb_service = malloc(sizeof(struct gdb_service));
|
|
||||||
|
struct gdb_service *gdb_service;
|
||||||
|
int ret;
|
||||||
|
gdb_service = malloc(sizeof(struct gdb_service));
|
||||||
|
|
||||||
if (NULL == gdb_service)
|
if (NULL == gdb_service)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
gdb_service->target = target;
|
gdb_service->target = target;
|
||||||
|
gdb_service->core[0] = -1;
|
||||||
|
gdb_service->core[1] = -1;
|
||||||
|
target->gdb_service = gdb_service;
|
||||||
|
|
||||||
return add_service("gdb",
|
ret = add_service("gdb",
|
||||||
port, 1, &gdb_new_connection, &gdb_input,
|
port, 1, &gdb_new_connection, &gdb_input,
|
||||||
&gdb_connection_closed, gdb_service);
|
&gdb_connection_closed, gdb_service);
|
||||||
|
/* initialialize all targets gdb service with the same pointer */
|
||||||
|
{
|
||||||
|
struct target_list *head;
|
||||||
|
struct target *curr;
|
||||||
|
head = target->head;
|
||||||
|
while(head != (struct target_list*)NULL)
|
||||||
|
{
|
||||||
|
curr = head->target;
|
||||||
|
if (curr != target) curr->gdb_service = gdb_service;
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gdb_target_add_one(struct target *target)
|
static int gdb_target_add_one(struct target *target)
|
||||||
{
|
{
|
||||||
|
/* one gdb instance per smp list */
|
||||||
|
if ((target->smp) && (target->gdb_service)) return ERROR_OK;
|
||||||
int retval = gdb_target_start(target, gdb_port_next);
|
int retval = gdb_target_start(target, gdb_port_next);
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
{
|
{
|
||||||
long portnumber;
|
long portnumber;
|
||||||
/* If we can parse the port number
|
/* If we can parse the port number
|
||||||
|
|
|
@ -30,15 +30,11 @@
|
||||||
#define GDB_SERVER_H
|
#define GDB_SERVER_H
|
||||||
|
|
||||||
struct image;
|
struct image;
|
||||||
|
struct reg;
|
||||||
#include <target/target.h>
|
#include <target/target.h>
|
||||||
|
|
||||||
#define GDB_BUFFER_SIZE 16384
|
#define GDB_BUFFER_SIZE 16384
|
||||||
|
|
||||||
struct gdb_service
|
|
||||||
{
|
|
||||||
struct target *target;
|
|
||||||
};
|
|
||||||
|
|
||||||
int gdb_target_add_all(struct target *target);
|
int gdb_target_add_all(struct target *target);
|
||||||
int gdb_register_commands(struct command_context *command_context);
|
int gdb_register_commands(struct command_context *command_context);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ TARGET_CORE_SRC = \
|
||||||
breakpoints.c \
|
breakpoints.c \
|
||||||
target.c \
|
target.c \
|
||||||
target_request.c \
|
target_request.c \
|
||||||
testee.c
|
testee.c \
|
||||||
|
smp.c
|
||||||
|
|
||||||
ARMV4_5_SRC = \
|
ARMV4_5_SRC = \
|
||||||
armv4_5.c \
|
armv4_5.c \
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
* Copyright (C) 2005 by Dominic Rath *
|
* Copyright (C) 2005 by Dominic Rath *
|
||||||
* Dominic.Rath@gmx.de *
|
* 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 *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
@ -42,10 +45,11 @@ static char *watchpoint_rw_strings[] =
|
||||||
// monotonic counter/id-number for breakpoints and watch points
|
// monotonic counter/id-number for breakpoints and watch points
|
||||||
static int bpwp_unique_id;
|
static int bpwp_unique_id;
|
||||||
|
|
||||||
int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
|
int breakpoint_add_internal(struct target *target, uint32_t address, uint32_t length, enum breakpoint_type type)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
struct breakpoint **breakpoint_p = &target->breakpoints;
|
struct breakpoint **breakpoint_p = &target->breakpoints;
|
||||||
|
char *reason;
|
||||||
int retval;
|
int retval;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
@ -76,9 +80,19 @@ int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enu
|
||||||
(*breakpoint_p)->unique_id = bpwp_unique_id++;
|
(*breakpoint_p)->unique_id = bpwp_unique_id++;
|
||||||
|
|
||||||
retval = target_add_breakpoint(target, *breakpoint_p);
|
retval = target_add_breakpoint(target, *breakpoint_p);
|
||||||
if (retval != ERROR_OK)
|
switch (retval) {
|
||||||
{
|
case ERROR_OK:
|
||||||
LOG_ERROR("could not add breakpoint");
|
break;
|
||||||
|
case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
|
||||||
|
reason = "resource not available";
|
||||||
|
goto fail;
|
||||||
|
case ERROR_TARGET_NOT_HALTED:
|
||||||
|
reason = "target running";
|
||||||
|
goto fail;
|
||||||
|
default:
|
||||||
|
reason = "unknown reason";
|
||||||
|
fail:
|
||||||
|
LOG_ERROR("can't add breakpoint: %s", reason);
|
||||||
free((*breakpoint_p)->orig_instr);
|
free((*breakpoint_p)->orig_instr);
|
||||||
free(*breakpoint_p);
|
free(*breakpoint_p);
|
||||||
*breakpoint_p = NULL;
|
*breakpoint_p = NULL;
|
||||||
|
@ -93,6 +107,29 @@ int breakpoint_add(struct target *target, uint32_t address, uint32_t length, enu
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int breakpoint_add(struct target *target, uint32_t address, 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 = breakpoint_add_internal(curr, address,length, type);
|
||||||
|
if (retval != ERROR_OK) return retval;
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return(breakpoint_add_internal(target, address, length, type));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* free up a breakpoint */
|
/* free up a breakpoint */
|
||||||
static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove)
|
static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove)
|
||||||
{
|
{
|
||||||
|
@ -119,7 +156,7 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint
|
||||||
free(breakpoint);
|
free(breakpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void breakpoint_remove(struct target *target, uint32_t address)
|
void breakpoint_remove_internal(struct target *target, uint32_t address)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
struct breakpoint **breakpoint_p = &target->breakpoints;
|
struct breakpoint **breakpoint_p = &target->breakpoints;
|
||||||
|
@ -141,8 +178,24 @@ void breakpoint_remove(struct target *target, uint32_t address)
|
||||||
LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
|
LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void breakpoint_remove(struct target *target, uint32_t address)
|
||||||
|
{
|
||||||
|
if ((target->smp))
|
||||||
|
{
|
||||||
|
struct target_list *head;
|
||||||
|
struct target *curr;
|
||||||
|
head = target->head;
|
||||||
|
while(head != (struct target_list*)NULL)
|
||||||
|
{
|
||||||
|
curr = head->target;
|
||||||
|
breakpoint_remove_internal(curr, address);
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else breakpoint_remove_internal(target, address);
|
||||||
|
}
|
||||||
|
|
||||||
void breakpoint_clear_target(struct target *target)
|
void breakpoint_clear_target_internal(struct target *target)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint;
|
struct breakpoint *breakpoint;
|
||||||
|
|
||||||
|
@ -154,6 +207,25 @@ void breakpoint_clear_target(struct target *target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
breakpoint_clear_target_internal(curr);
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else breakpoint_clear_target_internal(target);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
|
struct breakpoint* breakpoint_find(struct target *target, uint32_t address)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
|
@ -174,6 +246,7 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
struct watchpoint **watchpoint_p = &target->watchpoints;
|
struct watchpoint **watchpoint_p = &target->watchpoints;
|
||||||
int retval;
|
int retval;
|
||||||
|
char *reason;
|
||||||
|
|
||||||
while (watchpoint)
|
while (watchpoint)
|
||||||
{
|
{
|
||||||
|
@ -204,11 +277,21 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
|
||||||
(*watchpoint_p)->unique_id = bpwp_unique_id++;
|
(*watchpoint_p)->unique_id = bpwp_unique_id++;
|
||||||
|
|
||||||
retval = target_add_watchpoint(target, *watchpoint_p);
|
retval = target_add_watchpoint(target, *watchpoint_p);
|
||||||
if (retval != ERROR_OK)
|
switch (retval) {
|
||||||
{
|
case ERROR_OK:
|
||||||
LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32,
|
break;
|
||||||
|
case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
|
||||||
|
reason = "resource not available";
|
||||||
|
goto bye;
|
||||||
|
case ERROR_TARGET_NOT_HALTED:
|
||||||
|
reason = "target running";
|
||||||
|
goto bye;
|
||||||
|
default:
|
||||||
|
reason = "unrecognized error";
|
||||||
|
bye:
|
||||||
|
LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
|
||||||
watchpoint_rw_strings[(*watchpoint_p)->rw],
|
watchpoint_rw_strings[(*watchpoint_p)->rw],
|
||||||
address);
|
address, reason);
|
||||||
free (*watchpoint_p);
|
free (*watchpoint_p);
|
||||||
*watchpoint_p = NULL;
|
*watchpoint_p = NULL;
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* Copyright (C) ST-Ericsson SA 2011 *
|
||||||
|
* Author: Michel Jaouen <michel.jaouen@stericsson.com> for ST-Ericsson. *
|
||||||
|
* 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, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "server/server.h"
|
||||||
|
#include <helper/types.h>
|
||||||
|
|
||||||
|
#include "target/target.h"
|
||||||
|
|
||||||
|
#include "server/gdb_server.h"
|
||||||
|
#include "smp.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* implementation of new packet in gdb interface for smp feature */
|
||||||
|
/* */
|
||||||
|
/* j : smp status request */
|
||||||
|
/* J : smp set request */
|
||||||
|
/* */
|
||||||
|
/* jc :read core id displayed by gdb connection */
|
||||||
|
/* reply XXXXXXXX core id is int32_t , 8 hex digits */
|
||||||
|
/* */
|
||||||
|
/* Reply ENN error not supported (target not smp) */
|
||||||
|
/* */
|
||||||
|
/* JcXX set core id displayed at next gdb continue */
|
||||||
|
/* maximum 8 bytes described core id int32_t (8 hex digits) */
|
||||||
|
/* (core id -1 , reserved for returning to normal continue mode) */
|
||||||
|
/* Reply ENN error not supported(target not smp,core id out of range) */
|
||||||
|
/* Reply OK : for success */
|
||||||
|
/* */
|
||||||
|
/* handling of this packet within gdb can be done by the creation */
|
||||||
|
/* internal variable by mean of function allocate_computed_value */
|
||||||
|
/* set $_core 1 => Jc01 packet is sent */
|
||||||
|
/* print $_core => jc packet is sent and result is affected in $ */
|
||||||
|
/* Another way to test this packet is the usage of maintenance packet */
|
||||||
|
/* maint packet Jc01 */
|
||||||
|
/* maint packet jc */
|
||||||
|
|
||||||
|
static const char DIGITS[16] = "0123456789abcdef";
|
||||||
|
|
||||||
|
|
||||||
|
/* packet j :smp status request */
|
||||||
|
int gdb_read_smp_packet(struct connection *connection,
|
||||||
|
struct target *target, char *packet, int packet_size)
|
||||||
|
{
|
||||||
|
uint32_t len = sizeof(int32_t);
|
||||||
|
uint8_t *buffer;
|
||||||
|
char *hex_buffer;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
if (target->smp)
|
||||||
|
{
|
||||||
|
if (strstr(packet, "jc"))
|
||||||
|
{
|
||||||
|
hex_buffer = malloc(len * 2 + 1);
|
||||||
|
buffer = (uint8_t *)&target->gdb_service->core[0];
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
uint8_t t = buffer[i];
|
||||||
|
hex_buffer[2 * i] = DIGITS[(t >> 4) & 0xf];
|
||||||
|
hex_buffer[2 * i + 1] = DIGITS[t & 0xf];
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_put_packet(connection, hex_buffer, len * 2);
|
||||||
|
|
||||||
|
free(hex_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
retval = gdb_put_packet(connection,"E01",3);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* J : smp set request */
|
||||||
|
int gdb_write_smp_packet(struct connection *connection,
|
||||||
|
struct target *target, char *packet, int packet_size)
|
||||||
|
{
|
||||||
|
char *separator;
|
||||||
|
int coreid = 0;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
|
/* skip command character */
|
||||||
|
if (target->smp)
|
||||||
|
{
|
||||||
|
if (strstr(packet, "Jc"))
|
||||||
|
{
|
||||||
|
packet+=2;
|
||||||
|
coreid = strtoul(packet, &separator, 16);
|
||||||
|
target->gdb_service->core[1] = coreid;
|
||||||
|
gdb_put_packet(connection, "OK", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retval = gdb_put_packet(connection,"E01",3);
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* Copyright (C) ST-Ericsson SA 2011 *
|
||||||
|
* Author: Michel Jaouen <michel.jaouen@stericsson.com> for ST-Ericsson. *
|
||||||
|
* 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, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "server/server.h"
|
||||||
|
int gdb_read_smp_packet(struct connection *connection,
|
||||||
|
struct target *target, char *packet, int packet_size);
|
||||||
|
int gdb_write_smp_packet(struct connection *connection,
|
||||||
|
struct target *target, char *packet, int packet_size);
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
* Copyright (C) 2011 by Broadcom Corporation *
|
* Copyright (C) 2011 by Broadcom Corporation *
|
||||||
* Evan Hunter - ehunter@broadcom.com *
|
* Evan Hunter - ehunter@broadcom.com *
|
||||||
* *
|
* *
|
||||||
|
* 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 *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
@ -729,7 +732,7 @@ int target_bulk_write_memory(struct target *target,
|
||||||
int target_add_breakpoint(struct target *target,
|
int target_add_breakpoint(struct target *target,
|
||||||
struct breakpoint *breakpoint)
|
struct breakpoint *breakpoint)
|
||||||
{
|
{
|
||||||
if (target->state != TARGET_HALTED) {
|
if ((target->state != TARGET_HALTED)&&(breakpoint->type!=BKPT_HARD)) {
|
||||||
LOG_WARNING("target %s is not halted", target->cmd_name);
|
LOG_WARNING("target %s is not halted", target->cmd_name);
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
@ -3931,6 +3934,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
|
||||||
/* loop for more e*/
|
/* loop for more e*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case TCFG_ENDIAN:
|
case TCFG_ENDIAN:
|
||||||
if (goi->isconfigure) {
|
if (goi->isconfigure) {
|
||||||
e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n);
|
e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n);
|
||||||
|
@ -3981,7 +3985,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
|
||||||
if (e != JIM_OK) {
|
if (e != JIM_OK) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
target->coreid = (int)w;
|
target->coreid = (int32_t)w;
|
||||||
} else {
|
} else {
|
||||||
if (goi->argc != 0) {
|
if (goi->argc != 0) {
|
||||||
goto no_params;
|
goto no_params;
|
||||||
|
@ -4893,6 +4897,61 @@ static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
return JIM_OK;
|
return JIM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char *targetname;
|
||||||
|
int retval,len;
|
||||||
|
struct target *target;
|
||||||
|
struct target_list *head, *curr, *new;
|
||||||
|
curr = (struct target_list*) NULL;
|
||||||
|
head = (struct target_list*) NULL;
|
||||||
|
new = (struct target_list*) NULL;
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
LOG_DEBUG("%d",argc);
|
||||||
|
/* argv[1] = target to associate in smp
|
||||||
|
* argv[2] = target to assoicate in smp
|
||||||
|
* argv[3] ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(i=1;i<argc;i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
targetname = Jim_GetString(argv[i], &len);
|
||||||
|
target = get_target(targetname);
|
||||||
|
LOG_DEBUG("%s ",targetname);
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
new=malloc(sizeof(struct target_list));
|
||||||
|
new->target = target;
|
||||||
|
new->next = (struct target_list*)NULL;
|
||||||
|
if (head == (struct target_list*)NULL)
|
||||||
|
{
|
||||||
|
head = new;
|
||||||
|
curr = head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curr->next = new;
|
||||||
|
curr = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* now parse the list of cpu and put the target in smp mode*/
|
||||||
|
curr=head;
|
||||||
|
|
||||||
|
while(curr!=(struct target_list *)NULL)
|
||||||
|
{
|
||||||
|
target=curr->target;
|
||||||
|
target->smp = 1;
|
||||||
|
target->head = head;
|
||||||
|
curr=curr->next;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
{
|
{
|
||||||
Jim_GetOptInfo goi;
|
Jim_GetOptInfo goi;
|
||||||
|
@ -5008,6 +5067,14 @@ static const struct command_registration target_subcommand_handlers[] = {
|
||||||
.help = "Returns the number of targets as an integer "
|
.help = "Returns the number of targets as an integer "
|
||||||
"(DEPRECATED)",
|
"(DEPRECATED)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "smp",
|
||||||
|
.mode = COMMAND_ANY,
|
||||||
|
.jim_handler = jim_target_smp,
|
||||||
|
.usage = "targetname1 targetname2 ...",
|
||||||
|
.help = "gather several target in a smp list"
|
||||||
|
},
|
||||||
|
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
* Copyright (C) 2011 by Broadcom Corporation *
|
* Copyright (C) 2011 by Broadcom Corporation *
|
||||||
* Evan Hunter - ehunter@broadcom.com *
|
* Evan Hunter - ehunter@broadcom.com *
|
||||||
* *
|
* *
|
||||||
|
* 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 *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
@ -38,7 +41,7 @@ struct breakpoint;
|
||||||
struct watchpoint;
|
struct watchpoint;
|
||||||
struct mem_param;
|
struct mem_param;
|
||||||
struct reg_param;
|
struct reg_param;
|
||||||
|
struct target_list;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TARGET_UNKNOWN = 0: we don't know anything about the target yet
|
* TARGET_UNKNOWN = 0: we don't know anything about the target yet
|
||||||
|
@ -102,6 +105,17 @@ struct working_area
|
||||||
struct working_area **user;
|
struct working_area **user;
|
||||||
struct working_area *next;
|
struct working_area *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gdb_service
|
||||||
|
{
|
||||||
|
struct target *target;
|
||||||
|
/* field for smp display */
|
||||||
|
/* element 0 coreid currently displayed ( 1 till n) */
|
||||||
|
/* element 1 coreid to be displayed at next resume 1 till n 0 means resume
|
||||||
|
* all cores
|
||||||
|
core displayed */
|
||||||
|
int32_t core[2];
|
||||||
|
};
|
||||||
|
|
||||||
// target_type.h contains the full definitionof struct targe_type
|
// target_type.h contains the full definitionof struct targe_type
|
||||||
struct target
|
struct target
|
||||||
|
@ -110,7 +124,7 @@ struct target
|
||||||
const char *cmd_name; /* tcl Name of target */
|
const char *cmd_name; /* tcl Name of target */
|
||||||
int target_number; /* DO NOT USE! field to be removed in 2010 */
|
int target_number; /* DO NOT USE! field to be removed in 2010 */
|
||||||
struct jtag_tap *tap; /* where on the jtag chain is this */
|
struct jtag_tap *tap; /* where on the jtag chain is this */
|
||||||
int coreid; /* which device on the TAP? */
|
int32_t coreid; /* which device on the TAP? */
|
||||||
const char *variant; /* what variant of this chip is it? */
|
const char *variant; /* what variant of this chip is it? */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,6 +180,20 @@ struct target
|
||||||
struct rtos *rtos; /* Instance of Real Time Operating System support */
|
struct rtos *rtos; /* Instance of Real Time Operating System support */
|
||||||
bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
|
bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
|
||||||
* and must be detected when symbols are offered */
|
* and must be detected when symbols are offered */
|
||||||
|
|
||||||
|
int smp; /* add some target attributes for smp support */
|
||||||
|
struct target_list *head;
|
||||||
|
/* the gdb service is there in case of smp , we have only one gdb server
|
||||||
|
* for all smp target
|
||||||
|
* the target attached to the gdb is changing dynamically by changing
|
||||||
|
* gdb_service->target pointer */
|
||||||
|
struct gdb_service *gdb_service;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct target_list {
|
||||||
|
struct target *target;
|
||||||
|
struct target_list *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Returns the instance-specific name of the specified target. */
|
/** Returns the instance-specific name of the specified target. */
|
||||||
|
|
Loading…
Reference in New Issue