command: document enum command_mode
[openocd.git] / src / rtos / zephyr.c
blob630511636babb41ee6137e2e8c1005f7213093c6
1 /***************************************************************************
2 * Copyright (C) 2017 by Intel Corporation
3 * Leandro Pereira <leandro.pereira@intel.com>
4 * Daniel Glöckner <dg@emlix.com>*
5 * Copyright (C) 2021 by Synopsys, Inc.
6 * Evgeniy Didin <didin@synopsys.com>
7 * *
8 * SPDX-License-Identifier: GPL-2.0-or-later *
9 ***************************************************************************/
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
15 #include <helper/time_support.h>
16 #include <jtag/jtag.h>
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"
27 #define UNIMPLEMENTED 0xFFFFFFFFU
29 /* ARC specific defines */
30 #define ARC_AUX_SEC_BUILD_REG 0xdb
31 #define ARC_REG_NUM 38
33 /* ARM specific defines */
34 #define ARM_XPSR_OFFSET 28
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];
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
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);
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 },
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 }
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,
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,
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 },
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 }
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
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)
196 return rtos_cortex_m_stack_align(target, stack_data, stacking,
197 stack_ptr, ARM_XPSR_OFFSET);
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,
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,
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,
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)
232 uint32_t real_stack_addr;
233 int retval = 0;
234 int num_callee_saved_regs;
235 const struct rtos_register_stacking *stacking;
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;
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;
250 stacking = params->cpu_saved_nofp_stacking;
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;
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);
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;
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;
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));
286 /* Put address after callee/caller in SP. */
287 int64_t stack_top;
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));
293 return retval;
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)
303 int retval = 0;
304 int num_callee_saved_regs;
305 const struct rtos_register_stacking *stacking;
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;
314 *addr = target_buffer_get_u32(rtos->target,
315 callee_saved_reg_list[0].value);
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;
322 retval = rtos_generic_stack_read(rtos->target, stacking, *addr, reg_list,
323 num_regs);
324 if (retval != ERROR_OK)
325 return retval;
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;
334 static struct zephyr_params zephyr_params_list[] = {
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,
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,
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,
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,
368 .target_name = NULL
372 static const struct symbol_table_elem zephyr_symbol_list[] = {
374 .symbol_name = "_kernel",
375 .optional = false
378 .symbol_name = "_kernel_openocd_offsets",
379 .optional = false
382 .symbol_name = "_kernel_openocd_size_t_size",
383 .optional = false
386 .symbol_name = "_kernel_openocd_num_offsets",
387 .optional = true
390 .symbol_name = NULL
394 static bool zephyr_detect_rtos(struct target *target)
396 if (!target->rtos->symbols) {
397 LOG_INFO("Zephyr: no symbols while detecting RTOS");
398 return false;
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");
406 if (target->rtos->symbols[symbol].optional)
407 continue;
408 if (target->rtos->symbols[symbol].address == 0)
409 return false;
412 LOG_INFO("Zephyr: all mandatory symbols found");
414 return true;
417 static int zephyr_create(struct target *target)
419 const char *name;
421 name = target_type_name(target);
423 LOG_INFO("Zephyr: looking for target: %s", name);
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;
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;
453 LOG_ERROR("Could not find target in Zephyr compatibility list");
454 return ERROR_FAIL;
457 struct zephyr_array {
458 void *ptr;
459 size_t elements;
462 static void zephyr_array_init(struct zephyr_array *array)
464 array->ptr = NULL;
465 array->elements = 0;
468 static void zephyr_array_free(struct zephyr_array *array)
470 free(array->ptr);
471 zephyr_array_init(array);
474 static void *zephyr_array_append(struct zephyr_array *array, size_t size)
476 if (!(array->elements % 16)) {
477 void *ptr = realloc(array->ptr, (array->elements + 16) * size);
479 if (!ptr) {
480 LOG_ERROR("Out of memory");
481 return NULL;
484 array->ptr = ptr;
487 return (unsigned char *)array->ptr + (array->elements++) * size;
490 static void *zephyr_array_detach_ptr(struct zephyr_array *array)
492 void *ptr = array->ptr;
494 zephyr_array_init(array);
496 return ptr;
499 static uint32_t zephyr_kptr(const struct rtos *rtos, enum zephyr_offsets off)
501 const struct zephyr_params *params = rtos->rtos_specific_params;
503 return rtos->symbols[ZEPHYR_VAL__KERNEL].address + params->offsets[off];
506 static int zephyr_fetch_thread(const struct rtos *rtos,
507 struct zephyr_thread *thread, uint32_t ptr)
509 const struct zephyr_params *param = rtos->rtos_specific_params;
510 int retval;
512 thread->ptr = ptr;
514 retval = target_read_u32(rtos->target, ptr + param->offsets[OFFSET_T_ENTRY],
515 &thread->entry);
516 if (retval != ERROR_OK)
517 return retval;
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;
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;
531 retval = target_read_u8(rtos->target, ptr + param->offsets[OFFSET_T_STATE],
532 &thread->state);
533 if (retval != ERROR_OK)
534 return retval;
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;
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;
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;
557 thread->name[sizeof(thread->name) - 1] = '\0';
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);
564 return ERROR_OK;
567 static int zephyr_fetch_thread_list(struct rtos *rtos, uint32_t current_thread)
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;
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;
583 zephyr_array_init(&thread_array);
585 for (; curr; curr = thread.next_ptr) {
586 retval = zephyr_fetch_thread(rtos, &thread, curr);
587 if (retval != ERROR_OK)
588 goto error;
590 td = zephyr_array_append(&thread_array, sizeof(*td));
591 if (!td)
592 goto error;
594 td->threadid = thread.ptr;
595 td->exists = true;
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;
607 if (td->threadid == current_thread)
608 curr_id = (int64_t)thread_array.elements - 1;
611 LOG_DEBUG("Got information for %zu threads", thread_array.elements);
613 rtos_free_threadlist(rtos);
615 rtos->thread_count = (int)thread_array.elements;
616 rtos->thread_details = zephyr_array_detach_ptr(&thread_array);
618 rtos->current_threadid = curr_id;
619 rtos->current_thread = current_thread;
621 return ERROR_OK;
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);
630 zephyr_array_free(&thread_array);
632 return ERROR_FAIL;
635 static int zephyr_update_threads(struct rtos *rtos)
637 struct zephyr_params *param;
638 int retval;
640 if (!rtos->rtos_specific_params)
641 return ERROR_FAIL;
643 param = (struct zephyr_params *)rtos->rtos_specific_params;
645 if (!rtos->symbols) {
646 LOG_ERROR("No symbols for Zephyr");
647 return ERROR_FAIL;
650 if (rtos->symbols[ZEPHYR_VAL__KERNEL].address == 0) {
651 LOG_ERROR("Can't obtain kernel struct from Zephyr");
652 return ERROR_FAIL;
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;
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;
668 if (param->size_width != 4) {
669 LOG_ERROR("Only size_t of 4 bytes are supported");
670 return ERROR_FAIL;
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;
682 if (param->num_offsets <= OFFSET_T_STACK_POINTER) {
683 LOG_ERROR("Number of offsets too small");
684 return ERROR_FAIL;
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;
695 if (param->offsets[OFFSET_VERSION] > 1) {
696 LOG_ERROR("Unexpected OpenOCD support version %" PRIu32,
697 param->offsets[OFFSET_VERSION]);
698 return ERROR_FAIL;
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;
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;
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;
726 LOG_DEBUG("Zephyr OpenOCD support version %" PRId32,
727 param->offsets[OFFSET_VERSION]);
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;
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;
743 return ERROR_OK;
746 static int zephyr_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
747 struct rtos_reg **reg_list, int *num_regs)
749 struct zephyr_params *params;
750 struct rtos_reg *callee_saved_reg_list = NULL;
751 target_addr_t addr;
752 int retval;
754 LOG_INFO("Getting thread %" PRId64 " reg list", thread_id);
756 if (!rtos)
757 return ERROR_FAIL;
759 if (thread_id == 0)
760 return ERROR_FAIL;
762 params = rtos->rtos_specific_params;
763 if (!params)
764 return ERROR_FAIL;
766 addr = thread_id + params->offsets[OFFSET_T_STACK_POINTER]
767 - params->callee_saved_stacking->register_offsets[0].offset;
769 retval = params->get_cpu_state(rtos, &addr, params, callee_saved_reg_list, reg_list, num_regs);
771 free(callee_saved_reg_list);
773 return retval;
776 static int zephyr_get_symbol_list_to_lookup(struct symbol_table_elem **symbol_list)
778 *symbol_list = malloc(sizeof(zephyr_symbol_list));
779 if (!*symbol_list) {
780 LOG_ERROR("Out of memory");
781 return ERROR_FAIL;
784 memcpy(*symbol_list, zephyr_symbol_list, sizeof(zephyr_symbol_list));
785 return ERROR_OK;
788 struct rtos_type zephyr_rtos = {
789 .name = "Zephyr",
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,