OpenOCD
chromium-ec.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 /*
4  * Copyright (c) 2018 National Instruments Corp
5  * Author: Moritz Fischer <moritz.fischer@ettus.com>
6  *
7  * Chromium-EC RTOS Task Awareness
8  */
9 
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13 
14 #include <helper/bits.h>
15 #include <rtos/rtos.h>
16 #include <target/target.h>
17 
19 
20 #define CROS_EC_MAX_TASKS 32
21 #define CROS_EC_MAX_NAME 200
22 #define CROS_EC_IDLE_STRING "<< idle >>"
23 
25  const char *target_name;
26  size_t ptr_size;
32 };
33 
34 static const struct chromium_ec_params chromium_ec_params_list[] = {
35  {
36  .target_name = "hla_target",
37  .ptr_size = 4,
38  .task_offset_next = 24,
39  .task_offset_sp = 0,
40  .task_offset_events = 4,
41  .task_offset_runtime = 8,
43 
44  },
45  {
46  .target_name = "cortex_m",
47  .ptr_size = 4,
48  .task_offset_next = 24,
49  .task_offset_sp = 0,
50  .task_offset_events = 4,
51  .task_offset_runtime = 8,
53  },
54 };
55 
56 static const char * const chromium_ec_symbol_list[] = {
57  "start_called",
58  "current_task",
59  "tasks",
60  "tasks_enabled",
61  "tasks_ready",
62  "task_names",
63  "build_info",
64  NULL,
65 };
66 
75 
77 };
78 
79 #define CROS_EC_MAX_BUILDINFO 512
80 
82 {
83  char build_info_buf[CROS_EC_MAX_BUILDINFO];
85  int ret;
86 
87  if (!target || !target->rtos || !target->rtos->symbols)
88  return false;
89 
91  sym < CHROMIUM_EC_VAL_COUNT; sym++) {
92  if (target->rtos->symbols[sym].address) {
93  LOG_DEBUG("Chromium-EC: Symbol \"%s\" found",
95  } else {
96  LOG_ERROR("Chromium-EC: Symbol \"%s\" missing",
98  return false;
99  }
100  }
101 
104  sizeof(build_info_buf),
105  (uint8_t *)build_info_buf);
106 
107  if (ret != ERROR_OK)
108  return false;
109 
110  LOG_INFO("Chromium-EC: Buildinfo: %s", build_info_buf);
111 
112  return target->rtos->symbols &&
114 }
115 
116 static int chromium_ec_create(struct target *target)
117 {
118  struct chromium_ec_params *params;
119  size_t t;
120 
121  for (t = 0; t < ARRAY_SIZE(chromium_ec_params_list); t++)
123  params = malloc(sizeof(*params));
124  if (!params) {
125  LOG_ERROR("Chromium-EC: out of memory");
126  return ERROR_FAIL;
127  }
128 
129  memcpy(params, &chromium_ec_params_list[t], sizeof(*params));
130  target->rtos->rtos_specific_params = (void *)params;
131  target->rtos->current_thread = 0;
133  target->rtos->thread_count = 0;
134 
135  LOG_INFO("Chromium-EC: Using target: %s", target_type_name(target));
136  return ERROR_OK;
137  }
138 
139  LOG_ERROR("Chromium-EC: target not supported: %s", target_type_name(target));
140  return ERROR_FAIL;
141 }
142 
143 static int chromium_ec_get_current_task_ptr(struct rtos *rtos, uint32_t *current_task)
144 {
145  if (!rtos || !rtos->symbols)
146  return ERROR_FAIL;
147 
148  return target_read_u32(rtos->target,
150  current_task);
151 }
152 
153 static int chromium_ec_get_num_tasks(struct rtos *rtos, int *num_tasks)
154 {
155  uint32_t tasks_enabled;
156  int ret, t, found;
157 
158  ret = target_read_u32(rtos->target,
160  &tasks_enabled);
161  if (ret != ERROR_OK) {
162  LOG_ERROR("Failed to determine #of tasks");
163  return ret;
164  }
165 
166  found = 0;
167  for (t = 0; t < CROS_EC_MAX_TASKS; t++)
168  if (tasks_enabled & BIT(t))
169  found++;
170 
171  *num_tasks = found;
172 
173  return ERROR_OK;
174 }
175 
177 {
178  uint32_t tasks_enabled, tasks_ready, start_called;
179  uint32_t current_task, thread_ptr, name_ptr;
180  char thread_str_buf[CROS_EC_MAX_NAME];
181  int ret, t, num_tasks, tasks_found;
182  struct chromium_ec_params *params;
183  uint8_t runtime_buf[8];
184  uint64_t runtime;
185  uint32_t events;
186 
187  params = rtos->rtos_specific_params;
188  if (!params)
189  return ERROR_FAIL;
190 
191  if (!rtos->symbols)
192  return ERROR_FAIL;
193 
194  num_tasks = 0;
195  ret = chromium_ec_get_num_tasks(rtos, &num_tasks);
196  if (ret != ERROR_OK) {
197  LOG_ERROR("Failed to get number of tasks");
198  return ret;
199  }
200 
201  current_task = 0;
202  ret = chromium_ec_get_current_task_ptr(rtos, &current_task);
203  if (ret != ERROR_OK) {
204  LOG_ERROR("Failed to get current task");
205  return ret;
206  }
207  LOG_DEBUG("Current task: %lx tasks_found: %d",
208  (unsigned long)current_task,
209  num_tasks);
210 
211  /* set current task to what we read */
212  rtos->current_thread = current_task;
213 
214  /* Nuke the old tasks */
216 
217  /* One check if task switching has started ... */
218  start_called = 0;
220  &start_called);
221  if (ret != ERROR_OK) {
222  LOG_ERROR("Failed to load start_called");
223  return ret;
224  }
225 
226  if (!rtos->current_thread || !num_tasks || !start_called) {
227  num_tasks++;
228 
229  rtos->thread_details = malloc(
230  sizeof(struct thread_detail) * num_tasks);
232  rtos->thread_details->exists = true;
234  rtos->thread_details->thread_name_str = strdup("Current Execution");
235 
236  if (!num_tasks || !start_called) {
237  rtos->thread_count = 1;
238  return ERROR_OK;
239  }
240  } else {
241  /* create space for new thread details */
242  rtos->thread_details = malloc(
243  sizeof(struct thread_detail) * num_tasks);
244  }
245 
246  tasks_enabled = 0;
248  &tasks_enabled);
249  if (ret != ERROR_OK) {
250  LOG_ERROR("Failed to load tasks_enabled");
251  return ret;
252  }
253 
254  tasks_ready = 0;
256  &tasks_ready);
257  if (ret != ERROR_OK) {
258  LOG_ERROR("Failed to load tasks_ready");
259  return ret;
260  }
261 
262  thread_ptr = rtos->symbols[CHROMIUM_EC_VAL_TASKS].address;
263 
264  tasks_found = 0;
265  for (t = 0; t < CROS_EC_MAX_TASKS; t++) {
266  if (!(tasks_enabled & BIT(t)))
267  continue;
268 
269  if (thread_ptr == current_task)
270  rtos->current_thread = thread_ptr;
271 
272  rtos->thread_details[tasks_found].threadid = thread_ptr;
273  ret = target_read_u32(rtos->target,
275  params->ptr_size * t, &name_ptr);
276  if (ret != ERROR_OK) {
277  LOG_ERROR("Failed to read name_ptr");
278  return ret;
279  }
280 
281  /* read name buffer */
283  (uint8_t *)thread_str_buf);
284  if (ret != ERROR_OK) {
285  LOG_ERROR("Failed to read task name");
286  return ret;
287  }
288 
289  /* sanitize string, gdb chokes on "<< idle >>" */
290  if (thread_str_buf[CROS_EC_MAX_NAME - 1] != '\0')
291  thread_str_buf[CROS_EC_MAX_NAME - 1] = '\0';
292  if (!strncmp(thread_str_buf, CROS_EC_IDLE_STRING, CROS_EC_MAX_NAME))
293  rtos->thread_details[tasks_found].thread_name_str = strdup("IDLE");
294  else
295  rtos->thread_details[tasks_found].thread_name_str = strdup(thread_str_buf);
296 
297  events = 0;
298  ret = target_read_u32(rtos->target,
299  thread_ptr + params->task_offset_events,
300  &events);
301  if (ret != ERROR_OK)
302  LOG_ERROR("Failed to get task %d's events", t);
303 
304  /* this is a bit kludgy but will do for now */
306  thread_ptr + params->task_offset_runtime,
307  sizeof(runtime_buf), runtime_buf);
308  if (ret != ERROR_OK)
309  LOG_ERROR("Failed to get task %d's runtime", t);
310  runtime = target_buffer_get_u64(rtos->target, runtime_buf);
311 
312  /* Priority is simply the position in the array */
313  if (thread_ptr == current_task)
314  snprintf(thread_str_buf, sizeof(thread_str_buf),
315  "State: Running, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
316  t, events, runtime);
317  else
318  snprintf(thread_str_buf, sizeof(thread_str_buf),
319  "State: %s, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
320  tasks_ready & BIT(t) ? "Ready" : "Waiting", t,
321  events, runtime);
322 
323  rtos->thread_details[tasks_found].extra_info_str = strdup(thread_str_buf);
324  rtos->thread_details[tasks_found].exists = true;
325 
326  thread_ptr += params->task_offset_next;
327 
328  tasks_found++;
329  }
330 
331  rtos->thread_count = tasks_found;
332 
333  return ERROR_OK;
334 }
335 
337  threadid_t threadid,
338  struct rtos_reg **reg_list,
339  int *num_regs)
340 {
341  struct chromium_ec_params *params = rtos->rtos_specific_params;
342  uint32_t stack_ptr = 0;
343  int ret, t;
344 
345  for (t = 0; t < rtos->thread_count; t++)
346  if (threadid == rtos->thread_details[t].threadid)
347  break;
348 
349  /* if we didn't find threadid, bail */
350  if (t == rtos->thread_count)
351  return ERROR_FAIL;
352 
353  ret = target_read_u32(rtos->target,
355  params->task_offset_next * t,
356  &stack_ptr);
357  if (ret != ERROR_OK) {
358  LOG_ERROR("Failed to load TCB");
359  return ret;
360  }
361 
362  return rtos_generic_stack_read(rtos->target, params->stacking,
363  stack_ptr, reg_list, num_regs);
364 }
365 
367 {
368  size_t s;
369 
370  *symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list),
371  sizeof(struct symbol_table_elem));
372  if (!(*symbol_list)) {
373  LOG_ERROR("Chromium-EC: out of memory");
374  return ERROR_FAIL;
375  }
376 
377  for (s = 0; s < ARRAY_SIZE(chromium_ec_symbol_list); s++)
378  (*symbol_list)[s].symbol_name = chromium_ec_symbol_list[s];
379 
380  return ERROR_OK;
381 }
382 
383 const struct rtos_type chromium_ec_rtos = {
384  .name = "Chromium-EC",
385  .detect_rtos = chromium_ec_detect_rtos,
386  .create = chromium_ec_create,
387  .update_threads = chromium_ec_update_threads,
388  .get_thread_reg_list = chromium_ec_get_thread_reg_list,
389  .get_symbol_list_to_lookup = chromium_ec_get_symbol_list_to_lookup,
390 };
static int chromium_ec_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
Definition: chromium-ec.c:366
#define CROS_EC_MAX_BUILDINFO
Definition: chromium-ec.c:79
static int chromium_ec_update_threads(struct rtos *rtos)
Definition: chromium-ec.c:176
const struct rtos_type chromium_ec_rtos
Definition: chromium-ec.c:383
#define CROS_EC_MAX_TASKS
Definition: chromium-ec.c:20
static bool chromium_ec_detect_rtos(struct target *target)
Definition: chromium-ec.c:81
chromium_ec_symbol_values
Definition: chromium-ec.c:67
@ CHROMIUM_EC_VAL_TASKS
Definition: chromium-ec.c:70
@ CHROMIUM_EC_VAL_START_CALLED
Definition: chromium-ec.c:68
@ CHROMIUM_EC_VAL_BUILD_INFO
Definition: chromium-ec.c:74
@ CHROMIUM_EC_VAL_TASKS_READY
Definition: chromium-ec.c:72
@ CHROMIUM_EC_VAL_COUNT
Definition: chromium-ec.c:76
@ CHROMIUM_EC_VAL_CURRENT_TASK
Definition: chromium-ec.c:69
@ CHROMIUM_EC_VAL_TASK_NAMES
Definition: chromium-ec.c:73
@ CHROMIUM_EC_VAL_TASKS_ENABLED
Definition: chromium-ec.c:71
static int chromium_ec_get_num_tasks(struct rtos *rtos, int *num_tasks)
Definition: chromium-ec.c:153
static const char *const chromium_ec_symbol_list[]
Definition: chromium-ec.c:56
static int chromium_ec_create(struct target *target)
Definition: chromium-ec.c:116
static int chromium_ec_get_thread_reg_list(struct rtos *rtos, threadid_t threadid, struct rtos_reg **reg_list, int *num_regs)
Definition: chromium-ec.c:336
#define CROS_EC_MAX_NAME
Definition: chromium-ec.c:21
static const struct chromium_ec_params chromium_ec_params_list[]
Definition: chromium-ec.c:34
#define CROS_EC_IDLE_STRING
Definition: chromium-ec.c:22
static int chromium_ec_get_current_task_ptr(struct rtos *rtos, uint32_t *current_task)
Definition: chromium-ec.c:143
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, struct rtos_reg **reg_list, int *num_regs)
Definition: rtos.c:602
void rtos_free_threadlist(struct rtos *rtos)
Definition: rtos.c:695
int64_t threadid_t
Definition: rtos.h:15
const struct rtos_register_stacking rtos_standard_cortex_m3_stacking
#define BIT(nr)
Definition: stm32l4x.h:18
const struct rtos_register_stacking * stacking
Definition: chromium-ec.c:31
const char * target_name
Definition: chromium-ec.c:25
off_t task_offset_events
Definition: chromium-ec.c:29
off_t task_offset_runtime
Definition: chromium-ec.c:30
Definition: rtos.h:53
Definition: rtos.h:59
const char * name
Definition: rtos.h:60
Definition: rtos.h:36
int thread_count
Definition: rtos.h:47
struct thread_detail * thread_details
Definition: rtos.h:46
struct symbol_table_elem * symbols
Definition: rtos.h:39
struct target * target
Definition: rtos.h:40
void * rtos_specific_params
Definition: rtos.h:50
threadid_t current_thread
Definition: rtos.h:45
Table should be terminated by an element with NULL in symbol_name.
Definition: rtos.h:23
symbol_address_t address
Definition: rtos.h:25
Definition: target.h:116
struct rtos * rtos
Definition: target.h:183
char * extra_info_str
Definition: rtos.h:33
char * thread_name_str
Definition: rtos.h:32
bool exists
Definition: rtos.h:31
threadid_t threadid
Definition: rtos.h:30
uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer)
Definition: target.c:307
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2407
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2550
const char * target_type_name(const struct target *target)
Get the target type name.
Definition: target.c:736
static const char * target_name(const struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:233
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
#define NULL
Definition: usb.h:16