9e59c41a52372843349ba238f83d7cdf3c2a88ad
[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 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 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 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 perfom 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 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 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 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 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 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 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 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 if ((*t)->context)
631 free((*t)->context);
632
633 free(*t);
634 *t = prev ? prev : task_list;
635 return task_list;
636 }
637
638 struct threads *liste_add_task(struct threads *task_list, struct threads *t,
639 struct threads **last)
640 {
641 t->next = NULL;
642
643 if (*last == NULL)
644 if (task_list == NULL) {
645 task_list = t;
646 return task_list;
647 } else {
648 struct threads *temp = task_list;
649
650 while (temp->next != NULL)
651 temp = temp->next;
652
653 temp->next = t;
654 *last = t;
655 return task_list;
656 } else {
657 (*last)->next = t;
658 *last = t;
659 return task_list;
660 }
661 }
662
663 #ifdef PID_CHECK
664 static int current_pid(struct linux_os *linux_os, uint32_t pid)
665 #else
666 static int current_base_addr(struct linux_os *linux_os, uint32_t base_addr)
667 #endif
668 {
669 struct current_thread *ct = linux_os->current_threads;
670 #ifdef PID_CHECK
671
672 while ((ct != NULL) && (ct->pid != pid))
673 #else
674 while ((ct != NULL) && (ct->TS != base_addr))
675 #endif
676 ct = ct->next;
677 #ifdef PID_CHECK
678 if ((ct != NULL) && (ct->pid == pid))
679 #else
680 if ((ct != NULL) && (ct->TS == base_addr))
681 #endif
682 return 1;
683
684 return 0;
685 }
686
687 int linux_get_tasks(struct target *target, int context)
688 {
689 int loop = 0;
690 int retval = 0;
691 struct linux_os *linux_os = (struct linux_os *)
692 target->rtos->rtos_specific_params;
693 linux_os->thread_list = NULL;
694 linux_os->thread_count = 0;
695
696 if (linux_os->init_task_addr == 0xdeadbeef) {
697 LOG_INFO("no init symbol\n");
698 return ERROR_FAIL;
699 }
700
701 int64_t start = timeval_ms();
702
703 struct threads *t = calloc(1, sizeof(struct threads));
704 struct threads *last = NULL;
705 t->base_addr = linux_os->init_task_addr;
706 /* retrieve the thread id , currently running in the different smp core */
707 get_current(target, 1);
708
709 while (((t->base_addr != linux_os->init_task_addr) &&
710 (t->base_addr != 0)) || (loop == 0)) {
711 loop++;
712 fill_task(target, t);
713 retval = get_name(target, t);
714
715 if (loop > MAX_THREADS) {
716 free(t);
717 LOG_INFO("more than %d threads !!", MAX_THREADS);
718 return ERROR_FAIL;
719 }
720
721 if (retval != ERROR_OK) {
722 free(t);
723 return ERROR_FAIL;
724 }
725
726 /* check that this thread is not one the current threads already
727 * created */
728 uint32_t base_addr;
729 #ifdef PID_CHECK
730
731 if (!current_pid(linux_os, t->pid)) {
732 #else
733 if (!current_base_addr(linux_os, t->base_addr)) {
734 #endif
735 t->threadid = linux_os->threadid_count;
736 t->status = 1;
737 linux_os->threadid_count++;
738
739 linux_os->thread_list =
740 liste_add_task(linux_os->thread_list, t, &last);
741 /* no interest to fill the context if it is a current thread. */
742 linux_os->thread_count++;
743 t->thread_info_addr = 0xdeadbeef;
744
745 if (context)
746 t->context =
747 cpu_context_read(target, t->base_addr,
748 &t->thread_info_addr);
749 base_addr = next_task(target, t);
750 } else {
751 /*LOG_INFO("thread %s is a current thread already created",t->name); */
752 base_addr = next_task(target, t);
753 free(t);
754 }
755
756 t = calloc(1, sizeof(struct threads));
757 t->base_addr = base_addr;
758 }
759
760 linux_os->threads_lookup = 1;
761 linux_os->threads_needs_update = 0;
762 linux_os->preupdtate_threadid_count = linux_os->threadid_count - 1;
763 /* check that all current threads have been identified */
764
765 LOG_INFO("complete time %" PRId64 ", thread mean %" PRId64 "\n",
766 (timeval_ms() - start),
767 (timeval_ms() - start) / linux_os->threadid_count);
768
769 LOG_INFO("threadid count %d", linux_os->threadid_count);
770 free(t);
771
772 return ERROR_OK;
773 }
774
775 static int clean_threadlist(struct target *target)
776 {
777 struct linux_os *linux_os = (struct linux_os *)
778 target->rtos->rtos_specific_params;
779 struct threads *old, *temp = linux_os->thread_list;
780
781 while (temp != NULL) {
782 old = temp;
783
784 if (temp->context)
785 free(temp->context);
786
787 temp = temp->next;
788 free(old);
789 }
790
791 return ERROR_OK;
792 }
793
794 static int linux_os_clean(struct target *target)
795 {
796 struct linux_os *os_linux = (struct linux_os *)
797 target->rtos->rtos_specific_params;
798 clean_threadlist(target);
799 os_linux->init_task_addr = 0xdeadbeef;
800 os_linux->name = "linux";
801 os_linux->thread_list = NULL;
802 os_linux->thread_count = 0;
803 os_linux->nr_cpus = 0;
804 os_linux->threads_lookup = 0;
805 os_linux->threads_needs_update = 0;
806 os_linux->threadid_count = 1;
807 return ERROR_OK;
808 }
809
810 static int insert_into_threadlist(struct target *target, struct threads *t)
811 {
812 struct linux_os *linux_os = (struct linux_os *)
813 target->rtos->rtos_specific_params;
814 struct threads *temp = linux_os->thread_list;
815 t->threadid = linux_os->threadid_count;
816 linux_os->threadid_count++;
817 t->status = 1;
818 t->next = NULL;
819
820 if (temp == NULL)
821 linux_os->thread_list = t;
822 else {
823 while (temp->next != NULL)
824 temp = temp->next;
825
826 t->next = NULL;
827 temp->next = t;
828 }
829
830 return ERROR_OK;
831 }
832
833 static void linux_identify_current_threads(struct target *target)
834 {
835 struct linux_os *linux_os = (struct linux_os *)
836 target->rtos->rtos_specific_params;
837 struct threads *thread_list = linux_os->thread_list;
838 struct current_thread *ct = linux_os->current_threads;
839 struct threads *t = NULL;
840
841 while ((ct != NULL)) {
842 if (ct->threadid == -1) {
843
844 /* un-identified thread */
845 int found = 0;
846 t = calloc(1, sizeof(struct threads));
847 t->base_addr = ct->TS;
848 #ifdef PID_CHECK
849
850 if (fill_task_pid(target, t) != ERROR_OK) {
851 error_handling:
852 free(t);
853 LOG_ERROR
854 ("linux identify_current_threads: unable to read pid");
855 return;
856 }
857 #endif
858
859 /* search in the list of threads if pid
860 already present */
861 while ((thread_list != NULL) && (found == 0)) {
862 #ifdef PID_CHECK
863 if (thread_list->pid == t->pid) {
864 #else
865 if (thread_list->base_addr == t->base_addr) {
866 #endif
867 free(t);
868 t = thread_list;
869 found = 1;
870 }
871 thread_list = thread_list->next;
872 }
873
874 if (!found) {
875 /* it is a new thread */
876 if (fill_task(target, t) != ERROR_OK)
877 goto error_handling;
878
879 get_name(target, t);
880 insert_into_threadlist(target, t);
881 t->thread_info_addr = 0xdeadbeef;
882 }
883
884 t->status = 3;
885 ct->threadid = t->threadid;
886 #ifdef PID_CHECK
887 ct->pid = t->pid;
888 #endif
889 linux_os->thread_count++;
890 #if 0
891 if (found == 0)
892 LOG_INFO("current thread core %x identified %s",
893 ct->core_id, t->name);
894 else
895 LOG_INFO("current thread core %x, reused %s",
896 ct->core_id, t->name);
897 #endif
898 }
899 #if 0
900 else {
901 struct threads tmp;
902 tmp.base_addr = ct->TS;
903 get_name(target, &tmp);
904 LOG_INFO("current thread core %x , already identified %s !!!",
905 ct->core_id, tmp.name);
906 }
907 #endif
908 ct = ct->next;
909 }
910
911 return;
912 #ifndef PID_CHECK
913 error_handling:
914 free(t);
915 LOG_ERROR("unable to read pid");
916 return;
917
918 #endif
919 }
920
921 static int linux_task_update(struct target *target, int context)
922 {
923 struct linux_os *linux_os = (struct linux_os *)
924 target->rtos->rtos_specific_params;
925 struct threads *thread_list = linux_os->thread_list;
926 int retval;
927 int loop = 0;
928 linux_os->thread_count = 0;
929
930 /*thread_list = thread_list->next; skip init_task*/
931 while (thread_list != NULL) {
932 thread_list->status = 0; /*setting all tasks to dead state*/
933
934 if (thread_list->context) {
935 free(thread_list->context);
936 thread_list->context = NULL;
937 }
938
939 thread_list = thread_list->next;
940 }
941
942 int found = 0;
943
944 if (linux_os->init_task_addr == 0xdeadbeef) {
945 LOG_INFO("no init symbol\n");
946 return ERROR_FAIL;
947 }
948 int64_t start = timeval_ms();
949 struct threads *t = calloc(1, sizeof(struct threads));
950 uint32_t previous = 0xdeadbeef;
951 t->base_addr = linux_os->init_task_addr;
952 retval = get_current(target, 0);
953 /*check that all current threads have been identified */
954 linux_identify_current_threads(target);
955
956 while (((t->base_addr != linux_os->init_task_addr) &&
957 (t->base_addr != previous)) || (loop == 0)) {
958 /* for avoiding any permanent loop for any reason possibly due to
959 * target */
960 loop++;
961 previous = t->base_addr;
962 /* read only pid */
963 #ifdef PID_CHECK
964 retval = fill_task_pid(target, t);
965 #endif
966
967 if (retval != ERROR_OK) {
968 free(t);
969 return ERROR_FAIL;
970 }
971
972 thread_list = linux_os->thread_list;
973
974 while (thread_list != NULL) {
975 #ifdef PID_CHECK
976 if (t->pid == thread_list->pid) {
977 #else
978 if (t->base_addr == thread_list->base_addr) {
979 #endif
980 if (!thread_list->status) {
981 #ifdef PID_CHECK
982 if (t->base_addr != thread_list->base_addr)
983 LOG_INFO("thread base_addr has changed !!");
984 #endif
985 /* this is not a current thread */
986 thread_list->base_addr = t->base_addr;
987 thread_list->status = 1;
988
989 /* we don 't update this field any more */
990
991 /*thread_list->state = t->state;
992 thread_list->oncpu = t->oncpu;
993 thread_list->asid = t->asid;
994 */
995 if (context)
996 thread_list->context =
997 cpu_context_read(target,
998 thread_list->
999 base_addr,
1000 &thread_list->
1001 thread_info_addr);
1002 } else {
1003 /* it is a current thread no need to read context */
1004 }
1005
1006 linux_os->thread_count++;
1007 found = 1;
1008 break;
1009 } else {
1010 found = 0;
1011 thread_list = thread_list->next;
1012 }
1013 }
1014
1015 if (found == 0) {
1016 uint32_t base_addr;
1017 fill_task(target, t);
1018 get_name(target, t);
1019 retval = insert_into_threadlist(target, t);
1020 t->thread_info_addr = 0xdeadbeef;
1021
1022 if (context)
1023 t->context =
1024 cpu_context_read(target, t->base_addr,
1025 &t->thread_info_addr);
1026
1027 base_addr = next_task(target, t);
1028 t = calloc(1, sizeof(struct threads));
1029 t->base_addr = base_addr;
1030 linux_os->thread_count++;
1031 } else
1032 t->base_addr = next_task(target, t);
1033 }
1034
1035 LOG_INFO("update thread done %" PRId64 ", mean%" PRId64 "\n",
1036 (timeval_ms() - start), (timeval_ms() - start) / loop);
1037 free(t);
1038 linux_os->threads_needs_update = 0;
1039 return ERROR_OK;
1040 }
1041
1042 int linux_gdb_thread_packet(struct target *target,
1043 struct connection *connection, char const *packet,
1044 int packet_size)
1045 {
1046 int retval;
1047 struct linux_os *linux_os =
1048 (struct linux_os *)target->rtos->rtos_specific_params;
1049
1050 if (linux_os->init_task_addr == 0xdeadbeef) {
1051 /* it has not been initialized */
1052 LOG_INFO("received thread request without init task address");
1053 gdb_put_packet(connection, "l", 1);
1054 return ERROR_OK;
1055 }
1056
1057 retval = linux_get_tasks(target, 1);
1058
1059 if (retval != ERROR_OK)
1060 return ERROR_TARGET_FAILURE;
1061
1062 char *out_str = calloc(MAX_THREADS * 17 + 10, 1);
1063 char *tmp_str = out_str;
1064 tmp_str += sprintf(tmp_str, "m");
1065 struct threads *temp = linux_os->thread_list;
1066
1067 while (temp != NULL) {
1068 tmp_str += sprintf(tmp_str, "%016" PRIx64, temp->threadid);
1069 temp = temp->next;
1070 if (temp)
1071 tmp_str += sprintf(tmp_str, ",");
1072 }
1073
1074 gdb_put_packet(connection, out_str, strlen(out_str));
1075 free(out_str);
1076 return ERROR_OK;
1077 }
1078
1079 int linux_gdb_thread_update(struct target *target,
1080 struct connection *connection, char const *packet,
1081 int packet_size)
1082 {
1083 int found = 0;
1084 struct linux_os *linux_os = (struct linux_os *)
1085 target->rtos->rtos_specific_params;
1086 struct threads *temp = linux_os->thread_list;
1087
1088 while (temp != NULL) {
1089 if (temp->threadid == linux_os->preupdtate_threadid_count + 1) {
1090 /*LOG_INFO("FOUND");*/
1091 found = 1;
1092 break;
1093 } else
1094 temp = temp->next;
1095 }
1096
1097 if (found == 1) {
1098 /*LOG_INFO("INTO GDB THREAD UPDATE FOUNDING START TASK");*/
1099 char *out_strr = calloc(MAX_THREADS * 17 + 10, 1);
1100 char *tmp_strr = out_strr;
1101 tmp_strr += sprintf(tmp_strr, "m");
1102 /*LOG_INFO("CHAR MALLOC & M DONE");*/
1103 tmp_strr += sprintf(tmp_strr, "%016" PRIx64, temp->threadid);
1104
1105 temp = temp->next;
1106
1107 while (temp != NULL) {
1108 /*LOG_INFO("INTO GDB THREAD UPDATE WHILE");*/
1109 tmp_strr += sprintf(tmp_strr, ",");
1110 tmp_strr +=
1111 sprintf(tmp_strr, "%016" PRIx64, temp->threadid);
1112 temp = temp->next;
1113 }
1114
1115 /*tmp_str[0] = 0;*/
1116 gdb_put_packet(connection, out_strr, strlen(out_strr));
1117 linux_os->preupdtate_threadid_count =
1118 linux_os->threadid_count - 1;
1119 free(out_strr);
1120 } else
1121 gdb_put_packet(connection, "l", 1);
1122
1123 return ERROR_OK;
1124 }
1125
1126 int linux_thread_extra_info(struct target *target,
1127 struct connection *connection, char const *packet,
1128 int packet_size)
1129 {
1130 int64_t threadid = 0;
1131 struct linux_os *linux_os = (struct linux_os *)
1132 target->rtos->rtos_specific_params;
1133 sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid);
1134 /*LOG_INFO("lookup extra info for thread %" SCNx64, threadid);*/
1135 struct threads *temp = linux_os->thread_list;
1136
1137 while (temp != NULL) {
1138 if (temp->threadid == threadid) {
1139 char *pid = " PID: ";
1140 char *pid_current = "*PID: ";
1141 char *name = "Name: ";
1142 int str_size = strlen(pid) + strlen(name);
1143 char *tmp_str = calloc(1, str_size + 50);
1144 char *tmp_str_ptr = tmp_str;
1145
1146 /* discriminate current task */
1147 if (temp->status == 3)
1148 tmp_str_ptr += sprintf(tmp_str_ptr, "%s",
1149 pid_current);
1150 else
1151 tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid);
1152
1153 tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid);
1154 sprintf(tmp_str_ptr, "%s", name);
1155 sprintf(tmp_str_ptr, "%s", temp->name);
1156 char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1);
1157 size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str,
1158 strlen(tmp_str), strlen(tmp_str) * 2 + 1);
1159 gdb_put_packet(connection, hex_str, pkt_len);
1160 free(hex_str);
1161 free(tmp_str);
1162 return ERROR_OK;
1163 }
1164
1165 temp = temp->next;
1166 }
1167
1168 LOG_INFO("thread not found");
1169 return ERROR_OK;
1170 }
1171
1172 int linux_gdb_T_packet(struct connection *connection,
1173 struct target *target, char const *packet, int packet_size)
1174 {
1175 int64_t threadid;
1176 struct linux_os *linux_os = (struct linux_os *)
1177 target->rtos->rtos_specific_params;
1178 int retval = ERROR_OK;
1179 sscanf(packet, "T%" SCNx64, &threadid);
1180
1181 if (linux_os->threads_needs_update == 0) {
1182 struct threads *temp = linux_os->thread_list;
1183 struct threads *prev = NULL;
1184
1185 while (temp != NULL) {
1186 if (temp->threadid == threadid) {
1187 if (temp->status != 0) {
1188 gdb_put_packet(connection, "OK", 2);
1189 return ERROR_OK;
1190 } else {
1191 /* delete item in the list */
1192 linux_os->thread_list =
1193 liste_del_task(linux_os->
1194 thread_list, &temp,
1195 prev);
1196 linux_os->thread_count--;
1197 gdb_put_packet(connection, "E01", 3);
1198 return ERROR_OK;
1199 }
1200 }
1201
1202 /* for deletion */
1203 prev = temp;
1204 temp = temp->next;
1205 }
1206
1207 LOG_INFO("gdb requested status on non existing thread");
1208 gdb_put_packet(connection, "E01", 3);
1209 return ERROR_OK;
1210
1211 } else {
1212 retval = linux_task_update(target, 1);
1213 struct threads *temp = linux_os->thread_list;
1214
1215 while (temp != NULL) {
1216 if (temp->threadid == threadid) {
1217 if (temp->status == 1) {
1218 gdb_put_packet(connection, "OK", 2);
1219 return ERROR_OK;
1220 } else {
1221 gdb_put_packet(connection, "E01", 3);
1222 return ERROR_OK;
1223 }
1224 }
1225
1226 temp = temp->next;
1227 }
1228 }
1229
1230 return retval;
1231 }
1232
1233 int linux_gdb_h_packet(struct connection *connection,
1234 struct target *target, char const *packet, int packet_size)
1235 {
1236 struct linux_os *linux_os = (struct linux_os *)
1237 target->rtos->rtos_specific_params;
1238 struct current_thread *ct = linux_os->current_threads;
1239
1240 /* select to display the current thread of the selected target */
1241 while ((ct != NULL) && (ct->core_id != target->coreid))
1242 ct = ct->next;
1243
1244 int64_t current_gdb_thread_rq;
1245
1246 if (linux_os->threads_lookup == 1) {
1247 if ((ct != NULL) && (ct->threadid == -1)) {
1248 ct = linux_os->current_threads;
1249
1250 while ((ct != NULL) && (ct->threadid == -1))
1251 ct = ct->next;
1252 }
1253
1254 if (ct == NULL) {
1255 /* no current thread can be identified
1256 * any way with smp */
1257 LOG_INFO("no current thread identified");
1258 /* attempt to display the name of the 2 threads identified with
1259 * get_current */
1260 struct threads t;
1261 ct = linux_os->current_threads;
1262
1263 while ((ct != NULL) && (ct->threadid == -1)) {
1264 t.base_addr = ct->TS;
1265 get_name(target, &t);
1266 LOG_INFO("name of unidentified thread %s",
1267 t.name);
1268 ct = ct->next;
1269 }
1270
1271 gdb_put_packet(connection, "OK", 2);
1272 return ERROR_OK;
1273 }
1274
1275 if (packet[1] == 'g') {
1276 sscanf(packet, "Hg%16" SCNx64, &current_gdb_thread_rq);
1277
1278 if (current_gdb_thread_rq == 0) {
1279 target->rtos->current_threadid = ct->threadid;
1280 gdb_put_packet(connection, "OK", 2);
1281 } else {
1282 target->rtos->current_threadid =
1283 current_gdb_thread_rq;
1284 gdb_put_packet(connection, "OK", 2);
1285 }
1286 } else if (packet[1] == 'c') {
1287 sscanf(packet, "Hc%16" SCNx64, &current_gdb_thread_rq);
1288
1289 if ((current_gdb_thread_rq == 0) ||
1290 (current_gdb_thread_rq == ct->threadid)) {
1291 target->rtos->current_threadid = ct->threadid;
1292 gdb_put_packet(connection, "OK", 2);
1293 } else
1294 gdb_put_packet(connection, "E01", 3);
1295 }
1296 } else
1297 gdb_put_packet(connection, "OK", 2);
1298
1299 return ERROR_OK;
1300 }
1301
1302 static int linux_thread_packet(struct connection *connection, char const *packet,
1303 int packet_size)
1304 {
1305 int retval = ERROR_OK;
1306 struct current_thread *ct;
1307 struct target *target = get_target_from_connection(connection);
1308 struct linux_os *linux_os = (struct linux_os *)
1309 target->rtos->rtos_specific_params;
1310
1311 switch (packet[0]) {
1312 case 'T': /* Is thread alive?*/
1313
1314 linux_gdb_T_packet(connection, target, packet, packet_size);
1315 break;
1316 case 'H': /* Set current thread */
1317 /* ( 'c' for step and continue, 'g' for all other operations )*/
1318 /*LOG_INFO(" H packet received '%s'", packet);*/
1319 linux_gdb_h_packet(connection, target, packet, packet_size);
1320 break;
1321 case 'q':
1322
1323 if (strncmp(packet, "qSymbol", 7) == 0) {
1324 if (rtos_qsymbol(connection, packet, packet_size) == 1) {
1325 linux_compute_virt2phys(target,
1326 target->rtos->
1327 symbols[INIT_TASK].
1328 address);
1329 }
1330
1331 break;
1332 } else if (strncmp(packet, "qfThreadInfo", 12) == 0) {
1333 if (linux_os->thread_list == NULL) {
1334 retval = linux_gdb_thread_packet(target,
1335 connection,
1336 packet,
1337 packet_size);
1338 break;
1339 } else {
1340 retval = linux_gdb_thread_update(target,
1341 connection,
1342 packet,
1343 packet_size);
1344 break;
1345 }
1346 } else if (strncmp(packet, "qsThreadInfo", 12) == 0) {
1347 gdb_put_packet(connection, "l", 1);
1348 break;
1349 } else if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) {
1350 linux_thread_extra_info(target, connection, packet,
1351 packet_size);
1352 break;
1353 } else {
1354 retval = GDB_THREAD_PACKET_NOT_CONSUMED;
1355 break;
1356 }
1357
1358 case 'Q':
1359 /* previously response was : thread not found
1360 * gdb_put_packet(connection, "E01", 3); */
1361 retval = GDB_THREAD_PACKET_NOT_CONSUMED;
1362 break;
1363 case 'c':
1364 case 's': {
1365 if (linux_os->threads_lookup == 1) {
1366 ct = linux_os->current_threads;
1367
1368 while ((ct != NULL) && (ct->core_id) != target->coreid)
1369 ct = ct->next;
1370
1371 if ((ct != NULL) && (ct->threadid == -1)) {
1372 ct = linux_os->current_threads;
1373
1374 while ((ct != NULL) && (ct->threadid == -1))
1375 ct = ct->next;
1376 }
1377
1378 if ((ct != NULL) && (ct->threadid !=
1379 target->rtos->
1380 current_threadid)
1381 && (target->rtos->current_threadid != -1))
1382 LOG_WARNING("WARNING! current GDB thread do not match" \
1383 "current thread running." \
1384 "Switch thread in GDB to threadid %d",
1385 (int)ct->threadid);
1386
1387 LOG_INFO("threads_needs_update = 1");
1388 linux_os->threads_needs_update = 1;
1389 }
1390 }
1391
1392 /* if a packet handler returned an error, exit input loop */
1393 if (retval != ERROR_OK)
1394 return retval;
1395 }
1396
1397 return retval;
1398 }
1399
1400 static int linux_os_smp_init(struct target *target)
1401 {
1402 struct target_list *head;
1403 /* keep only target->rtos */
1404 struct rtos *rtos = target->rtos;
1405 struct linux_os *os_linux =
1406 (struct linux_os *)rtos->rtos_specific_params;
1407 struct current_thread *ct;
1408 head = target->head;
1409
1410 while (head != (struct target_list *)NULL) {
1411 if (head->target->rtos != rtos) {
1412 struct linux_os *smp_os_linux =
1413 (struct linux_os *)head->target->rtos->
1414 rtos_specific_params;
1415 /* remap smp target on rtos */
1416 free(head->target->rtos);
1417 head->target->rtos = rtos;
1418 /* reuse allocated ct */
1419 ct = smp_os_linux->current_threads;
1420 ct->threadid = -1;
1421 ct->TS = 0xdeadbeef;
1422 ct->core_id = head->target->coreid;
1423 os_linux->current_threads =
1424 add_current_thread(os_linux->current_threads, ct);
1425 os_linux->nr_cpus++;
1426 free(smp_os_linux);
1427 }
1428
1429 head = head->next;
1430 }
1431
1432 return ERROR_OK;
1433 }
1434
1435 static int linux_os_create(struct target *target)
1436 {
1437 struct linux_os *os_linux = calloc(1, sizeof(struct linux_os));
1438 struct current_thread *ct = calloc(1, sizeof(struct current_thread));
1439 LOG_INFO("linux os creation\n");
1440 os_linux->init_task_addr = 0xdeadbeef;
1441 os_linux->name = "linux";
1442 os_linux->thread_list = NULL;
1443 os_linux->thread_count = 0;
1444 target->rtos->current_threadid = -1;
1445 os_linux->nr_cpus = 1;
1446 os_linux->threads_lookup = 0;
1447 os_linux->threads_needs_update = 0;
1448 os_linux->threadid_count = 1;
1449 os_linux->current_threads = NULL;
1450 target->rtos->rtos_specific_params = os_linux;
1451 ct->core_id = target->coreid;
1452 ct->threadid = -1;
1453 ct->TS = 0xdeadbeef;
1454 os_linux->current_threads =
1455 add_current_thread(os_linux->current_threads, ct);
1456 /* overload rtos thread default handler */
1457 target->rtos->gdb_thread_packet = linux_thread_packet;
1458 /* initialize a default virt 2 phys translation */
1459 os_linux->phys_mask = ~0xc0000000;
1460 os_linux->phys_base = 0x0;
1461 return JIM_OK;
1462 }
1463
1464 static char *linux_ps_command(struct target *target)
1465 {
1466 struct linux_os *linux_os = (struct linux_os *)
1467 target->rtos->rtos_specific_params;
1468 int retval = ERROR_OK;
1469 char *display;
1470
1471 if (linux_os->threads_lookup == 0)
1472 retval = linux_get_tasks(target, 1);
1473 else {
1474 if (linux_os->threads_needs_update != 0)
1475 retval = linux_task_update(target, 0);
1476 }
1477
1478 if (retval == ERROR_OK) {
1479 struct threads *temp = linux_os->thread_list;
1480 char *tmp;
1481 LOG_INFO("allocation for %d threads line",
1482 linux_os->thread_count);
1483 display = calloc((linux_os->thread_count + 2) * 80, 1);
1484
1485 if (!display)
1486 goto error;
1487
1488 tmp = display;
1489 tmp += sprintf(tmp, "PID\t\tCPU\t\tASID\t\tNAME\n");
1490 tmp += sprintf(tmp, "---\t\t---\t\t----\t\t----\n");
1491
1492 while (temp != NULL) {
1493 if (temp->status) {
1494 if (temp->context)
1495 tmp +=
1496 sprintf(tmp,
1497 "%" PRId32 "\t\t%" PRId32 "\t\t%" PRIx32 "\t\t%s\n",
1498 temp->pid, temp->oncpu,
1499 temp->asid, temp->name);
1500 else
1501 tmp +=
1502 sprintf(tmp,
1503 "%" PRId32 "\t\t%" PRId32 "\t\t%" PRIx32 "\t\t%s\n",
1504 temp->pid, temp->oncpu,
1505 temp->asid, temp->name);
1506 }
1507
1508 temp = temp->next;
1509 }
1510
1511 return display;
1512 }
1513
1514 error:
1515 display = calloc(40, 1);
1516 sprintf(display, "linux_ps_command failed\n");
1517 return display;
1518 }

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)