1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2011 by Broadcom Corporation *
5 * Evan Hunter - ehunter@broadcom.com *
6 ***************************************************************************/
12 #include <helper/time_support.h>
13 #include <jtag/jtag.h>
14 #include "target/target.h"
15 #include "target/target_type.h"
17 #include "helper/log.h"
18 #include "helper/types.h"
19 #include "rtos_embkernel_stackings.h"
21 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
23 static bool embkernel_detect_rtos(struct target
*target
);
24 static int embkernel_create(struct target
*target
);
25 static int embkernel_update_threads(struct rtos
*rtos
);
26 static int embkernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
27 struct rtos_reg
**reg_list
, int *num_regs
);
28 static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[]);
30 struct rtos_type embkernel_rtos
= {
32 .detect_rtos
= embkernel_detect_rtos
,
33 .create
= embkernel_create
,
34 .update_threads
= embkernel_update_threads
,
35 .get_thread_reg_list
=
36 embkernel_get_thread_reg_list
,
37 .get_symbol_list_to_lookup
= embkernel_get_symbol_list_to_lookup
,
41 SYMBOL_ID_S_CURRENT_TASK
= 0,
42 SYMBOL_ID_S_LIST_READY
= 1,
43 SYMBOL_ID_S_LIST_SLEEP
= 2,
44 SYMBOL_ID_S_LIST_SUSPENDED
= 3,
45 SYMBOL_ID_S_MAX_PRIORITIES
= 4,
46 SYMBOL_ID_S_CURRENT_TASK_COUNT
= 5,
49 static const char * const embkernel_symbol_list
[] = {
53 "Rtos::sListSuspended",
54 "Rtos::sMaxPriorities",
55 "Rtos::sCurrentTaskCount",
58 struct embkernel_params
{
59 const char *target_name
;
60 const unsigned char pointer_width
;
61 const unsigned char thread_count_width
;
62 const unsigned char rtos_list_size
;
63 const unsigned char thread_stack_offset
;
64 const unsigned char thread_name_offset
;
65 const unsigned char thread_priority_offset
;
66 const unsigned char thread_priority_width
;
67 const unsigned char iterable_next_offset
;
68 const unsigned char iterable_task_owner_offset
;
69 const struct rtos_register_stacking
*stacking_info
;
72 static const struct embkernel_params embkernel_params_list
[] = {
74 "cortex_m", /* target_name */
75 4, /* pointer_width */
76 4, /* thread_count_width */
77 8, /*rtos_list_size */
78 0, /*thread_stack_offset */
79 4, /*thread_name_offset */
80 8, /*thread_priority_offset */
81 4, /*thread_priority_width */
82 4, /*iterable_next_offset */
83 12, /*iterable_task_owner_offset */
84 &rtos_embkernel_cortex_m_stacking
, /* stacking_info*/
86 { "hla_target", /* target_name */
87 4, /* pointer_width */
88 4, /* thread_count_width */
89 8, /*rtos_list_size */
90 0, /*thread_stack_offset */
91 4, /*thread_name_offset */
92 8, /*thread_priority_offset */
93 4, /*thread_priority_width */
94 4, /*iterable_next_offset */
95 12, /*iterable_task_owner_offset */
96 &rtos_embkernel_cortex_m_stacking
, /* stacking_info */
100 static bool embkernel_detect_rtos(struct target
*target
)
102 if (target
->rtos
->symbols
) {
103 if (target
->rtos
->symbols
[SYMBOL_ID_S_CURRENT_TASK
].address
!= 0)
109 static int embkernel_create(struct target
*target
)
112 while ((i
< ARRAY_SIZE(embkernel_params_list
)) &&
113 (strcmp(embkernel_params_list
[i
].target_name
, target
->type
->name
) != 0))
116 if (i
>= ARRAY_SIZE(embkernel_params_list
)) {
117 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
118 "list", target
->type
->name
);
122 target
->rtos
->rtos_specific_params
= (void *) &embkernel_params_list
[i
];
126 static int embkernel_get_tasks_details(struct rtos
*rtos
, int64_t iterable
, const struct embkernel_params
*param
,
127 struct thread_detail
*details
, const char *state_str
)
130 int retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_task_owner_offset
, param
->pointer_width
,
132 if (retval
!= ERROR_OK
)
134 details
->threadid
= (threadid_t
) task
;
135 details
->exists
= true;
137 int64_t name_ptr
= 0;
138 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_name_offset
, param
->pointer_width
,
139 (uint8_t *) &name_ptr
);
140 if (retval
!= ERROR_OK
)
143 details
->thread_name_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
145 retval
= target_read_buffer(rtos
->target
, name_ptr
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
,
146 (uint8_t *) details
->thread_name_str
);
147 if (retval
!= ERROR_OK
)
149 details
->thread_name_str
[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
- 1] = 0;
151 snprintf(details
->thread_name_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "NoName:[0x%08X]", (unsigned int) task
);
154 int64_t priority
= 0;
155 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_priority_offset
, param
->thread_priority_width
,
156 (uint8_t *) &priority
);
157 if (retval
!= ERROR_OK
)
159 details
->extra_info_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
160 if (task
== rtos
->current_thread
) {
161 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "State: Running, Priority: %u",
162 (unsigned int) priority
);
164 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "State: %s, Priority: %u",
165 state_str
, (unsigned int) priority
);
168 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable
,
169 (unsigned int)task
, details
->thread_name_str
);
173 static int embkernel_update_threads(struct rtos
*rtos
)
177 const struct embkernel_params
*param
;
182 if (!rtos
->rtos_specific_params
)
185 if (!rtos
->symbols
) {
186 LOG_ERROR("No symbols for embKernel");
190 if (rtos
->symbols
[SYMBOL_ID_S_CURRENT_TASK
].address
== 0) {
191 LOG_ERROR("Don't have the thread list head");
195 /* wipe out previous thread details if any */
196 rtos_free_threadlist(rtos
);
198 param
= (const struct embkernel_params
*) rtos
->rtos_specific_params
;
200 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_CURRENT_TASK
].address
, param
->pointer_width
,
201 (uint8_t *) &rtos
->current_thread
);
202 if (retval
!= ERROR_OK
) {
203 LOG_ERROR("Error reading current thread in embKernel thread list");
207 int64_t max_used_priority
= 0;
208 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_MAX_PRIORITIES
].address
, param
->pointer_width
,
209 (uint8_t *) &max_used_priority
);
210 if (retval
!= ERROR_OK
)
213 int thread_list_size
= 0;
214 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_CURRENT_TASK_COUNT
].address
,
215 param
->thread_count_width
, (uint8_t *) &thread_list_size
);
217 if (retval
!= ERROR_OK
) {
218 LOG_ERROR("Could not read embKernel thread count from target");
222 /* create space for new thread details */
223 rtos
->thread_details
= malloc(sizeof(struct thread_detail
) * thread_list_size
);
224 if (!rtos
->thread_details
) {
225 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
230 /* Look for ready tasks */
231 for (int pri
= 0; pri
< max_used_priority
; pri
++) {
232 /* Get first item in queue */
233 int64_t iterable
= 0;
234 retval
= target_read_buffer(rtos
->target
,
235 rtos
->symbols
[SYMBOL_ID_S_LIST_READY
].address
+ (pri
* param
->rtos_list_size
), param
->pointer_width
,
236 (uint8_t *) &iterable
);
237 if (retval
!= ERROR_OK
)
239 for (; iterable
&& thread_idx
< thread_list_size
; thread_idx
++) {
240 /* Get info from this iterable item */
241 retval
= embkernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[thread_idx
], "Ready");
242 if (retval
!= ERROR_OK
)
244 /* Get next iterable item */
245 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
246 (uint8_t *) &iterable
);
247 if (retval
!= ERROR_OK
)
251 /* Look for sleeping tasks */
252 int64_t iterable
= 0;
253 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_LIST_SLEEP
].address
, param
->pointer_width
,
254 (uint8_t *) &iterable
);
255 if (retval
!= ERROR_OK
)
257 for (; iterable
&& thread_idx
< thread_list_size
; thread_idx
++) {
258 /*Get info from this iterable item */
259 retval
= embkernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[thread_idx
], "Sleeping");
260 if (retval
!= ERROR_OK
)
262 /*Get next iterable item */
263 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
264 (uint8_t *) &iterable
);
265 if (retval
!= ERROR_OK
)
269 /* Look for suspended tasks */
271 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_LIST_SUSPENDED
].address
, param
->pointer_width
,
272 (uint8_t *) &iterable
);
273 if (retval
!= ERROR_OK
)
275 for (; iterable
&& thread_idx
< thread_list_size
; thread_idx
++) {
276 /* Get info from this iterable item */
277 retval
= embkernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[thread_idx
], "Suspended");
278 if (retval
!= ERROR_OK
)
280 /*Get next iterable item */
281 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
282 (uint8_t *) &iterable
);
283 if (retval
!= ERROR_OK
)
287 rtos
->thread_count
= 0;
288 rtos
->thread_count
= thread_idx
;
289 LOG_OUTPUT("Found %u tasks\n", (unsigned int)thread_idx
);
293 static int embkernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
294 struct rtos_reg
**reg_list
, int *num_regs
)
297 const struct embkernel_params
*param
;
298 int64_t stack_ptr
= 0;
306 if (!rtos
->rtos_specific_params
)
309 param
= (const struct embkernel_params
*) rtos
->rtos_specific_params
;
311 /* Read the stack pointer */
312 retval
= target_read_buffer(rtos
->target
, thread_id
+ param
->thread_stack_offset
, param
->pointer_width
,
313 (uint8_t *) &stack_ptr
);
314 if (retval
!= ERROR_OK
) {
315 LOG_ERROR("Error reading stack frame from embKernel thread");
319 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, reg_list
, num_regs
);
322 static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
325 *symbol_list
= calloc(ARRAY_SIZE(embkernel_symbol_list
), sizeof(struct symbol_table_elem
));
327 for (i
= 0; i
< ARRAY_SIZE(embkernel_symbol_list
); i
++)
328 (*symbol_list
)[i
].symbol_name
= embkernel_symbol_list
[i
];