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