OpenOCD
esp_xtensa_smp.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * ESP Xtensa SMP target API for OpenOCD *
5  * Copyright (C) 2020 Espressif Systems Ltd. Co *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include "assert.h"
13 #include <target/target.h>
14 #include <target/target_type.h>
15 #include <target/smp.h>
17 #include "esp_xtensa_smp.h"
18 #include "esp_xtensa_semihosting.h"
19 #include "esp_algorithm.h"
20 
21 /*
22 Multiprocessor stuff common:
23 
24 The ESP Xtensa chip can have several cores in it, which can run in SMP-mode if an
25 SMP-capable OS is running. The hardware has a few features which makes
26 SMP debugging much easier.
27 
28 First of all, there's something called a 'break network', consisting of a
29 BreakIn input and a BreakOut output on each CPU. The idea is that as soon
30 as a CPU goes into debug mode for whatever reason, it'll signal that using
31 its DebugOut pin. This signal is connected to the other CPU's DebugIn
32 input, causing this CPU also to go into debugging mode. To resume execution
33 when using only this break network, we will need to manually resume both
34 CPUs.
35 
36 An alternative to this is the XOCDMode output and the RunStall (or DebugStall)
37 input. When these are cross-connected, a CPU that goes into debug mode will
38 halt execution entirely on the other CPU. Execution on the other CPU can be
39 resumed by either the first CPU going out of debug mode, or the second CPU
40 going into debug mode: the stall is temporarily lifted as long as the stalled
41 CPU is in debug mode.
42 
43 A third, separate, signal is CrossTrigger. This is connected in the same way
44 as the breakIn/breakOut network, but is for the TRAX (trace memory) feature;
45 it does not affect OCD in any way.
46 */
47 
48 /*
49 Multiprocessor stuff:
50 
51 The ESP Xtensa chip has several Xtensa cores inside, but represent themself to the OCD
52 as one chip that works in multithreading mode under FreeRTOS OS.
53 The core that initiate the stop condition will be defined as an active cpu.
54 When one core stops, then other core will be stopped automatically by smpbreak.
55 The core that initiates stop condition will be defined as an active core, and
56 registers of this core will be transferred.
57 */
58 
59 #define ESP_XTENSA_SMP_EXAMINE_OTHER_CORES 5
60 
61 static int esp_xtensa_smp_update_halt_gdb(struct target *target, bool *need_resume);
62 
64 {
66 }
67 
69 {
70  return ERROR_OK;
71 }
72 
74 {
75  LOG_TARGET_DEBUG(target, "begin");
76 
77  int ret = xtensa_deassert_reset(target);
78  if (ret != ERROR_OK)
79  return ret;
80  /* in SMP mode when chip was running single-core app the other core can be left un-examined,
81  because examination is done before SOC reset. But after SOC reset it is functional and should be handled.
82  So try to examine un-examined core just after SOC reset */
84  ret = xtensa_examine(target);
85  return ret;
86 }
87 
89 {
90  int res;
91  struct target_list *head;
92  struct esp_xtensa_smp_common *esp_xtensa_smp = target_to_esp_xtensa_smp(target);
93 
94  LOG_TARGET_DEBUG(target, "begin");
95  /* in SMP mode we need to ensure that at first we reset SOC on PRO-CPU
96  and then call xtensa_assert_reset() for all cores */
97  if (target->smp) {
99  if (head->target != target)
100  return ERROR_OK;
101  }
102  /* Reset the SoC first */
103  if (esp_xtensa_smp->chip_ops->reset) {
104  res = esp_xtensa_smp->chip_ops->reset(target);
105  if (res != ERROR_OK)
106  return res;
107  }
108  if (!target->smp)
109  return xtensa_assert_reset(target);
110 
112  res = xtensa_assert_reset(head->target);
113  if (res != ERROR_OK)
114  return res;
115  }
116  return ERROR_OK;
117 }
118 
120 {
121  struct target_list *head;
122 
123  if (!target->smp)
124  return esp_xtensa_on_halt(target);
125 
127  int res = esp_xtensa_on_halt(head->target);
128  if (res != ERROR_OK)
129  return res;
130  }
131  return ERROR_OK;
132 }
133 
134 static struct target *get_halted_esp_xtensa_smp(struct target *target, int32_t coreid)
135 {
136  struct target_list *head;
137  struct target *curr;
138 
140  curr = head->target;
141  if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
142  return curr;
143  }
144 
145  return target;
146 }
147 
149 {
150  enum target_state old_state = target->state;
151  struct esp_xtensa_smp_common *esp_xtensa_smp = target_to_esp_xtensa_smp(target);
152  struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
153  uint32_t old_dbg_stubs_base = esp_xtensa->esp.dbg_stubs.base;
154  struct target_list *head;
155  struct target *curr;
156  bool other_core_resume_req = false;
157 
160  LOG_INFO("Switch GDB target to '%s'", target_name(target->gdb_service->target));
161  if (esp_xtensa_smp->chip_ops->on_halt)
162  esp_xtensa_smp->chip_ops->on_halt(target);
164  return ERROR_OK;
165  }
166 
167  int ret = esp_xtensa_poll(target);
168  if (ret != ERROR_OK)
169  return ret;
170 
171  if (esp_xtensa->esp.dbg_stubs.base && old_dbg_stubs_base != esp_xtensa->esp.dbg_stubs.base) {
172  /* debug stubs base is set only in PRO-CPU TRAX register, so sync this info */
174  curr = head->target;
175  if (curr == target)
176  continue;
177  target_to_esp_xtensa(curr)->esp.dbg_stubs.base = esp_xtensa->esp.dbg_stubs.base;
178  }
179  }
180 
181  if (target->smp) {
182  if (target->state == TARGET_RESET) {
184  } else if (esp_xtensa_smp->examine_other_cores > 0 &&
186  LOG_TARGET_DEBUG(target, "Check for unexamined cores after reset");
187  bool all_examined = true;
189  curr = head->target;
190  if (curr == target)
191  continue;
192  if (!target_was_examined(curr)) {
193  if (target_examine_one(curr) != ERROR_OK) {
194  LOG_DEBUG("Failed to examine!");
195  all_examined = false;
196  }
197  }
198  }
199  if (all_examined)
200  esp_xtensa_smp->examine_other_cores = 0;
201  else
202  esp_xtensa_smp->examine_other_cores--;
203  }
204  }
205 
206  if (old_state != TARGET_HALTED && target->state == TARGET_HALTED) {
207  if (target->smp) {
208  ret = esp_xtensa_smp_update_halt_gdb(target, &other_core_resume_req);
209  if (ret != ERROR_OK)
210  return ret;
211  }
212  /* Call any event callbacks that are applicable */
213  if (old_state == TARGET_DEBUG_RUNNING) {
215  } else {
217  if (ret == ERROR_OK && esp_xtensa->semihost.need_resume &&
218  !esp_xtensa_smp->other_core_does_resume) {
219  esp_xtensa->semihost.need_resume = false;
220  /* Resume xtensa_resume will handle BREAK instruction. */
221  ret = target_resume(target, true, 0, true, false);
222  if (ret != ERROR_OK) {
223  LOG_ERROR("Failed to resume target");
224  return ret;
225  }
226  }
227  return ret;
228  }
229  /* check whether any core polled by esp_xtensa_smp_update_halt_gdb() requested resume */
230  if (target->smp && other_core_resume_req) {
231  /* Resume xtensa_resume will handle BREAK instruction. */
232  ret = target_resume(target, true, 0, true, false);
233  if (ret != ERROR_OK) {
234  LOG_ERROR("Failed to resume target");
235  return ret;
236  }
237  return ERROR_OK;
238  }
239  if (esp_xtensa_smp->chip_ops->on_halt)
240  esp_xtensa_smp->chip_ops->on_halt(target);
242  }
243  }
244 
245  return ERROR_OK;
246 }
247 
248 static int esp_xtensa_smp_update_halt_gdb(struct target *target, bool *need_resume)
249 {
250  struct esp_xtensa_smp_common *esp_xtensa_smp;
251  struct target *gdb_target = NULL;
252  struct target_list *head;
253  struct target *curr;
254  int ret = ERROR_OK;
255 
256  *need_resume = false;
257 
259  LOG_DEBUG("GDB target '%s'", target_name(target->gdb_service->target));
260 
261  if (target->gdb_service && target->gdb_service->core[0] == -1) {
264  LOG_INFO("Set GDB target to '%s'", target_name(target));
265  }
266 
267  if (target->gdb_service)
268  gdb_target = target->gdb_service->target;
269 
270  /* due to smpbreak config other cores can also go to HALTED state */
272  curr = head->target;
273  LOG_DEBUG("Check target '%s'", target_name(curr));
274  /* skip calling context */
275  if (curr == target)
276  continue;
277  if (!target_was_examined(curr)) {
278  curr->state = TARGET_HALTED;
279  continue;
280  }
281  /* skip targets that were already halted */
282  if (curr->state == TARGET_HALTED)
283  continue;
284  /* Skip gdb_target; it alerts GDB so has to be polled as last one */
285  if (curr == gdb_target)
286  continue;
287  LOG_DEBUG("Poll target '%s'", target_name(curr));
288 
289  esp_xtensa_smp = target_to_esp_xtensa_smp(curr);
290  /* avoid auto-resume after syscall, it will be done later */
291  esp_xtensa_smp->other_core_does_resume = true;
292  /* avoid recursion in esp_xtensa_smp_poll() */
293  curr->smp = 0;
294  if (esp_xtensa_smp->chip_ops->poll)
295  ret = esp_xtensa_smp->chip_ops->poll(curr);
296  else
297  ret = esp_xtensa_smp_poll(curr);
298  curr->smp = 1;
299  if (ret != ERROR_OK)
300  return ret;
301  esp_xtensa_smp->other_core_does_resume = false;
302  struct esp_xtensa_common *curr_esp_xtensa = target_to_esp_xtensa(curr);
303  if (curr_esp_xtensa->semihost.need_resume) {
304  curr_esp_xtensa->semihost.need_resume = false;
305  *need_resume = true;
306  }
307  }
308 
309  /* after all targets were updated, poll the gdb serving target */
310  if (gdb_target && gdb_target != target) {
311  esp_xtensa_smp = target_to_esp_xtensa_smp(gdb_target);
312  if (esp_xtensa_smp->chip_ops->poll)
313  ret = esp_xtensa_smp->chip_ops->poll(gdb_target);
314  else
315  ret = esp_xtensa_smp_poll(gdb_target);
316  }
317 
318  LOG_DEBUG("exit");
319 
320  return ret;
321 }
322 
323 static inline int esp_xtensa_smp_smpbreak_disable(struct target *target, uint32_t *smp_break)
324 {
325  int res = xtensa_smpbreak_get(target, smp_break);
326  if (res != ERROR_OK)
327  return res;
328  return xtensa_smpbreak_set(target, 0);
329 }
330 
331 static inline int esp_xtensa_smp_smpbreak_restore(struct target *target, uint32_t smp_break)
332 {
333  return xtensa_smpbreak_set(target, smp_break);
334 }
335 
337  bool handle_breakpoints, bool debug_execution)
338 {
339  struct target_list *head;
340  struct target *curr;
341 
342  LOG_TARGET_DEBUG(target, "begin");
343 
345  curr = head->target;
346  /* in single-core mode disabled core cannot be examined, but need to be resumed too*/
347  if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) {
348  /* resume current address, not in SMP mode */
349  curr->smp = 0;
350  int res = esp_xtensa_smp_resume(curr, true, 0, handle_breakpoints, debug_execution);
351  curr->smp = 1;
352  if (res != ERROR_OK)
353  return res;
354  }
355  }
356  return ERROR_OK;
357 }
358 
360  bool current,
362  bool handle_breakpoints,
363  bool debug_execution)
364 {
365  int res;
366  uint32_t smp_break;
367 
368  xtensa_smpbreak_get(target, &smp_break);
369  LOG_TARGET_DEBUG(target, "smp_break=0x%" PRIx32, smp_break);
370 
371  /* dummy resume for smp toggle in order to reduce gdb impact */
372  if ((target->smp) && (target->gdb_service) && (target->gdb_service->core[1] != -1)) {
373  /* simulate a start and halt of target */
376  /* fake resume at next poll we play the target core[1], see poll*/
377  LOG_TARGET_DEBUG(target, "Fake resume");
379  return ERROR_OK;
380  }
381 
382  /* xtensa_prepare_resume() can step over breakpoint/watchpoint and generate signals on BreakInOut circuit for
383  * other cores. So disconnect this core from BreakInOut circuit and do xtensa_prepare_resume(). */
384  res = esp_xtensa_smp_smpbreak_disable(target, &smp_break);
385  if (res != ERROR_OK)
386  return res;
387  res = xtensa_prepare_resume(target, current, address, handle_breakpoints, debug_execution);
388  /* restore configured BreakInOut signals config */
389  int ret = esp_xtensa_smp_smpbreak_restore(target, smp_break);
390  if (ret != ERROR_OK)
391  return ret;
392  if (res != ERROR_OK) {
393  LOG_TARGET_ERROR(target, "Failed to prepare for resume!");
394  return res;
395  }
396 
397  if (target->smp) {
398  if (target->gdb_service)
399  target->gdb_service->core[0] = -1;
400  res = esp_xtensa_smp_resume_cores(target, handle_breakpoints, debug_execution);
401  if (res != ERROR_OK)
402  return res;
403  }
404 
405  res = xtensa_do_resume(target);
406  if (res != ERROR_OK) {
407  LOG_TARGET_ERROR(target, "Failed to resume!");
408  return res;
409  }
410 
412  if (!debug_execution)
414  else
416 
418  return ERROR_OK;
419 }
420 
422  bool current,
424  bool handle_breakpoints)
425 {
426  int res;
427  uint32_t smp_break = 0;
428  struct esp_xtensa_smp_common *esp_xtensa_smp = target_to_esp_xtensa_smp(target);
429 
430  if (target->smp) {
431  res = esp_xtensa_smp_smpbreak_disable(target, &smp_break);
432  if (res != ERROR_OK)
433  return res;
434  }
435  res = xtensa_step(target, current, address, handle_breakpoints);
436 
437  if (res == ERROR_OK) {
438  if (esp_xtensa_smp->chip_ops->on_halt)
439  esp_xtensa_smp->chip_ops->on_halt(target);
441  }
442 
443  if (target->smp) {
444  int ret = esp_xtensa_smp_smpbreak_restore(target, smp_break);
445  if (ret != ERROR_OK)
446  return ret;
447  }
448 
449  return res;
450 }
451 
453 {
455  if (res != ERROR_OK)
456  return res;
457 
458  if (!target->smp)
459  return ERROR_OK;
460 
461  struct target_list *head;
463  struct target *curr = head->target;
464  if (curr == target || !target_was_examined(curr))
465  continue;
466  /* Need to use high level API here because every target for core contains list of watchpoints.
467  * GDB works with active core only, so we need to duplicate every watchpoint on other cores,
468  * otherwise watchpoint_free() on active core can fail if WP has been initially added on another core. */
469  curr->smp = 0;
472  curr->smp = 1;
473  if (res != ERROR_OK)
474  return res;
475  }
476  return ERROR_OK;
477 }
478 
480 {
482  if (res != ERROR_OK)
483  return res;
484 
485  if (!target->smp)
486  return ERROR_OK;
487 
488  struct target_list *head;
490  struct target *curr = head->target;
491  if (curr == target)
492  continue;
493  /* see big comment in esp_xtensa_smp_watchpoint_add() */
494  curr->smp = 0;
496  curr->smp = 1;
497  }
498  return ERROR_OK;
499 }
500 
501 int esp_xtensa_smp_run_func_image(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, ...)
502 {
503  struct target *run_target = target;
504  struct target_list *head;
505  va_list ap;
506  uint32_t smp_break = 0;
507  int res;
508 
509  if (target->smp) {
510  /* find first HALTED and examined core */
512  run_target = head->target;
513  if (target_was_examined(run_target) && run_target->state == TARGET_HALTED)
514  break;
515  }
516  if (!head) {
517  LOG_ERROR("Failed to find HALTED core!");
518  return ERROR_FAIL;
519  }
520 
521  res = esp_xtensa_smp_smpbreak_disable(run_target, &smp_break);
522  if (res != ERROR_OK)
523  return res;
524  }
525 
526  va_start(ap, num_args);
527  int algo_res = esp_algorithm_run_func_image_va(run_target, run, num_args, ap);
528  va_end(ap);
529 
530  if (target->smp) {
531  res = esp_xtensa_smp_smpbreak_restore(run_target, smp_break);
532  if (res != ERROR_OK)
533  return res;
534  }
535  return algo_res;
536 }
537 
539  struct esp_algorithm_run_data *run,
540  uint32_t func_addr,
541  uint32_t num_args,
542  ...)
543 {
544  struct target *run_target = target;
545  struct target_list *head;
546  va_list ap;
547  uint32_t smp_break = 0;
548  int res;
549 
550  if (target->smp) {
551  /* find first HALTED and examined core */
553  run_target = head->target;
554  if (target_was_examined(run_target) && run_target->state == TARGET_HALTED)
555  break;
556  }
557  if (!head) {
558  LOG_ERROR("Failed to find HALTED core!");
559  return ERROR_FAIL;
560  }
561  res = esp_xtensa_smp_smpbreak_disable(run_target, &smp_break);
562  if (res != ERROR_OK)
563  return res;
564  }
565 
566  va_start(ap, num_args);
567  int algo_res = esp_algorithm_run_onboard_func_va(run_target, run, func_addr, num_args, ap);
568  va_end(ap);
569 
570  if (target->smp) {
571  res = esp_xtensa_smp_smpbreak_restore(run_target, smp_break);
572  if (res != ERROR_OK)
573  return res;
574  }
575  return algo_res;
576 }
577 
579  struct esp_xtensa_smp_common *esp_xtensa_smp,
580  struct xtensa_debug_module_config *dm_cfg,
581  const struct esp_xtensa_smp_chip_ops *chip_ops,
582  const struct esp_semihost_ops *semihost_ops)
583 {
584  int ret = esp_xtensa_init_arch_info(target, &esp_xtensa_smp->esp_xtensa, dm_cfg, semihost_ops);
585  if (ret != ERROR_OK)
586  return ret;
587  esp_xtensa_smp->chip_ops = chip_ops;
589  return ERROR_OK;
590 }
591 
593 {
594  int ret = esp_xtensa_target_init(cmd_ctx, target);
595  if (ret != ERROR_OK)
596  return ret;
597 
598  if (target->smp) {
599  struct target_list *head;
601  struct target *curr = head->target;
602  ret = esp_xtensa_semihosting_init(curr);
603  if (ret != ERROR_OK)
604  return ret;
605  }
606  } else {
608  if (ret != ERROR_OK)
609  return ret;
610  }
611  return ERROR_OK;
612 }
613 
614 COMMAND_HANDLER(esp_xtensa_smp_cmd_xtdef)
615 {
617  if (target->smp && CMD_ARGC > 0) {
618  struct target_list *head;
619  struct target *curr;
621  curr = head->target;
622  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtdef_do,
623  target_to_xtensa(curr));
624  if (ret != ERROR_OK)
625  return ret;
626  }
627  return ERROR_OK;
628  }
629  return CALL_COMMAND_HANDLER(xtensa_cmd_xtdef_do,
631 }
632 
633 COMMAND_HANDLER(esp_xtensa_smp_cmd_xtopt)
634 {
636  if (target->smp && CMD_ARGC > 0) {
637  struct target_list *head;
638  struct target *curr;
640  curr = head->target;
641  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtopt_do,
642  target_to_xtensa(curr));
643  if (ret != ERROR_OK)
644  return ret;
645  }
646  return ERROR_OK;
647  }
648  return CALL_COMMAND_HANDLER(xtensa_cmd_xtopt_do,
650 }
651 
652 COMMAND_HANDLER(esp_xtensa_smp_cmd_xtmem)
653 {
655  if (target->smp && CMD_ARGC > 0) {
656  struct target_list *head;
657  struct target *curr;
659  curr = head->target;
660  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtmem_do,
661  target_to_xtensa(curr));
662  if (ret != ERROR_OK)
663  return ret;
664  }
665  return ERROR_OK;
666  }
667  return CALL_COMMAND_HANDLER(xtensa_cmd_xtmem_do,
669 }
670 
671 COMMAND_HANDLER(esp_xtensa_smp_cmd_xtmpu)
672 {
674  if (target->smp && CMD_ARGC > 0) {
675  struct target_list *head;
676  struct target *curr;
678  curr = head->target;
679  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtmpu_do,
680  target_to_xtensa(curr));
681  if (ret != ERROR_OK)
682  return ret;
683  }
684  return ERROR_OK;
685  }
686  return CALL_COMMAND_HANDLER(xtensa_cmd_xtmpu_do,
688 }
689 
690 COMMAND_HANDLER(esp_xtensa_smp_cmd_xtmmu)
691 {
693  if (target->smp && CMD_ARGC > 0) {
694  struct target_list *head;
695  struct target *curr;
697  curr = head->target;
698  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtmmu_do,
699  target_to_xtensa(curr));
700  if (ret != ERROR_OK)
701  return ret;
702  }
703  return ERROR_OK;
704  }
705  return CALL_COMMAND_HANDLER(xtensa_cmd_xtmmu_do,
707 }
708 
709 COMMAND_HANDLER(esp_xtensa_smp_cmd_xtreg)
710 {
712  if (target->smp && CMD_ARGC > 0) {
713  struct target_list *head;
714  struct target *curr;
716  curr = head->target;
717  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtreg_do,
718  target_to_xtensa(curr));
719  if (ret != ERROR_OK)
720  return ret;
721  }
722  return ERROR_OK;
723  }
724  return CALL_COMMAND_HANDLER(xtensa_cmd_xtreg_do,
726 }
727 
728 COMMAND_HANDLER(esp_xtensa_smp_cmd_xtregfmt)
729 {
731  if (target->smp && CMD_ARGC > 0) {
732  struct target_list *head;
733  struct target *curr;
735  curr = head->target;
736  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_xtregfmt_do,
737  target_to_xtensa(curr));
738  if (ret != ERROR_OK)
739  return ret;
740  }
741  return ERROR_OK;
742  }
743  return CALL_COMMAND_HANDLER(xtensa_cmd_xtregfmt_do,
745 }
746 
747 COMMAND_HANDLER(esp_xtensa_smp_cmd_permissive_mode)
748 {
750  if (target->smp && CMD_ARGC > 0) {
751  struct target_list *head;
752  struct target *curr;
754  curr = head->target;
755  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_permissive_mode_do,
756  target_to_xtensa(curr));
757  if (ret != ERROR_OK)
758  return ret;
759  }
760  return ERROR_OK;
761  }
762  return CALL_COMMAND_HANDLER(xtensa_cmd_permissive_mode_do,
764 }
765 
766 COMMAND_HANDLER(esp_xtensa_smp_cmd_smpbreak)
767 {
769  if (target->smp && CMD_ARGC > 0) {
770  struct target_list *head;
771  struct target *curr;
773  curr = head->target;
774  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_smpbreak_do, curr);
775  if (ret != ERROR_OK)
776  return ret;
777  }
778  return ERROR_OK;
779  }
780  return CALL_COMMAND_HANDLER(xtensa_cmd_smpbreak_do, target);
781 }
782 
783 COMMAND_HANDLER(esp_xtensa_smp_cmd_mask_interrupts)
784 {
786  if (target->smp && CMD_ARGC > 0) {
787  struct target_list *head;
788  struct target *curr;
790  curr = head->target;
791  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_mask_interrupts_do,
792  target_to_xtensa(curr));
793  if (ret != ERROR_OK)
794  return ret;
795  }
796  return ERROR_OK;
797  }
798  return CALL_COMMAND_HANDLER(xtensa_cmd_mask_interrupts_do,
800 }
801 
802 COMMAND_HANDLER(esp_xtensa_smp_cmd_perfmon_enable)
803 {
805  if (target->smp && CMD_ARGC > 0) {
806  struct target_list *head;
807  struct target *curr;
809  curr = head->target;
810  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_enable_do,
811  target_to_xtensa(curr));
812  if (ret != ERROR_OK)
813  return ret;
814  }
815  return ERROR_OK;
816  }
817  return CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_enable_do,
819 }
820 
821 COMMAND_HANDLER(esp_xtensa_smp_cmd_perfmon_dump)
822 {
824  if (target->smp) {
825  struct target_list *head;
826  struct target *curr;
828  curr = head->target;
829  LOG_TARGET_INFO(curr, ":");
830  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_dump_do,
831  target_to_xtensa(curr));
832  if (ret != ERROR_OK)
833  return ret;
834  }
835  return ERROR_OK;
836  }
837  return CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_dump_do,
839 }
840 
841 COMMAND_HANDLER(esp_xtensa_smp_cmd_tracestart)
842 {
844  if (target->smp) {
845  struct target_list *head;
846  struct target *curr;
848  curr = head->target;
849  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_tracestart_do,
850  target_to_xtensa(curr));
851  if (ret != ERROR_OK)
852  return ret;
853  }
854  return ERROR_OK;
855  }
856  return CALL_COMMAND_HANDLER(xtensa_cmd_tracestart_do,
858 }
859 
860 COMMAND_HANDLER(esp_xtensa_smp_cmd_tracestop)
861 {
863  if (target->smp) {
864  struct target_list *head;
865  struct target *curr;
867  curr = head->target;
868  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_tracestop_do,
869  target_to_xtensa(curr));
870  if (ret != ERROR_OK)
871  return ret;
872  }
873  return ERROR_OK;
874  }
875  return CALL_COMMAND_HANDLER(xtensa_cmd_tracestop_do,
877 }
878 
879 COMMAND_HANDLER(esp_xtensa_smp_cmd_tracedump)
880 {
882  if (target->smp) {
883  struct target_list *head;
884  struct target *curr;
885  int32_t cores_max_id = 0;
886  /* assume that core IDs are assigned to SMP targets sequentially: 0,1,2... */
888  curr = head->target;
889  if (cores_max_id < curr->coreid)
890  cores_max_id = curr->coreid;
891  }
892  if (CMD_ARGC < ((uint32_t)cores_max_id + 1)) {
894  "Need %d filenames to dump to as output!",
895  cores_max_id + 1);
896  return ERROR_FAIL;
897  }
899  curr = head->target;
900  int ret = CALL_COMMAND_HANDLER(xtensa_cmd_tracedump_do,
901  target_to_xtensa(curr), CMD_ARGV[curr->coreid]);
902  if (ret != ERROR_OK)
903  return ret;
904  }
905  return ERROR_OK;
906  }
907  return CALL_COMMAND_HANDLER(xtensa_cmd_tracedump_do,
909 }
910 
912  {
913  .name = "xtdef",
914  .handler = esp_xtensa_smp_cmd_xtdef,
915  .mode = COMMAND_CONFIG,
916  .help = "Configure Xtensa core type",
917  .usage = "<type>",
918  },
919  {
920  .name = "xtopt",
921  .handler = esp_xtensa_smp_cmd_xtopt,
922  .mode = COMMAND_CONFIG,
923  .help = "Configure Xtensa core option",
924  .usage = "<name> <value>",
925  },
926  {
927  .name = "xtmem",
928  .handler = esp_xtensa_smp_cmd_xtmem,
929  .mode = COMMAND_CONFIG,
930  .help = "Configure Xtensa memory/cache option",
931  .usage = "<type> [parameters]",
932  },
933  {
934  .name = "xtmmu",
935  .handler = esp_xtensa_smp_cmd_xtmmu,
936  .mode = COMMAND_CONFIG,
937  .help = "Configure Xtensa MMU option",
938  .usage = "<NIREFILLENTRIES> <NDREFILLENTRIES> <IVARWAY56> <DVARWAY56>",
939  },
940  {
941  .name = "xtmpu",
942  .handler = esp_xtensa_smp_cmd_xtmpu,
943  .mode = COMMAND_CONFIG,
944  .help = "Configure Xtensa MPU option",
945  .usage = "<num FG seg> <min seg size> <lockable> <executeonly>",
946  },
947  {
948  .name = "xtreg",
949  .handler = esp_xtensa_smp_cmd_xtreg,
950  .mode = COMMAND_CONFIG,
951  .help = "Configure Xtensa register",
952  .usage = "<regname> <regnum>",
953  },
954  {
955  .name = "xtregs",
956  .handler = esp_xtensa_smp_cmd_xtreg,
957  .mode = COMMAND_CONFIG,
958  .help = "Configure number of Xtensa registers",
959  .usage = "<numregs>",
960  },
961  {
962  .name = "xtregfmt",
963  .handler = esp_xtensa_smp_cmd_xtregfmt,
964  .mode = COMMAND_CONFIG,
965  .help = "Configure format of Xtensa register map",
966  .usage = "<numgregs>",
967  },
968  {
969  .name = "set_permissive",
970  .handler = esp_xtensa_smp_cmd_permissive_mode,
971  .mode = COMMAND_ANY,
972  .help = "When set to 1, enable Xtensa permissive mode (less client-side checks)",
973  .usage = "[0|1]",
974  },
975  {
976  .name = "maskisr",
977  .handler = esp_xtensa_smp_cmd_mask_interrupts,
978  .mode = COMMAND_ANY,
979  .help = "mask Xtensa interrupts at step",
980  .usage = "['on'|'off']",
981  },
982  {
983  .name = "smpbreak",
984  .handler = esp_xtensa_smp_cmd_smpbreak,
985  .mode = COMMAND_ANY,
986  .help = "Set the way the CPU chains OCD breaks",
987  .usage =
988  "[none|breakinout|runstall] | [BreakIn] [BreakOut] [RunStallIn] [DebugModeOut]",
989  },
990  {
991  .name = "perfmon_enable",
992  .handler = esp_xtensa_smp_cmd_perfmon_enable,
993  .mode = COMMAND_EXEC,
994  .help = "Enable and start performance counter",
995  .usage = "<counter_id> <select> [mask] [kernelcnt] [tracelevel]",
996  },
997  {
998  .name = "perfmon_dump",
999  .handler = esp_xtensa_smp_cmd_perfmon_dump,
1000  .mode = COMMAND_EXEC,
1001  .help =
1002  "Dump performance counter value. If no argument specified, dumps all counters.",
1003  .usage = "[counter_id]",
1004  },
1005  {
1006  .name = "tracestart",
1007  .handler = esp_xtensa_smp_cmd_tracestart,
1008  .mode = COMMAND_EXEC,
1009  .help =
1010  "Tracing: Set up and start a trace. Optionally set stop trigger address and amount of data captured after.",
1011  .usage = "[pc <pcval>/[maskbitcount]] [after <n> [ins|words]]",
1012  },
1013  {
1014  .name = "tracestop",
1015  .handler = esp_xtensa_smp_cmd_tracestop,
1016  .mode = COMMAND_EXEC,
1017  .help = "Tracing: Stop current trace as started by the tracestart command",
1018  .usage = "",
1019  },
1020  {
1021  .name = "tracedump",
1022  .handler = esp_xtensa_smp_cmd_tracedump,
1023  .mode = COMMAND_EXEC,
1024  .help = "Tracing: Dump trace memory to a files. One file per core.",
1025  .usage = "<outfile1> <outfile2>",
1026  },
1028 };
1029 
1031  {
1032  .name = "xtensa",
1033  .usage = "",
1035  },
1037 };
int watchpoint_add(struct target *target, target_addr_t address, unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
Definition: breakpoints.c:568
int watchpoint_remove(struct target *target, target_addr_t address)
Definition: breakpoints.c:605
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:141
#define CALL_COMMAND_HANDLER(name, extra ...)
Use this to macro to call a command helper (or a nested handler).
Definition: command.h:118
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:146
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
@ COMMAND_EXEC
Definition: command.h:40
uint32_t address
Starting address. Sector aligned.
Definition: dw-spi-helper.h:0
static int esp_algorithm_run_func_image_va(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, va_list ap)
Loads and runs stub from specified image.
static int esp_algorithm_run_onboard_func_va(struct target *target, struct esp_algorithm_run_data *run, target_addr_t func_addr, uint32_t num_args, va_list ap)
Runs pre-compiled on-board function.
int esp_xtensa_init_arch_info(struct target *target, struct esp_xtensa_common *esp_xtensa, struct xtensa_debug_module_config *dm_cfg, const struct esp_semihost_ops *semihost_ops)
Definition: esp_xtensa.c:65
int esp_xtensa_poll(struct target *target)
Definition: esp_xtensa.c:105
int esp_xtensa_target_init(struct command_context *cmd_ctx, struct target *target)
Definition: esp_xtensa.c:82
int esp_xtensa_on_halt(struct target *target)
Definition: esp_xtensa.c:58
static struct esp_xtensa_common * target_to_esp_xtensa(struct target *target)
Definition: esp_xtensa.h:24
int esp_xtensa_semihosting_init(struct target *target)
int esp_xtensa_semihosting(struct target *target, int *retval)
Checks and processes an ESP Xtensa semihosting request.
int esp_xtensa_smp_run_onboard_func(struct target *target, struct esp_algorithm_run_data *run, uint32_t func_addr, uint32_t num_args,...)
int esp_xtensa_smp_init_arch_info(struct target *target, struct esp_xtensa_smp_common *esp_xtensa_smp, struct xtensa_debug_module_config *dm_cfg, const struct esp_xtensa_smp_chip_ops *chip_ops, const struct esp_semihost_ops *semihost_ops)
const struct command_registration esp_xtensa_smp_command_handlers[]
int esp_xtensa_smp_step(struct target *target, bool current, target_addr_t address, bool handle_breakpoints)
#define ESP_XTENSA_SMP_EXAMINE_OTHER_CORES
static int esp_xtensa_smp_update_halt_gdb(struct target *target, bool *need_resume)
COMMAND_HANDLER(esp_xtensa_smp_cmd_xtdef)
static int esp_xtensa_smp_resume_cores(struct target *target, bool handle_breakpoints, bool debug_execution)
int esp_xtensa_smp_soft_reset_halt(struct target *target)
int esp_xtensa_smp_deassert_reset(struct target *target)
int esp_xtensa_smp_resume(struct target *target, bool current, target_addr_t address, bool handle_breakpoints, bool debug_execution)
const struct command_registration esp_xtensa_smp_xtensa_command_handlers[]
static struct esp_xtensa_smp_common * target_to_esp_xtensa_smp(struct target *target)
static int esp_xtensa_smp_smpbreak_disable(struct target *target, uint32_t *smp_break)
int esp_xtensa_smp_watchpoint_remove(struct target *target, struct watchpoint *watchpoint)
int esp_xtensa_smp_run_func_image(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args,...)
static int esp_xtensa_smp_smpbreak_restore(struct target *target, uint32_t smp_break)
int esp_xtensa_smp_target_init(struct command_context *cmd_ctx, struct target *target)
int esp_xtensa_smp_on_halt(struct target *target)
int esp_xtensa_smp_watchpoint_add(struct target *target, struct watchpoint *watchpoint)
int esp_xtensa_smp_assert_reset(struct target *target)
int esp_xtensa_smp_poll(struct target *target)
static struct target * get_halted_esp_xtensa_smp(struct target *target, int32_t coreid)
#define list_first_entry(ptr, type, member)
Definition: list.h:127
#define LOG_TARGET_INFO(target, fmt_str,...)
Definition: log.h:153
#define ERROR_FAIL
Definition: log.h:174
#define LOG_TARGET_ERROR(target, fmt_str,...)
Definition: log.h:162
#define LOG_TARGET_DEBUG(target, fmt_str,...)
Definition: log.h:150
#define LOG_ERROR(expr ...)
Definition: log.h:133
#define LOG_INFO(expr ...)
Definition: log.h:127
#define LOG_DEBUG(expr ...)
Definition: log.h:110
#define ERROR_OK
Definition: log.h:168
static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) __attribute__((unused))
Definition: opcodes.h:117
struct target * target
Definition: rtt/rtt.c:26
@ SEMIHOSTING_HANDLED
#define foreach_smp_target(pos, head)
Definition: smp.h:15
const char * name
Definition: command.h:235
Algorithm run data.
struct esp_dbg_stubs dbg_stubs
Definition: esp.h:81
uint32_t base
Address.
Definition: esp.h:70
Semihost calls handling operations.
struct esp_semihost_data semihost
Definition: esp_xtensa.h:20
struct esp_common esp
Definition: esp_xtensa.h:19
int(* poll)(struct target *target)
int(* on_halt)(struct target *target)
int(* reset)(struct target *target)
struct esp_xtensa_common esp_xtensa
const struct esp_xtensa_smp_chip_ops * chip_ops
int32_t core[2]
Definition: target.h:100
struct target * target
Definition: target.h:95
struct target * target
Definition: target.h:214
Definition: target.h:116
int32_t coreid
Definition: target.h:120
struct gdb_service * gdb_service
Definition: target.h:199
enum target_debug_reason debug_reason
Definition: target.h:154
enum target_state state
Definition: target.h:157
struct list_head * smp_targets
Definition: target.h:188
unsigned int smp
Definition: target.h:187
void * arch_info
Definition: target.h:164
uint64_t mask
Definition: breakpoints.h:44
enum watchpoint_rw rw
Definition: breakpoints.h:46
unsigned int length
Definition: breakpoints.h:43
uint64_t value
Definition: breakpoints.h:45
target_addr_t address
Definition: breakpoints.h:42
int target_call_event_callbacks(struct target *target, enum target_event event)
Definition: target.c:1765
int target_examine_one(struct target *target)
Examine the specified target, letting it perform any Initialisation that requires JTAG access.
Definition: target.c:673
int target_resume(struct target *target, bool current, target_addr_t address, bool handle_breakpoints, bool debug_execution)
Make the target (re)start executing using its saved execution context (possibly with some modificatio...
Definition: target.c:556
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:458
@ DBG_REASON_NOTHALTED
Definition: target.h:74
static bool target_was_examined(const struct target *target)
Definition: target.h:436
@ TARGET_EVENT_HALTED
Definition: target.h:252
@ TARGET_EVENT_RESUMED
Definition: target.h:253
@ TARGET_EVENT_DEBUG_HALTED
Definition: target.h:271
static const char * target_name(const struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:233
target_state
Definition: target.h:53
@ TARGET_RESET
Definition: target.h:57
@ TARGET_DEBUG_RUNNING
Definition: target.h:58
@ TARGET_HALTED
Definition: target.h:56
@ TARGET_RUNNING
Definition: target.h:55
uint64_t target_addr_t
Definition: types.h:335
#define container_of(ptr, type, member)
Cast a member of a structure out to the containing structure.
Definition: types.h:68
#define NULL
Definition: usb.h:16
int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint)
Definition: xtensa.c:2649
int xtensa_smpbreak_set(struct target *target, uint32_t set)
Definition: xtensa.c:944
int xtensa_examine(struct target *target)
Definition: xtensa.c:886
int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint)
Definition: xtensa.c:2705
int xtensa_smpbreak_get(struct target *target, uint32_t *val)
Definition: xtensa.c:968
int xtensa_do_resume(struct target *target)
Definition: xtensa.c:1656
int xtensa_deassert_reset(struct target *target)
Definition: xtensa.c:1182
int xtensa_assert_reset(struct target *target)
Definition: xtensa.c:1161
int xtensa_step(struct target *target, bool current, target_addr_t address, bool handle_breakpoints)
Definition: xtensa.c:1946
int xtensa_prepare_resume(struct target *target, bool current, target_addr_t address, bool handle_breakpoints, bool debug_execution)
Definition: xtensa.c:1593
static struct xtensa * target_to_xtensa(struct target *target)
Definition: xtensa.h:291