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