openocd: fix SPDX tag format for files .c
[fw/openocd] / src / rtos / zephyr.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4  *   Copyright (C) 2017 by Intel Corporation
5  *   Leandro Pereira <leandro.pereira@intel.com>
6  *   Daniel Glöckner <dg@emlix.com>*
7  *   Copyright (C) 2021 by Synopsys, Inc.
8  *   Evgeniy Didin <didin@synopsys.com>
9  ***************************************************************************/
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include <helper/time_support.h>
16 #include <jtag/jtag.h>
17
18 #include "helper/log.h"
19 #include "helper/types.h"
20 #include "rtos.h"
21 #include "rtos_standard_stackings.h"
22 #include "target/target.h"
23 #include "target/target_type.h"
24 #include "target/armv7m.h"
25 #include "target/arc.h"
26
27 #define UNIMPLEMENTED 0xFFFFFFFFU
28
29 /* ARC specific defines */
30 #define ARC_AUX_SEC_BUILD_REG 0xdb
31 #define ARC_REG_NUM 38
32
33 /* ARM specific defines */
34 #define ARM_XPSR_OFFSET 28
35
36 struct zephyr_thread {
37         uint32_t ptr, next_ptr;
38         uint32_t entry;
39         uint32_t stack_pointer;
40         uint8_t state;
41         uint8_t user_options;
42         int8_t prio;
43         char name[64];
44 };
45
46 enum zephyr_offsets {
47         OFFSET_VERSION,
48         OFFSET_K_CURR_THREAD,
49         OFFSET_K_THREADS,
50         OFFSET_T_ENTRY,
51         OFFSET_T_NEXT_THREAD,
52         OFFSET_T_STATE,
53         OFFSET_T_USER_OPTIONS,
54         OFFSET_T_PRIO,
55         OFFSET_T_STACK_POINTER,
56         OFFSET_T_NAME,
57         OFFSET_T_ARCH,
58         OFFSET_T_PREEMPT_FLOAT,
59         OFFSET_T_COOP_FLOAT,
60         OFFSET_MAX
61 };
62
63 struct zephyr_params {
64         const char *target_name;
65         uint8_t size_width;
66         uint8_t pointer_width;
67         uint32_t num_offsets;
68         uint32_t offsets[OFFSET_MAX];
69         const struct rtos_register_stacking *callee_saved_stacking;
70         const struct rtos_register_stacking *cpu_saved_nofp_stacking;
71         const struct rtos_register_stacking *cpu_saved_fp_stacking;
72         int (*get_cpu_state)(struct rtos *rtos, target_addr_t *addr,
73                         struct zephyr_params *params,
74                         struct rtos_reg *callee_saved_reg_list,
75                         struct rtos_reg **reg_list, int *num_regs);
76 };
77
78 static const struct stack_register_offset arm_callee_saved[] = {
79         { ARMV7M_R13, 32, 32 },
80         { ARMV7M_R4,  0,  32 },
81         { ARMV7M_R5,  4,  32 },
82         { ARMV7M_R6,  8,  32 },
83         { ARMV7M_R7,  12, 32 },
84         { ARMV7M_R8,  16, 32 },
85         { ARMV7M_R9,  20, 32 },
86         { ARMV7M_R10, 24, 32 },
87         { ARMV7M_R11, 28, 32 },
88 };
89
90 static const struct stack_register_offset arc_callee_saved[] = {
91         { ARC_R13,  0,  32 },
92         { ARC_R14,  4,  32 },
93         { ARC_R15,  8,  32 },
94         { ARC_R16,  12,  32 },
95         { ARC_R17,  16,  32 },
96         { ARC_R18,  20,  32 },
97         { ARC_R19,  24,  32 },
98         { ARC_R20,  28,  32 },
99         { ARC_R21,  32,  32 },
100         { ARC_R22,  36,  32 },
101         { ARC_R23,  40,  32 },
102         { ARC_R24,  44,  32 },
103         { ARC_R25,  48,  32 },
104         { ARC_GP,  52,  32 },
105         { ARC_FP,  56,  32 },
106         { ARC_R30,  60,  32 }
107 };
108 static const struct rtos_register_stacking arm_callee_saved_stacking = {
109         .stack_registers_size = 36,
110         .stack_growth_direction = -1,
111         .num_output_registers = ARRAY_SIZE(arm_callee_saved),
112         .register_offsets = arm_callee_saved,
113 };
114
115 static const struct rtos_register_stacking arc_callee_saved_stacking = {
116         .stack_registers_size = 64,
117         .stack_growth_direction = -1,
118         .num_output_registers = ARRAY_SIZE(arc_callee_saved),
119         .register_offsets = arc_callee_saved,
120 };
121
122 static const struct stack_register_offset arm_cpu_saved[] = {
123         { ARMV7M_R0,   0,  32 },
124         { ARMV7M_R1,   4,  32 },
125         { ARMV7M_R2,   8,  32 },
126         { ARMV7M_R3,   12, 32 },
127         { ARMV7M_R4,   -1, 32 },
128         { ARMV7M_R5,   -1, 32 },
129         { ARMV7M_R6,   -1, 32 },
130         { ARMV7M_R7,   -1, 32 },
131         { ARMV7M_R8,   -1, 32 },
132         { ARMV7M_R9,   -1, 32 },
133         { ARMV7M_R10,  -1, 32 },
134         { ARMV7M_R11,  -1, 32 },
135         { ARMV7M_R12,  16, 32 },
136         { ARMV7M_R13,  -2, 32 },
137         { ARMV7M_R14,  20, 32 },
138         { ARMV7M_PC,   24, 32 },
139         { ARMV7M_XPSR, 28, 32 },
140 };
141
142 static struct stack_register_offset arc_cpu_saved[] = {
143         { ARC_R0,               -1,  32 },
144         { ARC_R1,               -1,  32 },
145         { ARC_R2,               -1,  32 },
146         { ARC_R3,               -1,  32 },
147         { ARC_R4,               -1,  32 },
148         { ARC_R5,               -1,  32 },
149         { ARC_R6,               -1,  32 },
150         { ARC_R7,               -1,  32 },
151         { ARC_R8,               -1,  32 },
152         { ARC_R9,               -1,  32 },
153         { ARC_R10,              -1,  32 },
154         { ARC_R11,              -1,  32 },
155         { ARC_R12,              -1,  32 },
156         { ARC_R13,              -1,  32 },
157         { ARC_R14,              -1,  32 },
158         { ARC_R15,              -1,  32 },
159         { ARC_R16,              -1,  32 },
160         { ARC_R17,              -1,  32 },
161         { ARC_R18,              -1,  32 },
162         { ARC_R19,              -1,  32 },
163         { ARC_R20,              -1,  32 },
164         { ARC_R21,              -1,  32 },
165         { ARC_R22,              -1,  32 },
166         { ARC_R23,              -1,  32 },
167         { ARC_R24,              -1,  32 },
168         { ARC_R25,              -1,  32 },
169         { ARC_GP,               -1,  32 },
170         { ARC_FP,               -1,  32 },
171         { ARC_SP,               -1,  32 },
172         { ARC_ILINK,            -1,  32 },
173         { ARC_R30,              -1,  32 },
174         { ARC_BLINK,             0,  32 },
175         { ARC_LP_COUNT,         -1,  32 },
176         { ARC_PCL,              -1,  32 },
177         { ARC_PC,               -1,  32 },
178         { ARC_LP_START,         -1,  32 },
179         { ARC_LP_END,           -1,  32 },
180         { ARC_STATUS32,          4,  32 }
181 };
182
183
184 enum zephyr_symbol_values {
185         ZEPHYR_VAL__KERNEL,
186         ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS,
187         ZEPHYR_VAL__KERNEL_OPENOCD_SIZE_T_SIZE,
188         ZEPHYR_VAL__KERNEL_OPENOCD_NUM_OFFSETS,
189         ZEPHYR_VAL_COUNT
190 };
191
192 static target_addr_t zephyr_cortex_m_stack_align(struct target *target,
193                 const uint8_t *stack_data,
194                 const struct rtos_register_stacking *stacking, target_addr_t stack_ptr)
195 {
196         return rtos_cortex_m_stack_align(target, stack_data, stacking,
197                         stack_ptr, ARM_XPSR_OFFSET);
198 }
199
200 static const struct rtos_register_stacking arm_cpu_saved_nofp_stacking = {
201         .stack_registers_size = 32,
202         .stack_growth_direction = -1,
203         .num_output_registers = ARRAY_SIZE(arm_cpu_saved),
204         .calculate_process_stack = zephyr_cortex_m_stack_align,
205         .register_offsets = arm_cpu_saved,
206 };
207
208 static const struct rtos_register_stacking arm_cpu_saved_fp_stacking = {
209         .stack_registers_size = 32 + 18 * 4,
210         .stack_growth_direction = -1,
211         .num_output_registers = ARRAY_SIZE(arm_cpu_saved),
212         .calculate_process_stack = zephyr_cortex_m_stack_align,
213         .register_offsets = arm_cpu_saved,
214 };
215
216 /* stack_registers_size is 8 because besides caller registers
217  * there are only blink and Status32 registers on stack left */
218 static struct rtos_register_stacking arc_cpu_saved_stacking = {
219         .stack_registers_size = 8,
220         .stack_growth_direction = -1,
221         .num_output_registers = ARRAY_SIZE(arc_cpu_saved),
222         .register_offsets = arc_cpu_saved,
223 };
224
225 /* ARCv2 specific implementation */
226 static int zephyr_get_arc_state(struct rtos *rtos, target_addr_t *addr,
227                          struct zephyr_params *params,
228                          struct rtos_reg *callee_saved_reg_list,
229                          struct rtos_reg **reg_list, int *num_regs)
230 {
231
232         uint32_t real_stack_addr;
233         int retval = 0;
234         int num_callee_saved_regs;
235         const struct rtos_register_stacking *stacking;
236
237         /* Getting real stack address from Kernel thread struct */
238         retval = target_read_u32(rtos->target, *addr, &real_stack_addr);
239         if (retval != ERROR_OK)
240                 return retval;
241
242         /* Getting callee registers */
243         retval = rtos_generic_stack_read(rtos->target,
244                         params->callee_saved_stacking,
245                         real_stack_addr, &callee_saved_reg_list,
246                         &num_callee_saved_regs);
247         if (retval != ERROR_OK)
248                 return retval;
249
250         stacking = params->cpu_saved_nofp_stacking;
251
252         /* Getting blink and status32 registers */
253         retval = rtos_generic_stack_read(rtos->target, stacking,
254                         real_stack_addr + num_callee_saved_regs * 4,
255                         reg_list, num_regs);
256         if (retval != ERROR_OK)
257                 return retval;
258
259         for (int i = 0; i < num_callee_saved_regs; i++)
260                 buf_cpy(callee_saved_reg_list[i].value,
261                         (*reg_list)[callee_saved_reg_list[i].number].value,
262                         callee_saved_reg_list[i].size);
263
264         /* The blink, sp, pc offsets in arc_cpu_saved structure may be changed,
265          * but the registers number shall not. So the next code searches the
266          * offsetst of these registers in arc_cpu_saved structure. */
267         unsigned short blink_offset = 0, pc_offset = 0, sp_offset = 0;
268         for (size_t i = 0; i < ARRAY_SIZE(arc_cpu_saved); i++) {
269                 if (arc_cpu_saved[i].number == ARC_BLINK)
270                         blink_offset = i;
271                 if (arc_cpu_saved[i].number == ARC_SP)
272                         sp_offset = i;
273                 if (arc_cpu_saved[i].number == ARC_PC)
274                         pc_offset = i;
275         }
276
277         if (blink_offset == 0 || sp_offset == 0 || pc_offset == 0) {
278                 LOG_ERROR("Basic registers offsets are missing, check <arc_cpu_saved> struct");
279                 return ERROR_FAIL;
280         }
281
282         /* Put blink value into PC */
283         buf_cpy((*reg_list)[blink_offset].value,
284                 (*reg_list)[pc_offset].value, sizeof((*reg_list)[blink_offset].value));
285
286         /* Put address after callee/caller in SP. */
287         int64_t stack_top;
288
289         stack_top = real_stack_addr + num_callee_saved_regs * 4
290                         + arc_cpu_saved_stacking.stack_registers_size;
291         buf_cpy(&stack_top, (*reg_list)[sp_offset].value, sizeof(stack_top));
292
293         return retval;
294 }
295
296 /* ARM Cortex-M-specific implementation */
297 static int zephyr_get_arm_state(struct rtos *rtos, target_addr_t *addr,
298                          struct zephyr_params *params,
299                          struct rtos_reg *callee_saved_reg_list,
300                          struct rtos_reg **reg_list, int *num_regs)
301 {
302
303         int retval = 0;
304         int num_callee_saved_regs;
305         const struct rtos_register_stacking *stacking;
306
307         retval = rtos_generic_stack_read(rtos->target,
308                         params->callee_saved_stacking,
309                         *addr, &callee_saved_reg_list,
310                         &num_callee_saved_regs);
311         if (retval != ERROR_OK)
312                 return retval;
313
314         *addr = target_buffer_get_u32(rtos->target,
315                         callee_saved_reg_list[0].value);
316
317         if (params->offsets[OFFSET_T_PREEMPT_FLOAT] != UNIMPLEMENTED)
318                 stacking = params->cpu_saved_fp_stacking;
319         else
320                 stacking = params->cpu_saved_nofp_stacking;
321
322         retval = rtos_generic_stack_read(rtos->target, stacking, *addr, reg_list,
323                         num_regs);
324         if (retval != ERROR_OK)
325                 return retval;
326
327         for (int i = 1; i < num_callee_saved_regs; i++)
328                 buf_cpy(callee_saved_reg_list[i].value,
329                         (*reg_list)[callee_saved_reg_list[i].number].value,
330                         callee_saved_reg_list[i].size);
331         return 0;
332 }
333
334 static struct zephyr_params zephyr_params_list[] = {
335         {
336                 .target_name = "cortex_m",
337                 .pointer_width = 4,
338                 .callee_saved_stacking = &arm_callee_saved_stacking,
339                 .cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
340                 .cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
341                 .get_cpu_state = &zephyr_get_arm_state,
342         },
343         {
344                 .target_name = "cortex_r4",
345                 .pointer_width = 4,
346                 .callee_saved_stacking = &arm_callee_saved_stacking,
347                 .cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
348                 .cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
349                 .get_cpu_state = &zephyr_get_arm_state,
350         },
351         {
352                 .target_name = "hla_target",
353                 .pointer_width = 4,
354                 .callee_saved_stacking = &arm_callee_saved_stacking,
355                 .cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
356                 .cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
357                 .get_cpu_state = &zephyr_get_arm_state,
358
359         },
360         {
361                 .target_name = "arcv2",
362                 .pointer_width = 4,
363                 .callee_saved_stacking = &arc_callee_saved_stacking,
364                 .cpu_saved_nofp_stacking = &arc_cpu_saved_stacking,
365                 .get_cpu_state = &zephyr_get_arc_state,
366         },
367         {
368                 .target_name = NULL
369         }
370 };
371
372 static const struct symbol_table_elem zephyr_symbol_list[] = {
373         {
374                 .symbol_name = "_kernel",
375                 .optional = false
376         },
377         {
378                 .symbol_name = "_kernel_thread_info_offsets",
379                 .optional = false
380         },
381         {
382                 .symbol_name = "_kernel_thread_info_size_t_size",
383                 .optional = false
384         },
385         {
386                 .symbol_name = "_kernel_thread_info_num_offsets",
387                 .optional = true
388         },
389         {
390                 .symbol_name = NULL
391         }
392 };
393
394 static bool zephyr_detect_rtos(struct target *target)
395 {
396         if (!target->rtos->symbols) {
397                 LOG_INFO("Zephyr: no symbols while detecting RTOS");
398                 return false;
399         }
400
401         for (enum zephyr_symbol_values symbol = ZEPHYR_VAL__KERNEL;
402                                         symbol != ZEPHYR_VAL_COUNT; symbol++) {
403                 LOG_INFO("Zephyr: does it have symbol %d (%s)?", symbol,
404                         target->rtos->symbols[symbol].optional ? "optional" : "mandatory");
405
406                 if (target->rtos->symbols[symbol].optional)
407                         continue;
408                 if (target->rtos->symbols[symbol].address == 0)
409                         return false;
410         }
411
412         LOG_INFO("Zephyr: all mandatory symbols found");
413
414         return true;
415 }
416
417 static int zephyr_create(struct target *target)
418 {
419         const char *name;
420
421         name = target_type_name(target);
422
423         LOG_INFO("Zephyr: looking for target: %s", name);
424
425         /* ARC specific, check if EM target has security subsystem
426          * In case of ARC_HAS_SECURE zephyr option enabled
427          * the thread stack contains blink,sec_stat,status32 register
428          * values. If ARC_HAS_SECURE is disabled, only blink and status32
429          * register values are saved on stack. */
430         if (!strcmp(name, "arcv2")) {
431                 uint32_t value;
432                 struct arc_common *arc = target_to_arc(target);
433                 /* Reading SEC_BUILD bcr */
434                 CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, ARC_AUX_SEC_BUILD_REG, &value));
435                 if (value != 0) {
436                         LOG_DEBUG("ARC EM board has security subsystem, changing offsets");
437                         arc_cpu_saved[ARC_REG_NUM - 1].offset = 8;
438                         /* After reading callee registers in stack
439                          * now blink,sec_stat,status32 registers
440                          * are located. */
441                         arc_cpu_saved_stacking.stack_registers_size = 12;
442                 }
443         }
444
445         for (struct zephyr_params *p = zephyr_params_list; p->target_name; p++) {
446                 if (!strcmp(p->target_name, name)) {
447                         LOG_INFO("Zephyr: target known, params at %p", p);
448                         target->rtos->rtos_specific_params = p;
449                         return ERROR_OK;
450                 }
451         }
452
453         LOG_ERROR("Could not find target in Zephyr compatibility list");
454         return ERROR_FAIL;
455 }
456
457 struct zephyr_array {
458         void *ptr;
459         size_t elements;
460 };
461
462 static void zephyr_array_init(struct zephyr_array *array)
463 {
464         array->ptr = NULL;
465         array->elements = 0;
466 }
467
468 static void zephyr_array_free(struct zephyr_array *array)
469 {
470         free(array->ptr);
471         zephyr_array_init(array);
472 }
473
474 static void *zephyr_array_append(struct zephyr_array *array, size_t size)
475 {
476         if (!(array->elements % 16)) {
477                 void *ptr = realloc(array->ptr, (array->elements + 16) * size);
478
479                 if (!ptr) {
480                         LOG_ERROR("Out of memory");
481                         return NULL;
482                 }
483
484                 array->ptr = ptr;
485         }
486
487         return (unsigned char *)array->ptr + (array->elements++) * size;
488 }
489
490 static void *zephyr_array_detach_ptr(struct zephyr_array *array)
491 {
492         void *ptr = array->ptr;
493
494         zephyr_array_init(array);
495
496         return ptr;
497 }
498
499 static uint32_t zephyr_kptr(const struct rtos *rtos, enum zephyr_offsets off)
500 {
501         const struct zephyr_params *params = rtos->rtos_specific_params;
502
503         return rtos->symbols[ZEPHYR_VAL__KERNEL].address + params->offsets[off];
504 }
505
506 static int zephyr_fetch_thread(const struct rtos *rtos,
507                                 struct zephyr_thread *thread, uint32_t ptr)
508 {
509         const struct zephyr_params *param = rtos->rtos_specific_params;
510         int retval;
511
512         thread->ptr = ptr;
513
514         retval = target_read_u32(rtos->target, ptr + param->offsets[OFFSET_T_ENTRY],
515                                  &thread->entry);
516         if (retval != ERROR_OK)
517                 return retval;
518
519         retval = target_read_u32(rtos->target,
520                                  ptr + param->offsets[OFFSET_T_NEXT_THREAD],
521                                  &thread->next_ptr);
522         if (retval != ERROR_OK)
523                 return retval;
524
525         retval = target_read_u32(rtos->target,
526                                  ptr + param->offsets[OFFSET_T_STACK_POINTER],
527                                  &thread->stack_pointer);
528         if (retval != ERROR_OK)
529                 return retval;
530
531         retval = target_read_u8(rtos->target, ptr + param->offsets[OFFSET_T_STATE],
532                                 &thread->state);
533         if (retval != ERROR_OK)
534                 return retval;
535
536         retval = target_read_u8(rtos->target,
537                                 ptr + param->offsets[OFFSET_T_USER_OPTIONS],
538                                 &thread->user_options);
539         if (retval != ERROR_OK)
540                 return retval;
541
542         uint8_t prio;
543         retval = target_read_u8(rtos->target,
544                                 ptr + param->offsets[OFFSET_T_PRIO], &prio);
545         if (retval != ERROR_OK)
546                 return retval;
547         thread->prio = prio;
548
549         thread->name[0] = '\0';
550         if (param->offsets[OFFSET_T_NAME] != UNIMPLEMENTED) {
551                 retval = target_read_buffer(rtos->target,
552                                         ptr + param->offsets[OFFSET_T_NAME],
553                                         sizeof(thread->name) - 1, (uint8_t *)thread->name);
554                 if (retval != ERROR_OK)
555                         return retval;
556
557                 thread->name[sizeof(thread->name) - 1] = '\0';
558         }
559
560         LOG_DEBUG("Fetched thread%" PRIx32 ": {entry@0x%" PRIx32
561                 ", state=%" PRIu8 ", useropts=%" PRIu8 ", prio=%" PRId8 "}",
562                 ptr, thread->entry, thread->state, thread->user_options, thread->prio);
563
564         return ERROR_OK;
565 }
566
567 static int zephyr_fetch_thread_list(struct rtos *rtos, uint32_t current_thread)
568 {
569         struct zephyr_array thread_array;
570         struct zephyr_thread thread;
571         struct thread_detail *td;
572         int64_t curr_id = -1;
573         uint32_t curr;
574         int retval;
575
576         retval = target_read_u32(rtos->target, zephyr_kptr(rtos, OFFSET_K_THREADS),
577                 &curr);
578         if (retval != ERROR_OK) {
579                 LOG_ERROR("Could not fetch current thread pointer");
580                 return retval;
581         }
582
583         zephyr_array_init(&thread_array);
584
585         for (; curr; curr = thread.next_ptr) {
586                 retval = zephyr_fetch_thread(rtos, &thread, curr);
587                 if (retval != ERROR_OK)
588                         goto error;
589
590                 td = zephyr_array_append(&thread_array, sizeof(*td));
591                 if (!td)
592                         goto error;
593
594                 td->threadid = thread.ptr;
595                 td->exists = true;
596
597                 if (thread.name[0])
598                         td->thread_name_str = strdup(thread.name);
599                 else
600                         td->thread_name_str = alloc_printf("thr_%" PRIx32 "_%" PRIx32,
601                                                            thread.entry, thread.ptr);
602                 td->extra_info_str = alloc_printf("prio:%" PRId8 ",useropts:%" PRIu8,
603                                                   thread.prio, thread.user_options);
604                 if (!td->thread_name_str || !td->extra_info_str)
605                         goto error;
606
607                 if (td->threadid == current_thread)
608                         curr_id = (int64_t)thread_array.elements - 1;
609         }
610
611         LOG_DEBUG("Got information for %zu threads", thread_array.elements);
612
613         rtos_free_threadlist(rtos);
614
615         rtos->thread_count = (int)thread_array.elements;
616         rtos->thread_details = zephyr_array_detach_ptr(&thread_array);
617
618         rtos->current_threadid = curr_id;
619         rtos->current_thread = current_thread;
620
621         return ERROR_OK;
622
623 error:
624         td = thread_array.ptr;
625         for (size_t i = 0; i < thread_array.elements; i++) {
626                 free(td[i].thread_name_str);
627                 free(td[i].extra_info_str);
628         }
629
630         zephyr_array_free(&thread_array);
631
632         return ERROR_FAIL;
633 }
634
635 static int zephyr_update_threads(struct rtos *rtos)
636 {
637         struct zephyr_params *param;
638         int retval;
639
640         if (!rtos->rtos_specific_params)
641                 return ERROR_FAIL;
642
643         param = (struct zephyr_params *)rtos->rtos_specific_params;
644
645         if (!rtos->symbols) {
646                 LOG_ERROR("No symbols for Zephyr");
647                 return ERROR_FAIL;
648         }
649
650         if (rtos->symbols[ZEPHYR_VAL__KERNEL].address == 0) {
651                 LOG_ERROR("Can't obtain kernel struct from Zephyr");
652                 return ERROR_FAIL;
653         }
654
655         if (rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address == 0) {
656                 LOG_ERROR("Please build Zephyr with CONFIG_OPENOCD option set");
657                 return ERROR_FAIL;
658         }
659
660         retval = target_read_u8(rtos->target,
661                 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_SIZE_T_SIZE].address,
662                 &param->size_width);
663         if (retval != ERROR_OK) {
664                 LOG_ERROR("Couldn't determine size of size_t from host");
665                 return retval;
666         }
667
668         if (param->size_width != 4) {
669                 LOG_ERROR("Only size_t of 4 bytes are supported");
670                 return ERROR_FAIL;
671         }
672
673         if (rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_NUM_OFFSETS].address) {
674                 retval = target_read_u32(rtos->target,
675                                 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_NUM_OFFSETS].address,
676                                 &param->num_offsets);
677                 if (retval != ERROR_OK) {
678                         LOG_ERROR("Couldn't not fetch number of offsets from Zephyr");
679                         return retval;
680                 }
681
682                 if (param->num_offsets <= OFFSET_T_STACK_POINTER) {
683                         LOG_ERROR("Number of offsets too small");
684                         return ERROR_FAIL;
685                 }
686         } else {
687                 retval = target_read_u32(rtos->target,
688                                 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address,
689                                 &param->offsets[OFFSET_VERSION]);
690                 if (retval != ERROR_OK) {
691                         LOG_ERROR("Couldn't not fetch offsets from Zephyr");
692                         return retval;
693                 }
694
695                 if (param->offsets[OFFSET_VERSION] > 1) {
696                         LOG_ERROR("Unexpected OpenOCD support version %" PRIu32,
697                                         param->offsets[OFFSET_VERSION]);
698                         return ERROR_FAIL;
699                 }
700                 switch (param->offsets[OFFSET_VERSION]) {
701                 case 0:
702                         param->num_offsets = OFFSET_T_STACK_POINTER + 1;
703                         break;
704                 case 1:
705                         param->num_offsets = OFFSET_T_COOP_FLOAT + 1;
706                         break;
707                 }
708         }
709         /* We can fetch the whole array for version 0, as they're supposed
710          * to grow only */
711         uint32_t address;
712         address  = rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address;
713         for (size_t i = 0; i < OFFSET_MAX; i++, address += param->size_width) {
714                 if (i >= param->num_offsets) {
715                         param->offsets[i] = UNIMPLEMENTED;
716                         continue;
717                 }
718
719                 retval = target_read_u32(rtos->target, address, &param->offsets[i]);
720                 if (retval != ERROR_OK) {
721                         LOG_ERROR("Could not fetch offsets from Zephyr");
722                         return ERROR_FAIL;
723                 }
724         }
725
726         LOG_DEBUG("Zephyr OpenOCD support version %" PRId32,
727                           param->offsets[OFFSET_VERSION]);
728
729         uint32_t current_thread;
730         retval = target_read_u32(rtos->target,
731                 zephyr_kptr(rtos, OFFSET_K_CURR_THREAD), &current_thread);
732         if (retval != ERROR_OK) {
733                 LOG_ERROR("Could not obtain current thread ID");
734                 return retval;
735         }
736
737         retval = zephyr_fetch_thread_list(rtos, current_thread);
738         if (retval != ERROR_OK) {
739                 LOG_ERROR("Could not obtain thread list");
740                 return retval;
741         }
742
743         return ERROR_OK;
744 }
745
746 static int zephyr_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
747                 struct rtos_reg **reg_list, int *num_regs)
748 {
749         struct zephyr_params *params;
750         struct rtos_reg *callee_saved_reg_list = NULL;
751         target_addr_t addr;
752         int retval;
753
754         LOG_INFO("Getting thread %" PRId64 " reg list", thread_id);
755
756         if (!rtos)
757                 return ERROR_FAIL;
758
759         if (thread_id == 0)
760                 return ERROR_FAIL;
761
762         params = rtos->rtos_specific_params;
763         if (!params)
764                 return ERROR_FAIL;
765
766         addr = thread_id + params->offsets[OFFSET_T_STACK_POINTER]
767                  - params->callee_saved_stacking->register_offsets[0].offset;
768
769         retval = params->get_cpu_state(rtos, &addr, params, callee_saved_reg_list, reg_list, num_regs);
770
771         free(callee_saved_reg_list);
772
773         return retval;
774 }
775
776 static int zephyr_get_symbol_list_to_lookup(struct symbol_table_elem **symbol_list)
777 {
778         *symbol_list = malloc(sizeof(zephyr_symbol_list));
779         if (!*symbol_list) {
780                 LOG_ERROR("Out of memory");
781                 return ERROR_FAIL;
782         }
783
784         memcpy(*symbol_list, zephyr_symbol_list, sizeof(zephyr_symbol_list));
785         return ERROR_OK;
786 }
787
788 struct rtos_type zephyr_rtos = {
789         .name = "Zephyr",
790
791         .detect_rtos = zephyr_detect_rtos,
792         .create = zephyr_create,
793         .update_threads = zephyr_update_threads,
794         .get_thread_reg_list = zephyr_get_thread_reg_list,
795         .get_symbol_list_to_lookup = zephyr_get_symbol_list_to_lookup,
796 };