rtos: declare local symbols as static
[openocd.git] / src / rtos / linux.c
1 /***************************************************************************
2 * Copyright (C) 2011 by STEricsson *
3 * Heythem Bouhaja heythem.bouhaja@stericsson.com : creation *
4 * Michel JAOUEN michel.jaouen@stericsson.com : adaptation to rtos *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <helper/time_support.h>
25 #include <jtag/jtag.h>
26 #include "target/target.h"
27 #include "target/target_type.h"
28 #include "helper/log.h"
29 #include "helper/types.h"
30 #include "rtos.h"
31 #include "rtos_standard_stackings.h"
32 #include <target/register.h>
33 #include "server/gdb_server.h"
34
35 #define LINUX_USER_KERNEL_BORDER 0xc0000000
36 #include "linux_header.h"
37 #define PHYS
38 #define MAX_THREADS 200
39 /* specific task */
40 struct linux_os {
41 const char *name;
42 uint32_t init_task_addr;
43 int thread_count;
44 int threadid_count;
45 int preupdtate_threadid_count;
46 int nr_cpus;
47 int threads_lookup;
48 int threads_needs_update;
49 struct current_thread *current_threads;
50 struct threads *thread_list;
51 /* virt2phys parameter */
52 uint32_t phys_mask;
53 uint32_t phys_base;
54 };
55
56 struct current_thread {
57 int64_t threadid;
58 int32_t core_id;
59 #ifdef PID_CHECK
60 uint32_t pid;
61 #endif
62 uint32_t TS;
63 struct current_thread *next;
64 };
65
66 struct threads {
67 char name[17];
68 uint32_t base_addr; /* address to read magic */
69 uint32_t state; /* magic value : filled only at creation */
70 uint32_t pid; /* linux pid : id for identifying a thread */
71 uint32_t oncpu; /* content cpu number in current thread */
72 uint32_t asid; /* filled only at creation */
73 int64_t threadid;
74 int status; /* dead = 1 alive = 2 current = 3 alive and current */
75 /* value that should not change during the live of a thread ? */
76 uint32_t thread_info_addr; /* contain latest thread_info_addr computed */
77 /* retrieve from thread_info */
78 struct cpu_context *context;
79 struct threads *next;
80 };
81
82 struct cpu_context {
83 uint32_t R4;
84 uint32_t R5;
85 uint32_t R6;
86 uint32_t R7;
87 uint32_t R8;
88 uint32_t R9;
89 uint32_t IP;
90 uint32_t FP;
91 uint32_t SP;
92 uint32_t PC;
93 uint32_t preempt_count;
94 };
95 static struct cpu_context *cpu_context_read(struct target *target, uint32_t base_addr,
96 uint32_t *info_addr);
97 static int insert_into_threadlist(struct target *target, struct threads *t);
98
99 static int linux_os_create(struct target *target);
100
101 static int linux_os_dummy_update(struct rtos *rtos)
102 {
103 /* update is done only when thread request come
104 * too many thread to do it on each stop */
105 return 0;
106 }
107
108 static int linux_compute_virt2phys(struct target *target, target_addr_t address)
109 {
110 struct linux_os *linux_os = (struct linux_os *)
111 target->rtos->rtos_specific_params;
112 target_addr_t pa = 0;
113 int retval = target->type->virt2phys(target, address, &pa);
114 if (retval != ERROR_OK) {
115 LOG_ERROR("Cannot compute linux virt2phys translation");
116 /* fixes default address */
117 linux_os->phys_base = 0;
118 return ERROR_FAIL;
119 }
120
121 linux_os->init_task_addr = address;
122 address = address & linux_os->phys_mask;
123 linux_os->phys_base = pa - address;
124 return ERROR_OK;
125 }
126
127 static int linux_read_memory(struct target *target,
128 uint32_t address, uint32_t size, uint32_t count,
129 uint8_t *buffer)
130 {
131 #ifdef PHYS
132 struct linux_os *linux_os = (struct linux_os *)
133 target->rtos->rtos_specific_params;
134 uint32_t pa = (address & linux_os->phys_mask) + linux_os->phys_base;
135 #endif
136 if (address < 0xc000000) {
137 LOG_ERROR("linux awareness : address in user space");
138 return ERROR_FAIL;
139 }
140 #ifdef PHYS
141 target_read_phys_memory(target, pa, size, count, buffer);
142 #endif
143 target_read_memory(target, address, size, count, buffer);
144 return ERROR_OK;
145 }
146
147 static int fill_buffer(struct target *target, uint32_t addr, uint8_t *buffer)
148 {
149
150 if ((addr & 0xfffffffc) != addr)
151 LOG_INFO("unaligned address %" PRIx32 "!!", addr);
152
153 int retval = linux_read_memory(target, addr, 4, 1, buffer);
154 return retval;
155
156 }
157
158 static uint32_t get_buffer(struct target *target, const uint8_t *buffer)
159 {
160 uint32_t value = 0;
161 const uint8_t *value_ptr = buffer;
162 value = target_buffer_get_u32(target, value_ptr);
163 return value;
164 }
165
166 static int linux_os_thread_reg_list(struct rtos *rtos,
167 int64_t thread_id, struct rtos_reg **reg_list, int *num_regs)
168 {
169 struct target *target = rtos->target;
170 struct linux_os *linux_os = (struct linux_os *)
171 target->rtos->rtos_specific_params;
172 struct current_thread *tmp = linux_os->current_threads;
173 struct current_thread *next;
174 int found = 0;
175 int retval;
176 /* check if a current thread is requested */
177 next = tmp;
178
179 do {
180 if (next->threadid == thread_id)
181 found = 1;
182 else
183 next = next->next;
184 } while ((found == 0) && (next != tmp) && (next != NULL));
185
186 if (found == 0) {
187 LOG_ERROR("could not find thread: %" PRIx64, thread_id);
188 return ERROR_FAIL;
189 }
190
191 /* search target to perform the access */
192 struct reg **gdb_reg_list;
193 struct target_list *head;
194 head = target->head;
195 found = 0;
196 do {
197 if (head->target->coreid == next->core_id) {
198
199 target = head->target;
200 found = 1;
201 } else
202 head = head->next;
203
204 } while ((head != (struct target_list *)NULL) && (found == 0));
205
206 if (found == 0) {
207 LOG_ERROR
208 (
209 "current thread %" PRIx64 ": no target to perform access of core id %" PRIx32,
210 thread_id,
211 next->core_id);
212 return ERROR_FAIL;
213 }
214
215 /*LOG_INFO("thread %lx current on core %x",thread_id, target->coreid);*/
216 retval = target_get_gdb_reg_list(target, &gdb_reg_list, num_regs, REG_CLASS_GENERAL);
217 if (retval != ERROR_OK)
218 return retval;
219
220 *reg_list = calloc(*num_regs, sizeof(struct rtos_reg));
221
222 for (int i = 0; i < *num_regs; ++i) {
223 if (!gdb_reg_list[i]->valid)
224 gdb_reg_list[i]->type->get(gdb_reg_list[i]);
225
226 (*reg_list)[i].number = gdb_reg_list[i]->number;
227 (*reg_list)[i].size = gdb_reg_list[i]->size;
228
229 buf_cpy(gdb_reg_list[i]->value, (*reg_list)[i].value, (*reg_list)[i].size);
230 }
231
232 return ERROR_OK;
233 }
234
235 static bool linux_os_detect(struct target *target)
236 {
237 LOG_INFO("should no be called");
238 return false;
239 }
240
241 static int linux_os_smp_init(struct target *target);
242 static int linux_os_clean(struct target *target);
243 #define INIT_TASK 0
244 static const char * const linux_symbol_list[] = {
245 "init_task",
246 NULL
247 };
248
249 static int linux_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
250 {
251 unsigned int i;
252 *symbol_list = (symbol_table_elem_t *)
253 calloc(ARRAY_SIZE(linux_symbol_list), sizeof(symbol_table_elem_t));
254
255 for (i = 0; i < ARRAY_SIZE(linux_symbol_list); i++)
256 (*symbol_list)[i].symbol_name = linux_symbol_list[i];
257
258 return 0;
259 }
260
261 static char *linux_ps_command(struct target *target);
262
263 const struct rtos_type Linux_os = {
264 .name = "linux",
265 .detect_rtos = linux_os_detect,
266 .create = linux_os_create,
267 .smp_init = linux_os_smp_init,
268 .update_threads = linux_os_dummy_update,
269 .get_thread_reg_list = linux_os_thread_reg_list,
270 .get_symbol_list_to_lookup = linux_get_symbol_list_to_lookup,
271 .clean = linux_os_clean,
272 .ps_command = linux_ps_command,
273 };
274
275 static int linux_thread_packet(struct connection *connection, char const *packet,
276 int packet_size);
277 static void linux_identify_current_threads(struct target *target);
278
279 #ifdef PID_CHECK
280 int fill_task_pid(struct target *target, struct threads *t)
281 {
282 uint32_t pid_addr = t->base_addr + PID;
283 uint8_t buffer[4];
284 int retval = fill_buffer(target, pid_addr, buffer);
285
286 if (retval == ERROR_OK) {
287 uint32_t val = get_buffer(target, buffer);
288 t->pid = val;
289 } else
290 LOG_ERROR("fill_task_pid: unable to read memory");
291
292 return retval;
293 }
294 #endif
295
296 static int fill_task(struct target *target, struct threads *t)
297 {
298 int retval;
299 uint32_t pid_addr = t->base_addr + PID;
300 uint32_t mem_addr = t->base_addr + MEM;
301 uint32_t on_cpu = t->base_addr + ONCPU;
302 uint8_t *buffer = calloc(1, 4);
303 retval = fill_buffer(target, t->base_addr, buffer);
304
305 if (retval == ERROR_OK) {
306 uint32_t val = get_buffer(target, buffer);
307 t->state = val;
308 } else
309 LOG_ERROR("fill_task: unable to read memory");
310
311 retval = fill_buffer(target, pid_addr, buffer);
312
313 if (retval == ERROR_OK) {
314 uint32_t val = get_buffer(target, buffer);
315 t->pid = val;
316 } else
317 LOG_ERROR("fill task: unable to read memory");
318
319 retval = fill_buffer(target, on_cpu, buffer);
320
321 if (retval == ERROR_OK) {
322 uint32_t val = get_buffer(target, buffer);
323 t->oncpu = val;
324 } else
325 LOG_ERROR("fill task: unable to read memory");
326
327 retval = fill_buffer(target, mem_addr, buffer);
328
329 if (retval == ERROR_OK) {
330 uint32_t val = get_buffer(target, buffer);
331
332 if (val != 0) {
333 uint32_t asid_addr = val + MM_CTX;
334 retval = fill_buffer(target, asid_addr, buffer);
335
336 if (retval == ERROR_OK) {
337 val = get_buffer(target, buffer);
338 t->asid = val;
339 } else
340 LOG_ERROR
341 ("fill task: unable to read memory -- ASID");
342 } else
343 t->asid = 0;
344 } else
345 LOG_ERROR("fill task: unable to read memory");
346
347 free(buffer);
348
349 return retval;
350 }
351
352 static int get_name(struct target *target, struct threads *t)
353 {
354 int retval;
355 uint32_t full_name[4];
356 uint32_t comm = t->base_addr + COMM;
357 int i;
358
359 for (i = 0; i < 17; i++)
360 t->name[i] = 0;
361
362 retval = linux_read_memory(target, comm, 4, 4, (uint8_t *) full_name);
363
364 if (retval != ERROR_OK) {
365 LOG_ERROR("get_name: unable to read memory\n");
366 return ERROR_FAIL;
367 }
368
369 uint32_t raw_name = target_buffer_get_u32(target,
370 (const uint8_t *)
371 &full_name[0]);
372 t->name[3] = raw_name >> 24;
373 t->name[2] = raw_name >> 16;
374 t->name[1] = raw_name >> 8;
375 t->name[0] = raw_name;
376 raw_name =
377 target_buffer_get_u32(target, (const uint8_t *)&full_name[1]);
378 t->name[7] = raw_name >> 24;
379 t->name[6] = raw_name >> 16;
380 t->name[5] = raw_name >> 8;
381 t->name[4] = raw_name;
382 raw_name =
383 target_buffer_get_u32(target, (const uint8_t *)&full_name[2]);
384 t->name[11] = raw_name >> 24;
385 t->name[10] = raw_name >> 16;
386 t->name[9] = raw_name >> 8;
387 t->name[8] = raw_name;
388 raw_name =
389 target_buffer_get_u32(target, (const uint8_t *)&full_name[3]);
390 t->name[15] = raw_name >> 24;
391 t->name[14] = raw_name >> 16;
392 t->name[13] = raw_name >> 8;
393 t->name[12] = raw_name;
394 return ERROR_OK;
395
396 }
397
398 static int get_current(struct target *target, int create)
399 {
400 struct target_list *head;
401 head = target->head;
402 uint8_t *buf;
403 uint32_t val;
404 uint32_t ti_addr;
405 uint8_t *buffer = calloc(1, 4);
406 struct linux_os *linux_os = (struct linux_os *)
407 target->rtos->rtos_specific_params;
408 struct current_thread *ctt = linux_os->current_threads;
409
410 /* invalid current threads content */
411 while (ctt != NULL) {
412 ctt->threadid = -1;
413 ctt->TS = 0xdeadbeef;
414 ctt = ctt->next;
415 }
416
417 while (head != (struct target_list *)NULL) {
418 struct reg **reg_list;
419 int reg_list_size;
420 int retval;
421
422 if (target_get_gdb_reg_list(head->target, &reg_list,
423 &reg_list_size, REG_CLASS_GENERAL) != ERROR_OK) {
424 free(buffer);
425 return ERROR_TARGET_FAILURE;
426 }
427
428 if (!reg_list[13]->valid)
429 reg_list[13]->type->get(reg_list[13]);
430
431 buf = reg_list[13]->value;
432 val = get_buffer(target, buf);
433 ti_addr = (val & 0xffffe000);
434 uint32_t TS_addr = ti_addr + 0xc;
435 retval = fill_buffer(target, TS_addr, buffer);
436
437 if (retval == ERROR_OK) {
438 uint32_t TS = get_buffer(target, buffer);
439 uint32_t cpu, on_cpu = TS + ONCPU;
440 retval = fill_buffer(target, on_cpu, buffer);
441
442 if (retval == ERROR_OK) {
443 /*uint32_t cpu = get_buffer(target, buffer);*/
444 struct current_thread *ct =
445 linux_os->current_threads;
446 cpu = head->target->coreid;
447
448 while ((ct != NULL) && (ct->core_id != (int32_t) cpu))
449 ct = ct->next;
450
451 if ((ct != NULL) && (ct->TS == 0xdeadbeef))
452 ct->TS = TS;
453 else
454 LOG_ERROR
455 ("error in linux current thread update");
456
457 if (create && ct) {
458 struct threads *t;
459 t = calloc(1, sizeof(struct threads));
460 t->base_addr = ct->TS;
461 fill_task(target, t);
462 get_name(target, t);
463 t->oncpu = cpu;
464 insert_into_threadlist(target, t);
465 t->status = 3;
466 t->thread_info_addr = 0xdeadbeef;
467 ct->threadid = t->threadid;
468 linux_os->thread_count++;
469 #ifdef PID_CHECK
470 ct->pid = t->pid;
471 #endif
472 /*LOG_INFO("Creation of current thread %s",t->name);*/
473 }
474 }
475 }
476
477 free(reg_list);
478 head = head->next;
479 }
480
481 free(buffer);
482
483 return ERROR_OK;
484 }
485
486 static struct cpu_context *cpu_context_read(struct target *target, uint32_t base_addr,
487 uint32_t *thread_info_addr_old)
488 {
489 struct cpu_context *context = calloc(1, sizeof(struct cpu_context));
490 uint32_t preempt_count_addr = 0;
491 uint32_t registers[10];
492 uint8_t *buffer = calloc(1, 4);
493 uint32_t stack = base_addr + QAT;
494 uint32_t thread_info_addr = 0;
495 uint32_t thread_info_addr_update = 0;
496 int retval = ERROR_FAIL;
497 context->R4 = 0xdeadbeef;
498 context->R5 = 0xdeadbeef;
499 context->R6 = 0xdeadbeef;
500 context->R7 = 0xdeadbeef;
501 context->R8 = 0xdeadbeef;
502 context->R9 = 0xdeadbeef;
503 context->IP = 0xdeadbeef;
504 context->FP = 0xdeadbeef;
505 context->SP = 0xdeadbeef;
506 context->PC = 0xdeadbeef;
507 retry:
508
509 if (*thread_info_addr_old == 0xdeadbeef) {
510 retval = fill_buffer(target, stack, buffer);
511
512 if (retval == ERROR_OK)
513 thread_info_addr = get_buffer(target, buffer);
514 else
515 LOG_ERROR("cpu_context: unable to read memory");
516
517 thread_info_addr_update = thread_info_addr;
518 } else
519 thread_info_addr = *thread_info_addr_old;
520
521 preempt_count_addr = thread_info_addr + PREEMPT;
522 retval = fill_buffer(target, preempt_count_addr, buffer);
523
524 if (retval == ERROR_OK)
525 context->preempt_count = get_buffer(target, buffer);
526 else {
527 if (*thread_info_addr_old != 0xdeadbeef) {
528 LOG_ERROR
529 ("cpu_context: cannot read at thread_info_addr");
530
531 if (*thread_info_addr_old < LINUX_USER_KERNEL_BORDER)
532 LOG_INFO
533 ("cpu_context : thread_info_addr in userspace!!!");
534
535 *thread_info_addr_old = 0xdeadbeef;
536 goto retry;
537 }
538
539 LOG_ERROR("cpu_context: unable to read memory");
540 }
541
542 thread_info_addr += CPU_CONT;
543
544 retval = linux_read_memory(target, thread_info_addr, 4, 10,
545 (uint8_t *) registers);
546
547 if (retval != ERROR_OK) {
548 free(buffer);
549 LOG_ERROR("cpu_context: unable to read memory\n");
550 return context;
551 }
552
553 context->R4 =
554 target_buffer_get_u32(target, (const uint8_t *)&registers[0]);
555 context->R5 =
556 target_buffer_get_u32(target, (const uint8_t *)&registers[1]);
557 context->R6 =
558 target_buffer_get_u32(target, (const uint8_t *)&registers[2]);
559 context->R7 =
560 target_buffer_get_u32(target, (const uint8_t *)&registers[3]);
561 context->R8 =
562 target_buffer_get_u32(target, (const uint8_t *)&registers[4]);
563 context->R9 =
564 target_buffer_get_u32(target, (const uint8_t *)&registers[5]);
565 context->IP =
566 target_buffer_get_u32(target, (const uint8_t *)&registers[6]);
567 context->FP =
568 target_buffer_get_u32(target, (const uint8_t *)&registers[7]);
569 context->SP =
570 target_buffer_get_u32(target, (const uint8_t *)&registers[8]);
571 context->PC =
572 target_buffer_get_u32(target, (const uint8_t *)&registers[9]);
573
574 if (*thread_info_addr_old == 0xdeadbeef)
575 *thread_info_addr_old = thread_info_addr_update;
576
577 free(buffer);
578
579 return context;
580 }
581
582 static uint32_t next_task(struct target *target, struct threads *t)
583 {
584 uint8_t *buffer = calloc(1, 4);
585 uint32_t next_addr = t->base_addr + NEXT;
586 int retval = fill_buffer(target, next_addr, buffer);
587
588 if (retval == ERROR_OK) {
589 uint32_t val = get_buffer(target, buffer);
590 val = val - NEXT;
591 free(buffer);
592 return val;
593 } else
594 LOG_ERROR("next task: unable to read memory");
595
596 free(buffer);
597
598 return 0;
599 }
600
601 static struct current_thread *add_current_thread(struct current_thread *currents,
602 struct current_thread *ct)
603 {
604 ct->next = NULL;
605
606 if (currents == NULL) {
607 currents = ct;
608 return currents;
609 } else {
610 struct current_thread *temp = currents;
611
612 while (temp->next != NULL)
613 temp = temp->next;
614
615 temp->next = ct;
616 return currents;
617 }
618 }
619
620 static struct threads *liste_del_task(struct threads *task_list, struct threads **t,
621 struct threads *prev)
622 {
623 LOG_INFO("del task %" PRId64, (*t)->threadid);
624 if (prev)
625 prev->next = (*t)->next;
626 else
627 task_list = (*t)->next;
628
629 /* free content of threads */
630 free((*t)->context);
631
632 free(*t);
633 *t = prev ? prev : task_list;
634 return task_list;
635 }
636
637 static struct threads *liste_add_task(struct threads *task_list, struct threads *t,
638 struct threads **last)
639 {
640 t->next = NULL;
641
642 if (*last == NULL)
643 if (task_list == NULL) {
644 task_list = t;
645 return task_list;
646 } else {
647 struct threads *temp = task_list;
648
649 while (temp->next != NULL)
650 temp = temp->next;
651
652 temp->next = t;
653 *last = t;
654 return task_list;
655 } else {
656 (*last)->next = t;
657 *last = t;
658 return task_list;
659 }
660 }
661
662 #ifdef PID_CHECK
663 static int current_pid(struct linux_os *linux_os, uint32_t pid)
664 #else
665 static int current_base_addr(struct linux_os *linux_os, uint32_t base_addr)
666 #endif
667 {
668 struct current_thread *ct = linux_os->current_threads;
669 #ifdef PID_CHECK
670
671 while ((ct != NULL) && (ct->pid != pid))
672 #else
673 while ((ct != NULL) && (ct->TS != base_addr))
674 #endif
675 ct = ct->next;
676 #ifdef PID_CHECK
677 if ((ct != NULL) && (ct->pid == pid))
678 #else
679 if ((ct != NULL) && (ct->TS == base_addr))
680 #endif
681 return 1;
682
683 return 0;
684 }
685
686 static int linux_get_tasks(struct target *target, int context)
687 {
688 int loop = 0;
689 int retval = 0;
690 struct linux_os *linux_os = (struct linux_os *)
691 target->rtos->rtos_specific_params;
692 linux_os->thread_list = NULL;
693 linux_os->thread_count = 0;
694
695 if (linux_os->init_task_addr == 0xdeadbeef) {
696 LOG_INFO("no init symbol\n");
697 return ERROR_FAIL;
698 }
699
700 int64_t start = timeval_ms();
701
702 struct threads *t = calloc(1, sizeof(struct threads));
703 struct threads *last = NULL;
704 t->base_addr = linux_os->init_task_addr;
705 /* retrieve the thread id , currently running in the different smp core */
706 get_current(target, 1);
707
708 while (((t->base_addr != linux_os->init_task_addr) &&
709 (t->base_addr != 0)) || (loop == 0)) {
710 loop++;
711 fill_task(target, t);
712 retval = get_name(target, t);
713
714 if (loop > MAX_THREADS) {
715 free(t);
716 LOG_INFO("more than %d threads !!", MAX_THREADS);
717 return ERROR_FAIL;
718 }
719
720 if (retval != ERROR_OK) {
721 free(t);
722 return ERROR_FAIL;
723 }
724
725 /* check that this thread is not one the current threads already
726 * created */
727 uint32_t base_addr;
728 #ifdef PID_CHECK
729
730 if (!current_pid(linux_os, t->pid)) {
731 #else
732 if (!current_base_addr(linux_os, t->base_addr)) {
733 #endif
734 t->threadid = linux_os->threadid_count;
735 t->status = 1;
736 linux_os->threadid_count++;
737
738 linux_os->thread_list =
739 liste_add_task(linux_os->thread_list, t, &last);
740 /* no interest to fill the context if it is a current thread. */
741 linux_os->thread_count++;
742 t->thread_info_addr = 0xdeadbeef;
743
744 if (context)
745 t->context =
746 cpu_context_read(target, t->base_addr,
747 &t->thread_info_addr);
748 base_addr = next_task(target, t);
749 } else {
750 /*LOG_INFO("thread %s is a current thread already created",t->name); */
751 base_addr = next_task(target, t);
752 free(t);
753 }
754
755 t = calloc(1, sizeof(struct threads));
756 t->base_addr = base_addr;
757 }
758
759 linux_os->threads_lookup = 1;
760 linux_os->threads_needs_update = 0;
761 linux_os->preupdtate_threadid_count = linux_os->threadid_count - 1;
762 /* check that all current threads have been identified */
763
764 LOG_INFO("complete time %" PRId64 ", thread mean %" PRId64 "\n",
765 (timeval_ms() - start),
766 (timeval_ms() - start) / linux_os->threadid_count);
767
768 LOG_INFO("threadid count %d", linux_os->threadid_count);
769 free(t);
770
771 return ERROR_OK;
772 }
773
774 static int clean_threadlist(struct target *target)
775 {
776 struct linux_os *linux_os = (struct linux_os *)
777 target->rtos->rtos_specific_params;
778 struct threads *old, *temp = linux_os->thread_list;
779
780 while (temp != NULL) {
781 old = temp;
782
783 free(temp->context);
784
785 temp = temp->next;
786 free(old);
787 }
788
789 return ERROR_OK;
790 }
791
792 static int linux_os_clean(struct target *target)
793 {
794 struct linux_os *os_linux = (struct linux_os *)
795 target->rtos->rtos_specific_params;
796 clean_threadlist(target);
797 os_linux->init_task_addr = 0xdeadbeef;
798 os_linux->name = "linux";
799 os_linux->thread_list = NULL;
800 os_linux->thread_count = 0;
801 os_linux->nr_cpus = 0;
802 os_linux->threads_lookup = 0;
803 os_linux->threads_needs_update = 0;
804 os_linux->threadid_count = 1;
805 return ERROR_OK;
806 }
807
808 static int insert_into_threadlist(struct target *target, struct threads *t)
809 {
810 struct linux_os *linux_os = (struct linux_os *)
811 target->rtos->rtos_specific_params;
812 struct threads *temp = linux_os->thread_list;
813 t->threadid = linux_os->threadid_count;
814 linux_os->threadid_count++;
815 t->status = 1;
816 t->next = NULL;
817
818 if (temp == NULL)
819 linux_os->thread_list = t;
820 else {
821 while (temp->next != NULL)
822 temp = temp->next;
823
824 t->next = NULL;
825 temp->next = t;
826 }
827
828 return ERROR_OK;
829 }
830
831 static void linux_identify_current_threads(struct target *target)
832 {
833 struct linux_os *linux_os = (struct linux_os *)
834 target->rtos->rtos_specific_params;
835 struct threads *thread_list = linux_os->thread_list;
836 struct current_thread *ct = linux_os->current_threads;
837 struct threads *t = NULL;
838
839 while ((ct != NULL)) {
840 if (ct->threadid == -1) {
841
842 /* un-identified thread */
843 int found = 0;
844 t = calloc(1, sizeof(struct threads));
845 t->base_addr = ct->TS;
846 #ifdef PID_CHECK
847
848 if (fill_task_pid(target, t) != ERROR_OK) {
849 error_handling:
850 free(t);
851 LOG_ERROR
852 ("linux identify_current_threads: unable to read pid");
853 return;
854 }
855 #endif
856
857 /* search in the list of threads if pid
858 already present */
859 while ((thread_list != NULL) && (found == 0)) {
860 #ifdef PID_CHECK
861 if (thread_list->pid == t->pid) {
862 #else
863 if (thread_list->base_addr == t->base_addr) {
864 #endif
865 free(t);
866 t = thread_list;
867 found = 1;
868 }
869 thread_list = thread_list->next;
870 }
871
872 if (!found) {
873 /* it is a new thread */
874 if (fill_task(target, t) != ERROR_OK)
875 goto error_handling;
876
877 get_name(target, t);
878 insert_into_threadlist(target, t);
879 t->thread_info_addr = 0xdeadbeef;
880 }
881
882 t->status = 3;
883 ct->threadid = t->threadid;
884 #ifdef PID_CHECK
885 ct->pid = t->pid;
886 #endif
887 linux_os->thread_count++;
888 #if 0
889 if (found == 0)
890 LOG_INFO("current thread core %x identified %s",
891 ct->core_id, t->name);
892 else
893 LOG_INFO("current thread core %x, reused %s",
894 ct->core_id, t->name);
895 #endif
896 }
897 #if 0
898 else {
899 struct threads tmp;
900 tmp.base_addr = ct->TS;
901 get_name(target, &tmp);
902 LOG_INFO("current thread core %x , already identified %s !!!",
903 ct->core_id, tmp.name);
904 }
905 #endif
906 ct = ct->next;
907 }
908
909 return;
910 #ifndef PID_CHECK
911 error_handling:
912 free(t);
913 LOG_ERROR("unable to read pid");
914 return;
915
916 #endif
917 }
918
919 static int linux_task_update(struct target *target, int context)
920 {
921 struct linux_os *linux_os = (struct linux_os *)
922 target->rtos->rtos_specific_params;
923 struct threads *thread_list = linux_os->thread_list;
924 int retval;
925 int loop = 0;
926 linux_os->thread_count = 0;
927
928 /*thread_list = thread_list->next; skip init_task*/
929 while (thread_list != NULL) {
930 thread_list->status = 0; /*setting all tasks to dead state*/
931
932 free(thread_list->context);
933 thread_list->context = NULL;
934
935 thread_list = thread_list->next;
936 }
937
938 int found = 0;
939
940 if (linux_os->init_task_addr == 0xdeadbeef) {
941 LOG_INFO("no init symbol\n");
942 return ERROR_FAIL;
943 }
944 int64_t start = timeval_ms();
945 struct threads *t = calloc(1, sizeof(struct threads));
946 uint32_t previous = 0xdeadbeef;
947 t->base_addr = linux_os->init_task_addr;
948 retval = get_current(target, 0);
949 /*check that all current threads have been identified */
950 linux_identify_current_threads(target);
951
952 while (((t->base_addr != linux_os->init_task_addr) &&
953 (t->base_addr != previous)) || (loop == 0)) {
954 /* for avoiding any permanent loop for any reason possibly due to
955 * target */
956 loop++;
957 previous = t->base_addr;
958 /* read only pid */
959 #ifdef PID_CHECK
960 retval = fill_task_pid(target, t);
961 #endif
962
963 if (retval != ERROR_OK) {
964 free(t);
965 return ERROR_FAIL;
966 }
967
968 thread_list = linux_os->thread_list;
969
970 while (thread_list != NULL) {
971 #ifdef PID_CHECK
972 if (t->pid == thread_list->pid) {
973 #else
974 if (t->base_addr == thread_list->base_addr) {
975 #endif
976 if (!thread_list->status) {
977 #ifdef PID_CHECK
978 if (t->base_addr != thread_list->base_addr)
979 LOG_INFO("thread base_addr has changed !!");
980 #endif
981 /* this is not a current thread */
982 thread_list->base_addr = t->base_addr;
983 thread_list->status = 1;
984
985 /* we don 't update this field any more */
986
987 /*thread_list->state = t->state;
988 thread_list->oncpu = t->oncpu;
989 thread_list->asid = t->asid;
990 */
991 if (context)
992 thread_list->context =
993 cpu_context_read(target,
994 thread_list->base_addr,
995 &thread_list->thread_info_addr);
996 } else {
997 /* it is a current thread no need to read context */
998 }
999
1000 linux_os->thread_count++;
1001 found = 1;
1002 break;
1003 } else {
1004 found = 0;
1005 thread_list = thread_list->next;
1006 }
1007 }
1008
1009 if (found == 0) {
1010 uint32_t base_addr;
1011 fill_task(target, t);
1012 get_name(target, t);
1013 retval = insert_into_threadlist(target, t);
1014 t->thread_info_addr = 0xdeadbeef;
1015
1016 if (context)
1017 t->context =
1018 cpu_context_read(target, t->base_addr,
1019 &t->thread_info_addr);
1020
1021 base_addr = next_task(target, t);
1022 t = calloc(1, sizeof(struct threads));
1023 t->base_addr = base_addr;
1024 linux_os->thread_count++;
1025 } else
1026 t->base_addr = next_task(target, t);
1027 }
1028
1029 LOG_INFO("update thread done %" PRId64 ", mean%" PRId64 "\n",
1030 (timeval_ms() - start), (timeval_ms() - start) / loop);
1031 free(t);
1032 linux_os->threads_needs_update = 0;
1033 return ERROR_OK;
1034 }
1035
1036 static int linux_gdb_thread_packet(struct target *target,
1037 struct connection *connection, char const *packet,
1038 int packet_size)
1039 {
1040 int retval;
1041 struct linux_os *linux_os =
1042 (struct linux_os *)target->rtos->rtos_specific_params;
1043
1044 if (linux_os->init_task_addr == 0xdeadbeef) {
1045 /* it has not been initialized */
1046 LOG_INFO("received thread request without init task address");
1047 gdb_put_packet(connection, "l", 1);
1048 return ERROR_OK;
1049 }
1050
1051 retval = linux_get_tasks(target, 1);
1052
1053 if (retval != ERROR_OK)
1054 return ERROR_TARGET_FAILURE;
1055
1056 char *out_str = calloc(MAX_THREADS * 17 + 10, 1);
1057 char *tmp_str = out_str;
1058 tmp_str += sprintf(tmp_str, "m");
1059 struct threads *temp = linux_os->thread_list;
1060
1061 while (temp != NULL) {
1062 tmp_str += sprintf(tmp_str, "%016" PRIx64, temp->threadid);
1063 temp = temp->next;
1064 if (temp)
1065 tmp_str += sprintf(tmp_str, ",");
1066 }
1067
1068 gdb_put_packet(connection, out_str, strlen(out_str));
1069 free(out_str);
1070 return ERROR_OK;
1071 }
1072
1073 static int linux_gdb_thread_update(struct target *target,
1074 struct connection *connection, char const *packet,
1075 int packet_size)
1076 {
1077 int found = 0;
1078 struct linux_os *linux_os = (struct linux_os *)
1079 target->rtos->rtos_specific_params;
1080 struct threads *temp = linux_os->thread_list;
1081
1082 while (temp != NULL) {
1083 if (temp->threadid == linux_os->preupdtate_threadid_count + 1) {
1084 /*LOG_INFO("FOUND");*/
1085 found = 1;
1086 break;
1087 } else
1088 temp = temp->next;
1089 }
1090
1091 if (found == 1) {
1092 /*LOG_INFO("INTO GDB THREAD UPDATE FOUNDING START TASK");*/
1093 char *out_strr = calloc(MAX_THREADS * 17 + 10, 1);
1094 char *tmp_strr = out_strr;
1095 tmp_strr += sprintf(tmp_strr, "m");
1096 /*LOG_INFO("CHAR MALLOC & M DONE");*/
1097 tmp_strr += sprintf(tmp_strr, "%016" PRIx64, temp->threadid);
1098
1099 temp = temp->next;
1100
1101 while (temp != NULL) {
1102 /*LOG_INFO("INTO GDB THREAD UPDATE WHILE");*/
1103 tmp_strr += sprintf(tmp_strr, ",");
1104 tmp_strr +=
1105 sprintf(tmp_strr, "%016" PRIx64, temp->threadid);
1106 temp = temp->next;
1107 }
1108
1109 /*tmp_str[0] = 0;*/
1110 gdb_put_packet(connection, out_strr, strlen(out_strr));
1111 linux_os->preupdtate_threadid_count =
1112 linux_os->threadid_count - 1;
1113 free(out_strr);
1114 } else
1115 gdb_put_packet(connection, "l", 1);
1116
1117 return ERROR_OK;
1118 }
1119
1120 static int linux_thread_extra_info(struct target *target,
1121 struct connection *connection, char const *packet,
1122 int packet_size)
1123 {
1124 int64_t threadid = 0;
1125 struct linux_os *linux_os = (struct linux_os *)
1126 target->rtos->rtos_specific_params;
1127 sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid);
1128 /*LOG_INFO("lookup extra info for thread %" SCNx64, threadid);*/
1129 struct threads *temp = linux_os->thread_list;
1130
1131 while (temp != NULL) {
1132 if (temp->threadid == threadid) {
1133 char *pid = " PID: ";
1134 char *pid_current = "*PID: ";
1135 char *name = "Name: ";
1136 int str_size = strlen(pid) + strlen(name);
1137 char *tmp_str = calloc(1, str_size + 50);
1138 char *tmp_str_ptr = tmp_str;
1139
1140 /* discriminate current task */
1141 if (temp->status == 3)
1142 tmp_str_ptr += sprintf(tmp_str_ptr, "%s",
1143 pid_current);
1144 else
1145 tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid);
1146
1147 tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid);
1148 sprintf(tmp_str_ptr, "%s", name);
1149 sprintf(tmp_str_ptr, "%s", temp->name);
1150 char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1);
1151 size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str,
1152 strlen(tmp_str), strlen(tmp_str) * 2 + 1);
1153 gdb_put_packet(connection, hex_str, pkt_len);
1154 free(hex_str);
1155 free(tmp_str);
1156 return ERROR_OK;
1157 }
1158
1159 temp = temp->next;
1160 }
1161
1162 LOG_INFO("thread not found");
1163 return ERROR_OK;
1164 }
1165
1166 static int linux_gdb_T_packet(struct connection *connection,
1167 struct target *target, char const *packet, int packet_size)
1168 {
1169 int64_t threadid;
1170 struct linux_os *linux_os = (struct linux_os *)
1171 target->rtos->rtos_specific_params;
1172 int retval = ERROR_OK;
1173 sscanf(packet, "T%" SCNx64, &threadid);
1174
1175 if (linux_os->threads_needs_update == 0) {
1176 struct threads *temp = linux_os->thread_list;
1177 struct threads *prev = NULL;
1178
1179 while (temp != NULL) {
1180 if (temp->threadid == threadid) {
1181 if (temp->status != 0) {
1182 gdb_put_packet(connection, "OK", 2);
1183 return ERROR_OK;
1184 } else {
1185 /* delete item in the list */
1186 linux_os->thread_list =
1187 liste_del_task(linux_os->thread_list,
1188 &temp, prev);
1189 linux_os->thread_count--;
1190 gdb_put_packet(connection, "E01", 3);
1191 return ERROR_OK;
1192 }
1193 }
1194
1195 /* for deletion */
1196 prev = temp;
1197 temp = temp->next;
1198 }
1199
1200 LOG_INFO("gdb requested status on non existing thread");
1201 gdb_put_packet(connection, "E01", 3);
1202 return ERROR_OK;
1203
1204 } else {
1205 retval = linux_task_update(target, 1);
1206 struct threads *temp = linux_os->thread_list;
1207
1208 while (temp != NULL) {
1209 if (temp->threadid == threadid) {
1210 if (temp->status == 1) {
1211 gdb_put_packet(connection, "OK", 2);
1212 return ERROR_OK;
1213 } else {
1214 gdb_put_packet(connection, "E01", 3);
1215 return ERROR_OK;
1216 }
1217 }
1218
1219 temp = temp->next;
1220 }
1221 }
1222
1223 return retval;
1224 }
1225
1226 static int linux_gdb_h_packet(struct connection *connection,
1227 struct target *target, char const *packet, int packet_size)
1228 {
1229 struct linux_os *linux_os = (struct linux_os *)
1230 target->rtos->rtos_specific_params;
1231 struct current_thread *ct = linux_os->current_threads;
1232
1233 /* select to display the current thread of the selected target */
1234 while ((ct != NULL) && (ct->core_id != target->coreid))
1235 ct = ct->next;
1236
1237 int64_t current_gdb_thread_rq;
1238
1239 if (linux_os->threads_lookup == 1) {
1240 if ((ct != NULL) && (ct->threadid == -1)) {
1241 ct = linux_os->current_threads;
1242
1243 while ((ct != NULL) && (ct->threadid == -1))
1244 ct = ct->next;
1245 }
1246
1247 if (ct == NULL) {
1248 /* no current thread can be identified
1249 * any way with smp */
1250 LOG_INFO("no current thread identified");
1251 /* attempt to display the name of the 2 threads identified with
1252 * get_current */
1253 struct threads t;
1254 ct = linux_os->current_threads;
1255
1256 while ((ct != NULL) && (ct->threadid == -1)) {
1257 t.base_addr = ct->TS;
1258 get_name(target, &t);
1259 LOG_INFO("name of unidentified thread %s",
1260 t.name);
1261 ct = ct->next;
1262 }
1263
1264 gdb_put_packet(connection, "OK", 2);
1265 return ERROR_OK;
1266 }
1267
1268 if (packet[1] == 'g') {
1269 sscanf(packet, "Hg%16" SCNx64, &current_gdb_thread_rq);
1270
1271 if (current_gdb_thread_rq == 0) {
1272 target->rtos->current_threadid = ct->threadid;
1273 gdb_put_packet(connection, "OK", 2);
1274 } else {
1275 target->rtos->current_threadid =
1276 current_gdb_thread_rq;
1277 gdb_put_packet(connection, "OK", 2);
1278 }
1279 } else if (packet[1] == 'c') {
1280 sscanf(packet, "Hc%16" SCNx64, &current_gdb_thread_rq);
1281
1282 if ((current_gdb_thread_rq == 0) ||
1283 (current_gdb_thread_rq == ct->threadid)) {
1284 target->rtos->current_threadid = ct->threadid;
1285 gdb_put_packet(connection, "OK", 2);
1286 } else
1287 gdb_put_packet(connection, "E01", 3);
1288 }
1289 } else
1290 gdb_put_packet(connection, "OK", 2);
1291
1292 return ERROR_OK;
1293 }
1294
1295 static int linux_thread_packet(struct connection *connection, char const *packet,
1296 int packet_size)
1297 {
1298 int retval = ERROR_OK;
1299 struct current_thread *ct;
1300 struct target *target = get_target_from_connection(connection);
1301 struct linux_os *linux_os = (struct linux_os *)
1302 target->rtos->rtos_specific_params;
1303
1304 switch (packet[0]) {
1305 case 'T': /* Is thread alive?*/
1306
1307 linux_gdb_T_packet(connection, target, packet, packet_size);
1308 break;
1309 case 'H': /* Set current thread */
1310 /* ( 'c' for step and continue, 'g' for all other operations )*/
1311 /*LOG_INFO(" H packet received '%s'", packet);*/
1312 linux_gdb_h_packet(connection, target, packet, packet_size);
1313 break;
1314 case 'q':
1315
1316 if (strncmp(packet, "qSymbol", 7) == 0) {
1317 if (rtos_qsymbol(connection, packet, packet_size) == 1) {
1318 linux_compute_virt2phys(target,
1319 target->rtos->symbols[INIT_TASK].address);
1320 }
1321
1322 break;
1323 } else if (strncmp(packet, "qfThreadInfo", 12) == 0) {
1324 if (linux_os->thread_list == NULL) {
1325 retval = linux_gdb_thread_packet(target,
1326 connection,
1327 packet,
1328 packet_size);
1329 break;
1330 } else {
1331 retval = linux_gdb_thread_update(target,
1332 connection,
1333 packet,
1334 packet_size);
1335 break;
1336 }
1337 } else if (strncmp(packet, "qsThreadInfo", 12) == 0) {
1338 gdb_put_packet(connection, "l", 1);
1339 break;
1340 } else if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) {
1341 linux_thread_extra_info(target, connection, packet,
1342 packet_size);
1343 break;
1344 } else {
1345 retval = GDB_THREAD_PACKET_NOT_CONSUMED;
1346 break;
1347 }
1348
1349 case 'Q':
1350 /* previously response was : thread not found
1351 * gdb_put_packet(connection, "E01", 3); */
1352 retval = GDB_THREAD_PACKET_NOT_CONSUMED;
1353 break;
1354 case 'c':
1355 case 's': {
1356 if (linux_os->threads_lookup == 1) {
1357 ct = linux_os->current_threads;
1358
1359 while ((ct != NULL) && (ct->core_id) != target->coreid)
1360 ct = ct->next;
1361
1362 if ((ct != NULL) && (ct->threadid == -1)) {
1363 ct = linux_os->current_threads;
1364
1365 while ((ct != NULL) && (ct->threadid == -1))
1366 ct = ct->next;
1367 }
1368
1369 if ((ct != NULL) && (ct->threadid !=
1370 target->rtos->current_threadid)
1371 && (target->rtos->current_threadid != -1))
1372 LOG_WARNING("WARNING! current GDB thread do not match "
1373 "current thread running. "
1374 "Switch thread in GDB to threadid %d",
1375 (int)ct->threadid);
1376
1377 LOG_INFO("threads_needs_update = 1");
1378 linux_os->threads_needs_update = 1;
1379 }
1380 }
1381
1382 /* if a packet handler returned an error, exit input loop */
1383 if (retval != ERROR_OK)
1384 return retval;
1385 }
1386
1387 return retval;
1388 }
1389
1390 static int linux_os_smp_init(struct target *target)
1391 {
1392 struct target_list *head;
1393 /* keep only target->rtos */
1394 struct rtos *rtos = target->rtos;
1395 struct linux_os *os_linux =
1396 (struct linux_os *)rtos->rtos_specific_params;
1397 struct current_thread *ct;
1398 head = target->head;
1399
1400 while (head != (struct target_list *)NULL) {
1401 if (head->target->rtos != rtos) {
1402 struct linux_os *smp_os_linux =
1403 (struct linux_os *)head->target->rtos->rtos_specific_params;
1404 /* remap smp target on rtos */
1405 free(head->target->rtos);
1406 head->target->rtos = rtos;
1407 /* reuse allocated ct */
1408 ct = smp_os_linux->current_threads;
1409 ct->threadid = -1;
1410 ct->TS = 0xdeadbeef;
1411 ct->core_id = head->target->coreid;
1412 os_linux->current_threads =
1413 add_current_thread(os_linux->current_threads, ct);
1414 os_linux->nr_cpus++;
1415 free(smp_os_linux);
1416 }
1417
1418 head = head->next;
1419 }
1420
1421 return ERROR_OK;
1422 }
1423
1424 static int linux_os_create(struct target *target)
1425 {
1426 struct linux_os *os_linux = calloc(1, sizeof(struct linux_os));
1427 struct current_thread *ct = calloc(1, sizeof(struct current_thread));
1428 LOG_INFO("linux os creation\n");
1429 os_linux->init_task_addr = 0xdeadbeef;
1430 os_linux->name = "linux";
1431 os_linux->thread_list = NULL;
1432 os_linux->thread_count = 0;
1433 target->rtos->current_threadid = -1;
1434 os_linux->nr_cpus = 1;
1435 os_linux->threads_lookup = 0;
1436 os_linux->threads_needs_update = 0;
1437 os_linux->threadid_count = 1;
1438 os_linux->current_threads = NULL;
1439 target->rtos->rtos_specific_params = os_linux;
1440 ct->core_id = target->coreid;
1441 ct->threadid = -1;
1442 ct->TS = 0xdeadbeef;
1443 os_linux->current_threads =
1444 add_current_thread(os_linux->current_threads, ct);
1445 /* overload rtos thread default handler */
1446 target->rtos->gdb_thread_packet = linux_thread_packet;
1447 /* initialize a default virt 2 phys translation */
1448 os_linux->phys_mask = ~0xc0000000;
1449 os_linux->phys_base = 0x0;
1450 return JIM_OK;
1451 }
1452
1453 static char *linux_ps_command(struct target *target)
1454 {
1455 struct linux_os *linux_os = (struct linux_os *)
1456 target->rtos->rtos_specific_params;
1457 int retval = ERROR_OK;
1458 char *display;
1459
1460 if (linux_os->threads_lookup == 0)
1461 retval = linux_get_tasks(target, 1);
1462 else {
1463 if (linux_os->threads_needs_update != 0)
1464 retval = linux_task_update(target, 0);
1465 }
1466
1467 if (retval == ERROR_OK) {
1468 struct threads *temp = linux_os->thread_list;
1469 char *tmp;
1470 LOG_INFO("allocation for %d threads line",
1471 linux_os->thread_count);
1472 display = calloc((linux_os->thread_count + 2) * 80, 1);
1473
1474 if (!display)
1475 goto error;
1476
1477 tmp = display;
1478 tmp += sprintf(tmp, "PID\t\tCPU\t\tASID\t\tNAME\n");
1479 tmp += sprintf(tmp, "---\t\t---\t\t----\t\t----\n");
1480
1481 while (temp != NULL) {
1482 if (temp->status) {
1483 if (temp->context)
1484 tmp +=
1485 sprintf(tmp,
1486 "%" PRIu32 "\t\t%" PRIu32 "\t\t%" PRIx32 "\t\t%s\n",
1487 temp->pid, temp->oncpu,
1488 temp->asid, temp->name);
1489 else
1490 tmp +=
1491 sprintf(tmp,
1492 "%" PRIu32 "\t\t%" PRIu32 "\t\t%" PRIx32 "\t\t%s\n",
1493 temp->pid, temp->oncpu,
1494 temp->asid, temp->name);
1495 }
1496
1497 temp = temp->next;
1498 }
1499
1500 return display;
1501 }
1502
1503 error:
1504 display = calloc(40, 1);
1505 sprintf(display, "linux_ps_command failed\n");
1506 return display;
1507 }

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)