uint64_t->target_addr_t for stack pointers.
[openocd.git] / src / rtos / hwthread.c
blob3702b0b4762d6976ba548286ba4c62cc72580855
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 ***************************************************************************/
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
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"
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(struct rtos *rtos, int64_t thread_id,
35 uint32_t reg_num, struct rtos_reg *rtos_reg);
36 static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
37 struct rtos_reg **reg_list, int *num_regs);
38 static int hwthread_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
39 static int hwthread_smp_init(struct target *target);
40 static int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value);
41 static int hwthread_read_buffer(struct rtos *rtos, target_addr_t address,
42 uint32_t size, uint8_t *buffer);
43 static int hwthread_write_buffer(struct rtos *rtos, target_addr_t address,
44 uint32_t size, const uint8_t *buffer);
46 #define HW_THREAD_NAME_STR_SIZE (32)
48 extern int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
50 static inline threadid_t threadid_from_target(const struct target *target)
52 return target->coreid + 1;
55 const struct rtos_type hwthread_rtos = {
56 .name = "hwthread",
57 .detect_rtos = hwthread_detect_rtos,
58 .create = hwthread_create,
59 .update_threads = hwthread_update_threads,
60 .get_thread_reg_list = hwthread_get_thread_reg_list,
61 .get_thread_reg = hwthread_get_thread_reg,
62 .get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup,
63 .smp_init = hwthread_smp_init,
64 .set_reg = hwthread_set_reg,
65 .read_buffer = hwthread_read_buffer,
66 .write_buffer = hwthread_write_buffer,
69 struct hwthread_params {
70 int dummy_param;
73 static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num)
75 char tmp_str[HW_THREAD_NAME_STR_SIZE];
76 threadid_t tid = threadid_from_target(curr);
78 memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE);
80 /* thread-id is the core-id of this core inside the SMP group plus 1 */
81 rtos->thread_details[thread_num].threadid = tid;
82 /* create the thread name */
83 rtos->thread_details[thread_num].exists = true;
84 rtos->thread_details[thread_num].thread_name_str = strdup(target_name(curr));
85 snprintf(tmp_str, HW_THREAD_NAME_STR_SIZE-1, "state: %s", debug_reason_name(curr));
86 rtos->thread_details[thread_num].extra_info_str = strdup(tmp_str);
88 return ERROR_OK;
91 static int hwthread_update_threads(struct rtos *rtos)
93 int threads_found = 0;
94 int thread_list_size = 0;
95 struct target_list *head;
96 struct target *target;
97 int64_t current_thread = 0;
98 enum target_debug_reason current_reason = DBG_REASON_UNDEFINED;
100 if (!rtos)
101 return -1;
103 target = rtos->target;
105 /* wipe out previous thread details if any */
106 rtos_free_threadlist(rtos);
108 /* determine the number of "threads" */
109 if (target->smp) {
110 for (head = target->head; head; head = head->next) {
111 struct target *curr = head->target;
113 if (!target_was_examined(curr))
114 continue;
116 ++thread_list_size;
118 } else
119 thread_list_size = 1;
121 /* create space for new thread details */
122 rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
124 if (target->smp) {
125 /* loop over all threads */
126 for (head = target->head; head; head = head->next) {
127 struct target *curr = head->target;
129 if (!target_was_examined(curr))
130 continue;
132 threadid_t tid = threadid_from_target(curr);
134 hwthread_fill_thread(rtos, curr, threads_found);
136 /* find an interesting thread to set as current */
137 switch (current_reason) {
138 case DBG_REASON_UNDEFINED:
139 current_reason = curr->debug_reason;
140 current_thread = tid;
141 break;
142 case DBG_REASON_SINGLESTEP:
143 /* single-step can only be overridden by itself */
144 if (curr->debug_reason == DBG_REASON_SINGLESTEP) {
145 if (tid == rtos->current_threadid)
146 current_thread = tid;
148 break;
149 case DBG_REASON_BREAKPOINT:
150 /* single-step overrides breakpoint */
151 if (curr->debug_reason == DBG_REASON_SINGLESTEP) {
152 current_reason = curr->debug_reason;
153 current_thread = tid;
154 } else
155 /* multiple breakpoints, prefer gdbs' threadid */
156 if (curr->debug_reason == DBG_REASON_BREAKPOINT) {
157 if (tid == rtos->current_threadid)
158 current_thread = tid;
160 break;
161 case DBG_REASON_WATCHPOINT:
162 /* breakpoint and single-step override watchpoint */
163 if (curr->debug_reason == DBG_REASON_SINGLESTEP ||
164 curr->debug_reason == DBG_REASON_BREAKPOINT) {
165 current_reason = curr->debug_reason;
166 current_thread = tid;
168 break;
169 case DBG_REASON_DBGRQ:
170 /* all other reasons override debug-request */
171 if (curr->debug_reason == DBG_REASON_SINGLESTEP ||
172 curr->debug_reason == DBG_REASON_WATCHPOINT ||
173 curr->debug_reason == DBG_REASON_BREAKPOINT) {
174 current_reason = curr->debug_reason;
175 current_thread = tid;
176 } else
177 if (curr->debug_reason == DBG_REASON_DBGRQ) {
178 if (tid == rtos->current_threadid)
179 current_thread = tid;
182 break;
184 default:
185 break;
188 threads_found++;
190 } else {
191 hwthread_fill_thread(rtos, target, threads_found);
192 current_thread = threadid_from_target(target);
193 threads_found++;
196 rtos->thread_count = threads_found;
198 /* we found an interesting thread, set it as current */
199 if (current_thread != 0)
200 rtos->current_thread = current_thread;
201 else if (rtos->current_threadid != 0)
202 rtos->current_thread = rtos->current_threadid;
203 else
204 rtos->current_thread = threadid_from_target(target);
206 LOG_DEBUG("%s current_thread=%i", __func__, (int)rtos->current_thread);
207 return 0;
210 static int hwthread_smp_init(struct target *target)
212 return hwthread_update_threads(target->rtos);
215 static struct target *hwthread_find_thread(struct target *target, int64_t thread_id)
217 /* Find the thread with that thread_id */
218 if (!target)
219 return NULL;
220 if (target->smp) {
221 for (struct target_list *head = target->head; head; head = head->next) {
222 if (thread_id == threadid_from_target(head->target))
223 return head->target;
225 } else if (thread_id == threadid_from_target(target)) {
226 return target;
228 return NULL;
231 static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
232 struct rtos_reg **rtos_reg_list, int *rtos_reg_list_size)
234 if (!rtos)
235 return ERROR_FAIL;
237 struct target *target = rtos->target;
239 struct target *curr = hwthread_find_thread(target, thread_id);
240 if (!curr)
241 return ERROR_FAIL;
243 if (!target_was_examined(curr))
244 return ERROR_FAIL;
246 int reg_list_size;
247 struct reg **reg_list;
248 int retval = target_get_gdb_reg_list(curr, &reg_list, &reg_list_size,
249 REG_CLASS_GENERAL);
250 if (retval != ERROR_OK)
251 return retval;
253 int j = 0;
254 for (int i = 0; i < reg_list_size; i++) {
255 if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden)
256 continue;
257 j++;
259 *rtos_reg_list_size = j;
260 *rtos_reg_list = calloc(*rtos_reg_list_size, sizeof(struct rtos_reg));
261 if (!*rtos_reg_list) {
262 free(reg_list);
263 return ERROR_FAIL;
266 j = 0;
267 for (int i = 0; i < reg_list_size; i++) {
268 if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden)
269 continue;
270 (*rtos_reg_list)[j].number = (*reg_list)[i].number;
271 (*rtos_reg_list)[j].size = (*reg_list)[i].size;
272 memcpy((*rtos_reg_list)[j].value, (*reg_list)[i].value,
273 ((*reg_list)[i].size + 7) / 8);
274 j++;
276 free(reg_list);
278 return ERROR_OK;
281 static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id,
282 uint32_t reg_num, struct rtos_reg *rtos_reg)
284 if (!rtos)
285 return ERROR_FAIL;
287 struct target *target = rtos->target;
289 struct target *curr = hwthread_find_thread(target, thread_id);
290 if (!curr) {
291 LOG_ERROR("Couldn't find RTOS thread for id %" PRId64 ".", thread_id);
292 return ERROR_FAIL;
295 if (!target_was_examined(curr)) {
296 LOG_ERROR("Target %d hasn't been examined yet.", curr->coreid);
297 return ERROR_FAIL;
300 struct reg *reg = register_get_by_number(curr->reg_cache, reg_num, true);
301 if (!reg) {
302 LOG_ERROR("Couldn't find register %" PRIu32 " in thread %" PRId64 ".", reg_num,
303 thread_id);
304 return ERROR_FAIL;
307 if (reg->type->get(reg) != ERROR_OK)
308 return ERROR_FAIL;
310 rtos_reg->number = reg->number;
311 rtos_reg->size = reg->size;
312 unsigned bytes = (reg->size + 7) / 8;
313 assert(bytes <= sizeof(rtos_reg->value));
314 memcpy(rtos_reg->value, reg->value, bytes);
316 return ERROR_OK;
319 static int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value)
321 if (!rtos)
322 return ERROR_FAIL;
324 struct target *target = rtos->target;
326 struct target *curr = hwthread_find_thread(target, rtos->current_thread);
327 if (!curr)
328 return ERROR_FAIL;
330 struct reg *reg = register_get_by_number(curr->reg_cache, reg_num, true);
331 if (!reg)
332 return ERROR_FAIL;
334 return reg->type->set(reg, reg_value);
337 static int hwthread_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
339 /* return an empty list, we don't have any symbols to look up */
340 *symbol_list = calloc(1, sizeof(struct symbol_table_elem));
341 (*symbol_list)[0].symbol_name = NULL;
342 return 0;
345 static int hwthread_target_for_threadid(struct connection *connection, int64_t thread_id, struct target **p_target)
347 struct target *target = get_target_from_connection(connection);
349 struct target *curr = hwthread_find_thread(target, thread_id);
350 if (!curr)
351 return ERROR_FAIL;
353 *p_target = curr;
355 return ERROR_OK;
358 static bool hwthread_detect_rtos(struct target *target)
360 /* always return 0, avoid auto-detection */
361 return false;
364 static int hwthread_thread_packet(struct connection *connection, const char *packet, int packet_size)
366 struct target *target = get_target_from_connection(connection);
368 struct target *curr = NULL;
369 int64_t current_threadid;
371 if (packet[0] == 'H' && packet[1] == 'g') {
372 sscanf(packet, "Hg%16" SCNx64, &current_threadid);
374 if (current_threadid > 0) {
375 if (hwthread_target_for_threadid(connection, current_threadid, &curr) != ERROR_OK) {
376 LOG_ERROR("hwthread: cannot find thread id %"PRId64, current_threadid);
377 gdb_put_packet(connection, "E01", 3);
378 return ERROR_FAIL;
380 target->rtos->current_thread = current_threadid;
381 } else
382 if (current_threadid == 0 || current_threadid == -1)
383 target->rtos->current_thread = threadid_from_target(target);
385 target->rtos->current_threadid = current_threadid;
387 gdb_put_packet(connection, "OK", 2);
388 return ERROR_OK;
391 return rtos_thread_packet(connection, packet, packet_size);
394 static int hwthread_create(struct target *target)
396 LOG_INFO("Hardware thread awareness created");
398 target->rtos->rtos_specific_params = NULL;
399 target->rtos->current_thread = 0;
400 target->rtos->thread_details = NULL;
401 target->rtos->gdb_target_for_threadid = hwthread_target_for_threadid;
402 target->rtos->gdb_thread_packet = hwthread_thread_packet;
403 return 0;
406 static int hwthread_read_buffer(struct rtos *rtos, target_addr_t address,
407 uint32_t size, uint8_t *buffer)
409 if (!rtos)
410 return ERROR_FAIL;
412 struct target *target = rtos->target;
414 struct target *curr = hwthread_find_thread(target, rtos->current_thread);
415 if (!curr)
416 return ERROR_FAIL;
418 return target_read_buffer(curr, address, size, buffer);
421 static int hwthread_write_buffer(struct rtos *rtos, target_addr_t address,
422 uint32_t size, const uint8_t *buffer)
424 if (!rtos)
425 return ERROR_FAIL;
427 struct target *target = rtos->target;
429 struct target *curr = hwthread_find_thread(target, rtos->current_thread);
430 if (!curr)
431 return ERROR_FAIL;
433 return target_write_buffer(curr, address, size, buffer);