smp: deprecate legacy SMP core switching support
[fw/openocd] / src / target / smp.c
1 /***************************************************************************
2  *                                                                         *
3  * Copyright (C) ST-Ericsson SA 2011                                       *
4  * Author: Michel Jaouen <michel.jaouen@stericsson.com> for ST-Ericsson.   *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
17  ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "server/server.h"
24
25 #include "target/target.h"
26
27 #include "server/gdb_server.h"
28 #include "smp.h"
29 #include "helper/binarybuffer.h"
30
31 /* DEPRECATED: gdb_read_smp_packet/gdb_write_smp_packet to be removed      */
32 /*  implementation of new packet in gdb interface for smp feature          */
33 /*                                                                         */
34 /*   j : smp  status request                                               */
35 /*   J : smp  set request                                                  */
36 /*                                                                         */
37 /*   jc :read core id displayed by gdb connection                          */
38 /*   reply XXXXXXXX core id is int32_t , 8 hex digits                      */
39 /*                                                                         */
40 /*   Reply ENN error not supported (target not smp)                        */
41 /*                                                                         */
42 /*   JcXX  set core id displayed at next gdb continue                      */
43 /*   maximum 8 bytes described core id int32_t (8 hex digits)              */
44 /*  (core id -1 , reserved for returning to normal continue mode) */
45 /*  Reply ENN error not supported(target not smp,core id out of range)     */
46 /*  Reply OK : for success                                                 */
47 /*                                                                         */
48 /*  handling of this packet within gdb can be done by the creation         */
49 /*  internal variable by mean of function allocate_computed_value          */
50 /*  set $_core 1 => Jc01 packet is sent                                    */
51 /*  print $_core => jc packet is sent and result is affected in $          */
52 /*  Another way to test this packet is the usage of maintenance packet     */
53 /*  maint packet Jc01                                                      */
54 /*  maint packet jc                                                        */
55
56 /* packet j :smp status request */
57 #define DEPRECATED_MSG "DEPRECATED: This method is deprecated in favor of the hwthread pseudo RTOS"
58 int gdb_read_smp_packet(struct connection *connection,
59                 char const *packet, int packet_size)
60 {
61         struct target *target = get_target_from_connection(connection);
62         int retval = ERROR_OK;
63
64         LOG_WARNING(DEPRECATED_MSG);
65
66         if (target->smp) {
67                 if (strncmp(packet, "jc", 2) == 0) {
68                         const uint32_t len = sizeof(target->gdb_service->core[0]);
69                         char hex_buffer[len * 2 + 1];
70                         uint8_t buffer[len];
71                         buf_set_u32(buffer, 0, len * 8, target->gdb_service->core[0]);
72                         size_t pkt_len = hexify(hex_buffer, buffer, sizeof(buffer),
73                                 sizeof(hex_buffer));
74
75                         retval = gdb_put_packet(connection, hex_buffer, pkt_len);
76                 }
77         } else
78                 retval = gdb_put_packet(connection, "E01", 3);
79         return retval;
80 }
81
82 /* J :  smp set request */
83 int gdb_write_smp_packet(struct connection *connection,
84                 char const *packet, int packet_size)
85 {
86         struct target *target = get_target_from_connection(connection);
87         char *separator;
88         int coreid = 0;
89         int retval = ERROR_OK;
90
91         LOG_WARNING(DEPRECATED_MSG);
92
93         /* skip command character */
94         if (target->smp) {
95                 if (strncmp(packet, "Jc", 2) == 0) {
96                         packet += 2;
97                         coreid = strtoul(packet, &separator, 16);
98                         target->gdb_service->core[1] = coreid;
99                         retval = gdb_put_packet(connection, "OK", 2);
100                 }
101         } else
102                 retval = gdb_put_packet(connection, "E01", 3);
103
104         return retval;
105 }
106
107 COMMAND_HANDLER(default_handle_smp_command)
108 {
109         struct target *target = get_current_target(CMD_CTX);
110         struct target_list *head;
111
112         if (CMD_ARGC > 1)
113                 return ERROR_COMMAND_SYNTAX_ERROR;
114
115         if (!CMD_ARGC) {
116                 command_print(CMD, "%s", target->smp ? "on" : "off");
117                 return ERROR_OK;
118         }
119
120         if (!strcmp(CMD_ARGV[0], "on")) {
121                 foreach_smp_target(head, target->smp_targets)
122                         head->target->smp = 1;
123
124                 return ERROR_OK;
125         }
126
127         if (!strcmp(CMD_ARGV[0], "off")) {
128                 foreach_smp_target(head, target->smp_targets)
129                         head->target->smp = 0;
130
131                 /* fixes the target display to the debugger */
132                 if (!list_empty(target->smp_targets))
133                         target->gdb_service->target = target;
134
135                 return ERROR_OK;
136         }
137
138         return ERROR_COMMAND_SYNTAX_ERROR;
139 }
140
141 COMMAND_HANDLER(handle_smp_gdb_command)
142 {
143         struct target *target = get_current_target(CMD_CTX);
144         int retval = ERROR_OK;
145         if (!list_empty(target->smp_targets)) {
146                 if (CMD_ARGC == 1) {
147                         int coreid = 0;
148                         COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);
149                         if (retval != ERROR_OK)
150                                 return retval;
151                         target->gdb_service->core[1] = coreid;
152
153                 }
154                 command_print(CMD, "gdb coreid  %" PRId32 " -> %" PRId32, target->gdb_service->core[0]
155                         , target->gdb_service->core[1]);
156         }
157         return ERROR_OK;
158 }
159
160 const struct command_registration smp_command_handlers[] = {
161         {
162                 .name = "smp",
163                 .handler = default_handle_smp_command,
164                 .mode = COMMAND_EXEC,
165                 .help = "smp handling",
166                 .usage = "[on|off]",
167         },
168         {
169                 .name = "smp_gdb",
170                 .handler = handle_smp_gdb_command,
171                 .mode = COMMAND_EXEC,
172                 .help = "display/fix current core played to gdb",
173                 .usage = "",
174         },
175         COMMAND_REGISTRATION_DONE
176 };