target: remove unused function target_buffer_get_u8()
[openocd.git] / src / rtos / hwthread.c
1 /***************************************************************************
2 * *
3 * This program is free software; you can redistribute it and/or modify *
4 * it under the terms of the GNU General Public License as published by *
5 * the Free Software Foundation; either version 2 of the License, or *
6 * (at your option) any later version. *
7 * *
8 * This program is distributed in the hope that it will be useful, *
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11 * GNU General Public License for more details. *
12 * *
13 * You should have received a copy of the GNU General Public License *
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
15 ***************************************************************************/
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <helper/time_support.h>
22 #include <jtag/jtag.h>
23 #include "target/target.h"
24 #include "target/target_type.h"
25 #include "target/register.h"
26 #include "rtos.h"
27 #include "helper/log.h"
28 #include "helper/types.h"
29 #include "server/gdb_server.h"
30
31 static bool hwthread_detect_rtos(struct target *target);
32 static int hwthread_create(struct target *target);
33 static int hwthread_update_threads(struct rtos *rtos);
34 static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
35 struct rtos_reg **reg_list, int *num_regs);
36 static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
37 static int hwthread_smp_init(struct target *target);
38
39 #define HW_THREAD_NAME_STR_SIZE (32)
40
41 extern int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
42
43 static inline threadid_t threadid_from_target(const struct target *target)
44 {
45 return target->coreid + 1;
46 }
47
48 const struct rtos_type hwthread_rtos = {
49 .name = "hwthread",
50 .detect_rtos = hwthread_detect_rtos,
51 .create = hwthread_create,
52 .update_threads = hwthread_update_threads,
53 .get_thread_reg_list = hwthread_get_thread_reg_list,
54 .get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup,
55 .smp_init = hwthread_smp_init,
56 };
57
58 struct hwthread_params {
59 int dummy_param;
60 };
61
62 static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num)
63 {
64 char tmp_str[HW_THREAD_NAME_STR_SIZE];
65 threadid_t tid = threadid_from_target(curr);
66
67 memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE);
68
69 /* thread-id is the core-id of this core inside the SMP group plus 1 */
70 rtos->thread_details[thread_num].threadid = tid;
71 /* create the thread name */
72 rtos->thread_details[thread_num].exists = true;
73 rtos->thread_details[thread_num].thread_name_str = strdup(target_name(curr));
74 snprintf(tmp_str, HW_THREAD_NAME_STR_SIZE-1, "state: %s", debug_reason_name(curr));
75 rtos->thread_details[thread_num].extra_info_str = strdup(tmp_str);
76
77 return ERROR_OK;
78 }
79
80 static int hwthread_update_threads(struct rtos *rtos)
81 {
82 int threads_found = 0;
83 int thread_list_size = 0;
84 struct target_list *head;
85 struct target *target;
86 int64_t current_thread = 0;
87 enum target_debug_reason current_reason = DBG_REASON_UNDEFINED;
88
89 if (rtos == NULL)
90 return -1;
91
92 target = rtos->target;
93
94 /* wipe out previous thread details if any */
95 rtos_free_threadlist(rtos);
96
97 /* determine the number of "threads" */
98 if (target->smp) {
99 for (head = target->head; head != NULL; head = head->next) {
100 struct target *curr = head->target;
101
102 if (!target_was_examined(curr))
103 continue;
104
105 ++thread_list_size;
106 }
107 } else
108 thread_list_size = 1;
109
110 /* create space for new thread details */
111 rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
112
113 if (target->smp) {
114 /* loop over all threads */
115 for (head = target->head; head != NULL; head = head->next) {
116 struct target *curr = head->target;
117
118 if (!target_was_examined(curr))
119 continue;
120
121 threadid_t tid = threadid_from_target(curr);
122
123 hwthread_fill_thread(rtos, curr, threads_found);
124
125 /* find an interesting thread to set as current */
126 switch (current_reason) {
127 case DBG_REASON_UNDEFINED:
128 current_reason = curr->debug_reason;
129 current_thread = tid;
130 break;
131 case DBG_REASON_SINGLESTEP:
132 /* single-step can only be overridden by itself */
133 if (curr->debug_reason == DBG_REASON_SINGLESTEP) {
134 if (tid == rtos->current_threadid)
135 current_thread = tid;
136 }
137 break;
138 case DBG_REASON_BREAKPOINT:
139 /* single-step overrides breakpoint */
140 if (curr->debug_reason == DBG_REASON_SINGLESTEP) {
141 current_reason = curr->debug_reason;
142 current_thread = tid;
143 } else
144 /* multiple breakpoints, prefer gdbs' threadid */
145 if (curr->debug_reason == DBG_REASON_BREAKPOINT) {
146 if (tid == rtos->current_threadid)
147 current_thread = tid;
148 }
149 break;
150 case DBG_REASON_WATCHPOINT:
151 /* breakpoint and single-step override watchpoint */
152 if (curr->debug_reason == DBG_REASON_SINGLESTEP ||
153 curr->debug_reason == DBG_REASON_BREAKPOINT) {
154 current_reason = curr->debug_reason;
155 current_thread = tid;
156 }
157 break;
158 case DBG_REASON_DBGRQ:
159 /* all other reasons override debug-request */
160 if (curr->debug_reason == DBG_REASON_SINGLESTEP ||
161 curr->debug_reason == DBG_REASON_WATCHPOINT ||
162 curr->debug_reason == DBG_REASON_BREAKPOINT) {
163 current_reason = curr->debug_reason;
164 current_thread = tid;
165 } else
166 if (curr->debug_reason == DBG_REASON_DBGRQ) {
167 if (tid == rtos->current_threadid)
168 current_thread = tid;
169 }
170
171 break;
172
173 default:
174 break;
175 }
176
177 threads_found++;
178 }
179 } else {
180 hwthread_fill_thread(rtos, target, threads_found);
181 current_thread = threadid_from_target(target);
182 threads_found++;
183 }
184
185 rtos->thread_count = threads_found;
186
187 /* we found an interesting thread, set it as current */
188 if (current_thread != 0)
189 rtos->current_thread = current_thread;
190 else if (rtos->current_threadid != 0)
191 rtos->current_thread = rtos->current_threadid;
192 else
193 rtos->current_thread = threadid_from_target(target);
194
195 LOG_DEBUG("%s current_thread=%i", __func__, (int)rtos->current_thread);
196 return 0;
197 }
198
199 static int hwthread_smp_init(struct target *target)
200 {
201 return hwthread_update_threads(target->rtos);
202 }
203
204 static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
205 struct rtos_reg **rtos_reg_list, int *num_regs)
206 {
207 struct target_list *head;
208 struct target *target;
209 struct target *curr;
210 struct reg **reg_list;
211 int retval;
212
213 if (rtos == NULL)
214 return ERROR_FAIL;
215
216 target = rtos->target;
217
218 /* Find the thread with that thread_id */
219 if (target->smp) {
220 curr = NULL;
221 for (head = target->head; head != NULL; head = head->next) {
222 curr = head->target;
223
224 if (thread_id == threadid_from_target(curr))
225 break;
226 }
227
228 if (head == NULL)
229 return ERROR_FAIL;
230 } else {
231 curr = target;
232 if (thread_id != threadid_from_target(curr))
233 return ERROR_FAIL;
234
235 }
236
237 if (!target_was_examined(curr))
238 return ERROR_FAIL;
239
240 retval = target_get_gdb_reg_list(curr, &reg_list, num_regs,
241 REG_CLASS_GENERAL);
242 if (retval != ERROR_OK)
243 return retval;
244
245 *rtos_reg_list = calloc(*num_regs, sizeof(struct rtos_reg));
246 if (*rtos_reg_list == NULL) {
247 free(reg_list);
248 return ERROR_FAIL;
249 }
250
251 for (int i = 0; i < *num_regs; i++) {
252 (*rtos_reg_list)[i].number = (*reg_list)[i].number;
253 (*rtos_reg_list)[i].size = (*reg_list)[i].size;
254 memcpy((*rtos_reg_list)[i].value, (*reg_list)[i].value,
255 ((*reg_list)[i].size + 7) / 8);
256 }
257
258 free(reg_list);
259
260 return ERROR_OK;
261
262 }
263
264 static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
265 {
266 /* return an empty list, we don't have any symbols to look up */
267 *symbol_list = calloc(1, sizeof(symbol_table_elem_t));
268 (*symbol_list)[0].symbol_name = NULL;
269 return 0;
270 }
271
272 static int hwthread_target_for_threadid(struct connection *connection, int64_t thread_id, struct target **p_target)
273 {
274 struct target *target = get_target_from_connection(connection);
275 struct target_list *head;
276 struct target *curr;
277
278 if (target->smp) {
279 /* Find the thread with that thread_id */
280 curr = NULL;
281 for (head = target->head; head != NULL; head = head->next) {
282 curr = head->target;
283
284 if (thread_id == threadid_from_target(curr))
285 break;
286 }
287
288 if (head == NULL)
289 return ERROR_FAIL;
290 } else {
291 curr = target;
292 if (thread_id != threadid_from_target(curr))
293 return ERROR_FAIL;
294 }
295
296 *p_target = curr;
297
298 return ERROR_OK;
299 }
300
301 static bool hwthread_detect_rtos(struct target *target)
302 {
303 /* always return 0, avoid auto-detection */
304 return false;
305 }
306
307 static int hwthread_thread_packet(struct connection *connection, const char *packet, int packet_size)
308 {
309 struct target *target = get_target_from_connection(connection);
310
311 struct target *curr = NULL;
312 int64_t current_threadid;
313
314 if (packet[0] == 'H' && packet[1] == 'g') {
315 sscanf(packet, "Hg%16" SCNx64, &current_threadid);
316
317 if (current_threadid > 0) {
318 if (hwthread_target_for_threadid(connection, current_threadid, &curr) != ERROR_OK) {
319 LOG_ERROR("hwthread: cannot find thread id %"PRId64, current_threadid);
320 gdb_put_packet(connection, "E01", 3);
321 return ERROR_FAIL;
322 }
323 target->rtos->current_thread = current_threadid;
324 } else
325 if (current_threadid == 0 || current_threadid == -1)
326 target->rtos->current_thread = threadid_from_target(target);
327
328 target->rtos->current_threadid = current_threadid;
329
330 gdb_put_packet(connection, "OK", 2);
331 return ERROR_OK;
332 }
333
334 return rtos_thread_packet(connection, packet, packet_size);
335 }
336
337 static int hwthread_create(struct target *target)
338 {
339 LOG_INFO("Hardware thread awareness created");
340
341 target->rtos->rtos_specific_params = NULL;
342 target->rtos->current_thread = 0;
343 target->rtos->thread_details = NULL;
344 target->rtos->gdb_target_for_threadid = hwthread_target_for_threadid;
345 target->rtos->gdb_thread_packet = hwthread_thread_packet;
346 return 0;
347 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)