source: rtems/cpukit/libdebugger/rtems-debugger-arm.c @ be5eee57

Last change on this file since be5eee57 was be5eee57, checked in by Sebastian Huber <sebastian.huber@…>, on 12/22/20 at 10:51:53

libdebugger: Fix for Armv8-R

This architecture variant has no MMU.

Update #4202.

  • Property mode set to 100644
File size: 64.8 KB
Line 
1/*
2 * Copyright (c) 2016-2019 Chris Johns <chrisj@rtems.org>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#define TARGET_DEBUG 0
28
29#define ARM_DUMP_ROM_TABLES 0
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include <errno.h>
36#include <inttypes.h>
37#include <stdlib.h>
38
39#include <rtems.h>
40#include <rtems/score/threadimpl.h>
41
42#include <rtems/debugger/rtems-debugger-bsp.h>
43
44#include "rtems-debugger-target.h"
45#include "rtems-debugger-threads.h"
46
47#if TARGET_DEBUG
48#include <rtems/bspIo.h>
49#endif
50
51/*
52 * ARM Variant controls.
53 */
54#if (__ARM_ARCH >= 7) && \
55    (__ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R')
56  #define ARM_CP15 1
57#endif
58
59#if (__ARM_ARCH >= 7) && \
60    (__ARM_ARCH_PROFILE == 'M')
61  #define ARM_THUMB_ONLY 1
62#else
63  #define ARM_THUMB_ONLY 0
64#endif
65
66#if defined(ARM_MULTILIB_ARCH_V4)
67 #define ARM_PSR_HAS_INT_MASK 1
68 #define ARM_PSR_HAS_THUMB    1
69#else
70 #define ARM_PSR_HAS_INT_MASK 0
71 #define ARM_PSR_HAS_THUMB    0
72#endif
73
74#if ARM_CP15
75#include <libcpu/arm-cp15.h>
76#endif
77
78/**
79 * If thumb build of code switch the asm to thumb as required.
80 *
81 * If the variant only supports thumb insturctions disable the support.
82 */
83#define NEEDS_THUMB_SWITCH !ARM_THUMB_ONLY && defined(__thumb__)
84
85#if NEEDS_THUMB_SWITCH
86  #define ARM_SWITCH_REG       uint32_t arm_switch_reg
87  #define ARM_SWITCH_REG_ASM   [arm_switch_reg] "=&r" (arm_switch_reg)
88  #define ARM_SWITCH_REG_ASM_L ARM_SWITCH_REG_ASM,
89  #define ASM_ARM_MODE         ".align 2\nbx pc\n.arm\n"
90  #define ASM_THUMB_MODE       "add %[arm_switch_reg], pc, #1\nbx %[arm_switch_reg]\n.thumb\n"
91#else
92  #define ARM_SWITCH_REG
93  #define ARM_SWITCH_REG_ASM
94  #define ARM_SWITCH_REG_ASM_L
95  #define ASM_ARM_MODE
96  #define ASM_THUMB_MODE
97#endif
98
99/*
100 * Hack to work around ARMv7-M not having a the T and I bits in the PSR.
101 *
102 * This needs to be fixed when real support for this ARM variant is added.
103 */
104#if !defined(ARM_PSR_I)
105  #define ARM_PSR_I 0
106#endif
107#if !defined(ARM_PSR_T)
108  #define ARM_PSR_T 0
109#endif
110
111/*
112 * The ARM has 2 interrupt bits.
113 */
114#define CPSR_IRQ_DISABLE 0x80    /* IIQ disabled when 1 */
115#define CPSR_FIQ_DISABLE 0x40    /* FIQ disabled when 1 */
116#define CPSR_INTS_MASK   (CPSR_IRQ_DISABLE | CPSR_FIQ_DISABLE)
117
118/*
119 * Software breakpoint block size.
120 */
121#define RTEMS_DEBUGGER_SWBREAK_NUM 64
122
123/*
124 * Number of registers.
125 */
126#define RTEMS_DEBUGGER_NUMREGS 26
127
128/*
129 * Number of bytes per type of register.
130 */
131#define RTEMS_DEBUGGER_REG_BYTES    4
132#define RTEMS_DEBUGGER_FP_REG_BYTES 12
133
134/*
135 * Debugger registers layout. See arm-core.xml in GDB source.
136 */
137#define REG_R0    0
138#define REG_R1    1
139#define REG_R2    2
140#define REG_R3    3
141#define REG_R4    4
142#define REG_R5    5
143#define REG_R6    6
144#define REG_R7    7
145#define REG_R8    8
146#define REG_R9    9
147#define REG_R10   10
148#define REG_R11   11
149#define REG_R12   12
150#define REG_SP    13
151#define REG_LR    14
152#define REG_PC    15
153#define REG_F0    16
154#define REG_F1    17
155#define REG_F2    18
156#define REG_F3    19
157#define REG_F4    20
158#define REG_F5    21
159#define REG_F6    22
160#define REG_F7    23
161#define REG_FPS   24
162#define REG_CPSR  25
163
164/**
165 * Register offset table with the total as the last entry.
166 *
167 * Check this table in gdb with the command:
168 *
169 *   maint print registers
170 */
171static const size_t arm_reg_offsets[RTEMS_DEBUGGER_NUMREGS + 1] =
172{
173  0,   /* REG_R0    4 uint32_t */
174  4,   /* REG_R1    4 uint32_t */
175  8,   /* REG_R2    4 uint32_t */
176  12,  /* REG_R3    4 uint32_t */
177  16,  /* REG_R4    4 uint32_t */
178  20,  /* REG_R5    4 uint32_t */
179  24,  /* REG_R6    4 uint32_t */
180  28,  /* REG_R7    4 uint32_t */
181  32,  /* REG_R8    4 uint32_t */
182  36,  /* REG_R9    4 uint32_t */
183  40,  /* REG_R10   4 uint32_t */
184  44,  /* REG_R11   4 uint32_t */
185  48,  /* REG_R12   4 uint32_t */
186  52,  /* REG_SP    4 *1 */
187  56,  /* REG_LR    4 uint32_t */
188  60,  /* REG_PC    4 *1 */
189  64,  /* REG_F0   12 _arm_ext */
190  76,  /* REG_F1   12 _arm_ext */
191  88,  /* REG_F2   12 _arm_ext */
192  100, /* REG_F3   12 _arm_ext */
193  112, /* REG_F4   12 _arm_ext */
194  124, /* REG_F5   12 _arm_ext */
195  136, /* REG_F6   12 _arm_ext */
196  148, /* REG_F7   12 _arm_ext */
197  160, /* REG_FPS   4 uint32_t */
198  164, /* REG_CPSR  4 uint32_t */
199  168  /* total size */
200};
201
202/*
203 * Number of bytes of registers.
204 */
205#define RTEMS_DEBUGGER_NUMREGBYTES arm_reg_offsets[RTEMS_DEBUGGER_NUMREGS]
206
207/**
208 * The various status registers.
209 */
210#if defined(ARM_MULTILIB_ARCH_V4) || defined(ARM_MULTILIB_ARCH_V6M)
211 #define FRAME_SR(_frame) (_frame)->register_cpsr
212#elif defined(ARM_MULTILIB_ARCH_V7M)
213 #define FRAME_SR(_frame) (_frame)->register_xpsr
214#else
215 #error ARM architecture is not supported.
216#endif
217
218/**
219 * Print the exception frame.
220 */
221#define EXC_FRAME_PRINT(_out, _prefix, _frame) \
222do { \
223  _out(_prefix "  R0 = %08" PRIx32 "  R1 = %08" PRIx32       \
224               "  R2 = %08" PRIx32 "  R3 = %08" PRIx32 "\n", \
225       _frame->register_r0, _frame->register_r1, \
226       _frame->register_r2, _frame->register_r3); \
227  _out(_prefix "  R4 = %08" PRIx32 "  R5 = %08" PRIx32       \
228               "  R6 = %08" PRIx32 "  R7 = %08" PRIx32 "\n", \
229       _frame->register_r4, _frame->register_r5, \
230       _frame->register_r6, _frame->register_r7); \
231  _out(_prefix "  R8 = %08" PRIx32 "  R9 = %08" PRIx32       \
232               " R10 = %08" PRIx32 " R11 = %08" PRIx32 "\n", \
233       _frame->register_r8, _frame->register_r9, \
234       _frame->register_r10, _frame->register_r11); \
235  _out(_prefix " R12 = %08" PRIx32 "  SP = %08" PRIx32       \
236               "  LR = %08" PRIxPTR "  PC = %08" PRIxPTR "\n", \
237       _frame->register_r12, _frame->register_sp, \
238       (intptr_t) _frame->register_lr, (intptr_t) _frame->register_pc); \
239  _out(_prefix " CPSR = %08" PRIx32 " %c%c%c%c%c%c%c%c%c%c%c"       \
240               " GE:%" PRIx32 " IT:%02" PRIx32 " M:%" PRIx32 " %s\n", \
241       FRAME_SR(_frame), \
242       (FRAME_SR(_frame) & (1 << 31)) != 0 ? 'N' : '-', \
243       (FRAME_SR(_frame) & (1 << 30)) != 0 ? 'Z' : '-', \
244       (FRAME_SR(_frame) & (1 << 29)) != 0 ? 'C' : '-', \
245       (FRAME_SR(_frame) & (1 << 28)) != 0 ? 'V' : '-', \
246       (FRAME_SR(_frame) & (1 << 27)) != 0 ? 'Q' : '-', \
247       (FRAME_SR(_frame) & (1 << 24)) != 0 ? 'J' : '-', \
248       (FRAME_SR(_frame) & (1 <<  9)) != 0 ? 'E' : '-', \
249       (FRAME_SR(_frame) & (1 <<  8)) != 0 ? 'A' : '-', \
250       (FRAME_SR(_frame) & (1 <<  7)) != 0 ? 'I' : '-', \
251       (FRAME_SR(_frame) & (1 <<  6)) != 0 ? 'F' : '-', \
252       (FRAME_SR(_frame) & (1 <<  5)) != 0 ? 'T' : '-', \
253       (FRAME_SR(_frame) >> 16) & 0xf, \
254       ((FRAME_SR(_frame) >> (25 - 5)) & (0x3 << 5)) | ((FRAME_SR(_frame) >> 10) & 0x1f), \
255       FRAME_SR(_frame) & 0x1f, arm_mode_label(FRAME_SR(_frame) & 0x1f)); \
256} while (0)
257
258/**
259 * The breakpoint.
260 */
261#ifdef __thumb__
262 static const uint8_t breakpoint[2] = { 0x55, 0xbe };
263#else
264 static const uint8_t breakpoint[4] = { 0x75, 0xe0, 0x20, 0xe1 };
265#endif
266
267/**
268 * Target lock.
269 */
270RTEMS_INTERRUPT_LOCK_DEFINE(static, target_lock, "target_lock")
271
272/**
273 * An exception offset is added to the return address of the PC on an
274 * exception's stack frame. The PC needs to be adjusted.
275 */
276static const size_t exc_offsets[2][5] =
277{
278  /* ARM undef_ins sup call pref abt data abt */
279  {  0,  4,        0,       4,       8 },
280  /* TMB undef_ins sup call pref abt data abt */
281  {  0,  2,        0,       4,       8 }
282};
283
284/**
285 * Is a session active?
286 */
287static bool debug_session_active;
288
289/*
290 * ARM debug hardware.
291 */
292static int   debug_version;
293static void* debug_registers;
294static int   debug_revision;
295static bool  debug_disable_ints;
296static int   hw_breakpoints;
297static int   hw_watchpoints;
298
299/**
300 * Hardware break and watch points.
301 */
302typedef struct
303{
304  bool                 enabled;
305  bool                 loaded;
306  void*                address;
307  size_t               length;
308  CPU_Exception_frame* frame;
309  uint32_t             control;
310  uint32_t             value;
311} arm_debug_hwbreak;
312
313#define ARM_HW_BREAKPOINT_MAX (16)
314#define ARM_HW_WATCHPOINT_MAX (16)
315
316/*
317 * Types of break points. Only the 2 we use listed.
318 */
319#define ARM_HW_BP_UNLINKED_INSTR_MATCH    (0x00)
320#define ARM_HW_BP_UNLINKED_INSTR_MISMATCH (0x04)
321
322/*
323 * Privilege levels.
324 */
325#define ARM_HW_BP_PRIV_PL0_SUP_SYS (0x00)
326#define ARM_HW_BP_PRIV_PL1_ONLY    (0x01)
327#define ARM_HW_BP_PRIV_PL0_ONLY    (0x02)
328#define ARM_HW_BP_PRIV_ALL_MODES   (0x03)
329
330static arm_debug_hwbreak hw_breaks[ARM_HW_BREAKPOINT_MAX];
331//static arm_debug_hwbreak hw_watches[ARM_HW_WATCHPOINT_MAX];
332
333/*
334 * Method of entry (MOE) to debug mode. Bits [5:2] of DBGDSCR.
335 */
336#define ARM_HW_DSCR_MOE_HALT_REQUEST       (0x0)
337#define ARM_HW_DSCR_MOE_BREAKPOINT_EVENT   (0x1)
338#define ARM_HW_DSCR_MOE_ASYNC_WATCHPOINT   (0x2)
339#define ARM_HW_DSCR_MOE_BREAKPOINT_INSTR   (0x3)
340#define ARM_HW_DSCR_MOE_EXTERNAL           (0x4)
341#define ARM_HW_DSCR_MOE_VECTOR_CATCH_EVENT (0x5)
342#define ARM_HW_DSCR_MOE_OS_UNLOCK_EVENT    (0x8)
343#define ARM_HW_DSCR_MOE_SYNC_WATCHPOINT    (0xa)
344
345/*
346 * Use to locally probe and catch exceptions when accessinf suspect addresses.
347 */
348#if ARM_CP15
349static void __attribute__((naked)) arm_debug_unlock_abort(void);
350#endif
351
352/*
353 * Target debugging support. Use this to debug the backend.
354 */
355#if TARGET_DEBUG
356void rtems_debugger_printk_lock(rtems_interrupt_lock_context* lock_context);
357void rtems_debugger_printk_unlock(rtems_interrupt_lock_context* lock_context);
358
359static void target_printk(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
360static void
361target_printk(const char* format, ...)
362{
363  rtems_interrupt_lock_context lock_context;
364  va_list ap;
365  va_start(ap, format);
366  rtems_debugger_printk_lock(&lock_context);
367  vprintk(format, ap);
368  rtems_debugger_printk_unlock(&lock_context);
369  va_end(ap);
370}
371#else
372#define target_printk(_fmt, ...)
373#define mode_labels(_m) NULL
374#endif
375
376static const char*
377arm_mode_label(int mode)
378{
379  switch (mode) {
380  case 0x10:
381    return "USR";
382  case 0x11:
383    return "FIQ";
384  case 0x12:
385    return "IRQ";
386  case 0x13:
387    return "SVC";
388  case 0x16:
389    return "MON";
390  case 0x17:
391    return "ABT";
392  case 0x1a:
393    return "HYP";
394  case 0x1b:
395    return "UND";
396  case 0x1f:
397    return "SYS";
398  }
399  return "---";
400}
401
402#if TARGET_DEBUG
403static const char*
404arm_moe_label(uint32_t moe)
405{
406  switch (moe) {
407  case ARM_HW_DSCR_MOE_HALT_REQUEST:
408    return "HLT";
409  case ARM_HW_DSCR_MOE_BREAKPOINT_EVENT:
410    return "BPE";
411  case ARM_HW_DSCR_MOE_ASYNC_WATCHPOINT:
412    return "AWP";
413  case ARM_HW_DSCR_MOE_BREAKPOINT_INSTR:
414    return "BPI";
415  case ARM_HW_DSCR_MOE_EXTERNAL:
416    return "EXT";
417  case ARM_HW_DSCR_MOE_VECTOR_CATCH_EVENT:
418    return "VCE";
419  case ARM_HW_DSCR_MOE_OS_UNLOCK_EVENT:
420    return "OUL";
421  case ARM_HW_DSCR_MOE_SYNC_WATCHPOINT:
422    return "SWP";
423  default:
424    break;
425  }
426  return "RSV";
427}
428#endif
429
430/*
431 * CP register access.
432 */
433#define ARM_CP_INSTR(_opc, _cp, _op1, _val, _CRn, _CRm, _op2)           \
434  #_opc " p" #_cp ", " #_op1 ", %[" #_val "], c" #_CRn ", c" #_CRm ", " #_op2 "\n"
435
436#define ARM_CP_WRITE(_cp, _op1, _val, _CRn, _CRm, _op2)    \
437  do {                                                     \
438    ARM_SWITCH_REG;                                        \
439    asm volatile(                                          \
440      ASM_ARM_MODE                                         \
441      ARM_CP_INSTR(mcr, _cp, _op1, val, _CRn, _CRm, _op2)  \
442      ASM_THUMB_MODE                                       \
443      : ARM_SWITCH_REG_ASM                                 \
444      : [val] "r" (_val));                                 \
445  } while (0)
446
447#define ARM_CP_READ(_cp, _op1, _val, _CRn, _CRm, _op2)     \
448  do {                                                     \
449    ARM_SWITCH_REG;                                        \
450    asm volatile(                                          \
451      ASM_ARM_MODE                                         \
452      ARM_CP_INSTR(mrc, _cp, _op1, val, _CRn, _CRm, _op2)  \
453      ASM_THUMB_MODE                                       \
454      : ARM_SWITCH_REG_ASM_L                               \
455        [val] "=&r" (_val));                               \
456  } while (0)
457
458/*
459 * CP14 register access.
460 *
461 * The registers can be access via the core or they can be memory-mapped.
462 */
463
464/*
465 * Read and write a CP14 register.
466 *
467 * The software debug event registers are not easy to program because there are
468 * up to 32 registers and the instructions have to assembler for each of the 32
469 * registers, you cannot program it. This means there is a switch table to do
470 * this.
471 */
472#define ARM_CP14_WRITE(_val, _CRn, _CRm, _op2) \
473  ARM_CP_WRITE(14, 0, _val, _CRn, _CRm, _op2)
474
475#define ARM_CP14_READ(_val, _CRn, _CRm, _op2)  \
476  ARM_CP_READ(14, 0, _val, _CRn, _CRm, _op2)
477
478/*
479 * Read and write a CP15 register.
480 *
481 * The Context ID register is a process level context and used to scope
482 * hardware break points.
483 */
484#define ARM_CP15_WRITE(_val, _op1, _CRn, _CRm, _op2) \
485  ARM_CP_WRITE(15, _op1, _val, _CRn, _CRm, _op2)
486
487#define ARM_CP15_READ(_val, _op1, _CRn, _CRm, _op2)  \
488  ARM_CP_READ(15, _op1, _val, _CRn, _CRm, _op2)
489
490/*
491 * Read and write a memory mapped debug register. The register number is a word
492 * offset from the base address.
493 */
494#define ARM_MMAP_ADDR(reg)       (((volatile uint32_t*) debug_registers) + (reg))
495#define ARM_MMAP_WRITE(reg, val) *ARM_MMAP_ADDR(reg) = (val); _ARM_Data_synchronization_barrier()
496#define ARM_MMAP_READ(reg)       *ARM_MMAP_ADDR(reg)
497
498static bool
499arm_debug_authentication(uint32_t dbgauthstatus)
500{
501  bool granted = (dbgauthstatus & (1 << 0)) != 0;
502  rtems_debugger_printf("rtems-db: arm debug: authentication: %s " \
503                        "(%s %s %s %s %s %s %s %s)\n",
504                        granted ? "granted" : "denied",
505                        (dbgauthstatus & (1 << 0)) == 0 ? "-" : "NSE",
506                        (dbgauthstatus & (1 << 1)) == 0 ? "-" : "NSI",
507                        (dbgauthstatus & (1 << 2)) == 0 ? "-" : "NSNE",
508                        (dbgauthstatus & (1 << 3)) == 0 ? "-" : "NSNI",
509                        (dbgauthstatus & (1 << 4)) == 0 ? "-" : "SE",
510                        (dbgauthstatus & (1 << 5)) == 0 ? "-" : "SI",
511                        (dbgauthstatus & (1 << 6)) == 0 ? "-" : "SNE",
512                        (dbgauthstatus & (1 << 7)) == 0 ? "-" : "SNI");
513  return granted;
514}
515
516static int
517arm_debug_cp14_enable(rtems_debugger_target* target)
518{
519  uint32_t val;
520  ARM_CP14_READ(val, 7, 14, 6);
521  if (!arm_debug_authentication(val))
522    return -1;
523  ARM_CP14_READ(val, 0, 1, 0);
524  if ((val & (1 << 15)) == 0) {
525    switch (debug_version) {
526    case 1:
527    case 2:
528      ARM_CP14_WRITE(val | (1 << 15), 0, 1, 0);
529      break;
530    case 3:
531    case 5:
532    default:
533      ARM_CP14_WRITE(val | (1 << 15), 0, 2, 2);
534      break;
535    case 4:
536      rtems_debugger_printf("rtems-db: arm debug: no cp14 access with version 4\n");
537      return -1;
538    }
539    ARM_CP14_READ(val, 0, 1, 0);
540    if ((val & (1 << 15)) == 0) {
541      rtems_debugger_printf("rtems-db: arm debug: cannot enter monitor mode\n");
542      errno = EIO;
543      return -1;
544    }
545  }
546  rtems_debugger_printf("rtems-db: arm debug: using cp14 register access\n");
547  return 0;
548}
549
550/*
551 * The write access to the software unlock register can cause an abort. Absorb
552 * it.
553 */
554static jmp_buf unlock_abort_jmpbuf;
555static size_t  arm_debug_retries;
556
557static void
558arm_debug_dump_rom_table(uint32_t* rom, size_t depth)
559{
560  uint32_t pidr[7];
561  uint32_t cidr[4];
562  uint32_t memtype;
563  uint32_t pidr4_4KB_count;
564  size_t   r;
565
566  static const char *table_class[16] = {
567    "reserved",
568    "ROM table",
569    "reserved", "reserved",
570    "reserved",
571    "reserved",
572    "reserved",
573    "reserved",
574    "reserved",
575    "CoreSight component",
576    "reserved",
577    "Peripheral Test Block",
578    "reserved",
579    "OptimoDE DESS",
580    "Generic IP component",
581    "PrimeCell or System component"
582  };
583
584  #define ROM_READ(b_, o_, r_) b_[((o_) / sizeof(uint32_t)) + (r_)]
585
586  if (depth > 16) {
587    rtems_debugger_printf("]] rom: too deep\n");
588    return;
589  }
590
591  for (r = 0; r < 4; ++r)
592    pidr[r] = ROM_READ(rom, 0xfe0, r) & 0xff;
593  for (r = 0; r < 3; ++r)
594    pidr[r + 4] = ROM_READ(rom, 0xfd0, r) & 0xff;
595  for (r = 0; r < 4; ++r)
596    cidr[r] = ROM_READ(rom, 0xff0, r) & 0xff;
597  memtype = ROM_READ(rom, 0xfcc, 0);
598
599  pidr4_4KB_count = pidr[4] & (((1 << (7 - 4)) - 1) >> 4);
600
601  rtems_debugger_printf("]] rom = %p\n", rom);
602  rtems_debugger_printf("   PIDR: %08x %08x %08x %08x %08x %08x %08x\n",
603                        pidr[0], pidr[1], pidr[2], pidr[3],
604                        pidr[4], pidr[5], pidr[6]);
605  rtems_debugger_printf("   CIDR: %08x %08x %08x %08x\n",
606                        cidr[0], cidr[1], cidr[2], cidr[3]);
607  rtems_debugger_printf("   4KB count: %u\n", pidr4_4KB_count);
608
609  if ((memtype & 0x01) != 0)
610    rtems_debugger_printf("   MEMTYPE sys memory present on bus\n");
611  else
612    rtems_debugger_printf("   MEMTYPE sys memory not present: dedicated debug bus\n");
613
614  /*
615   * Read ROM table entries until we get 0
616   */
617  for (r = 0; rom[r] != 0; ++r) {
618    uint32_t  romentry = rom[r];
619    uint32_t  c_pidr[7];
620    uint32_t  c_cidr[4];
621    uint32_t* c_base;
622    uint32_t  table_type;
623    size_t    i;
624
625    c_base = (uint32_t*) ((intptr_t) rom + (romentry & 0xFFFFF000));
626
627    /*
628     * Read the IDs.
629     */
630    for (i = 0; i < 4; ++i)
631      c_pidr[i] = ROM_READ(c_base, 0xfe0, i) & 0xff;
632    for (i = 0; i < 3; ++i)
633      c_pidr[i + 4] = ROM_READ(c_base, 0xfd0, i) & 0xff;
634    for (i = 0; i < 4; ++i)
635      c_cidr[i] = ROM_READ(c_base, 0xff0, i) & 0xff;
636
637    table_type = ROM_READ(c_base, 0xfcc, 0);
638
639    rtems_debugger_printf("   > Base: %p, start: 0x%" PRIx32 "\n",
640                          c_base,
641                          /* component may take multiple 4K pages */
642                          (uint32_t)((intptr_t) c_base - 0x1000 * (c_pidr[4] >> 4)));
643    rtems_debugger_printf("     Class is 0x%x, %s\n",
644                          (c_cidr[1] >> 4) & 0xf, table_class[(c_cidr[1] >> 4) & 0xf]);
645
646    if (((c_cidr[1] >> 4) & 0x0f) == 1) {
647      arm_debug_dump_rom_table(c_base, depth + 1);
648    }
649    else if (((c_cidr[1] >> 4) & 0x0f) == 9) {
650      const char* major = "reserved";
651      const char* subtype = "reserved";
652      unsigned    minor = (table_type >> 4) & 0x0f;
653
654      switch (table_type & 0x0f) {
655      case 0:
656        major = "Miscellaneous";
657        switch (minor) {
658        case 0:
659          subtype = "other";
660          break;
661        case 4:
662          subtype = "Validation component";
663          break;
664        }
665        break;
666      case 1:
667        major = "Trace Sink";
668        switch (minor) {
669        case 0:
670          subtype = "other";
671          break;
672        case 1:
673          subtype = "Port";
674          break;
675        case 2:
676          subtype = "Buffer";
677          break;
678        case 3:
679          subtype = "Router";
680          break;
681        }
682        break;
683      case 2:
684        major = "Trace Link";
685        switch (minor) {
686        case 0:
687          subtype = "other";
688          break;
689        case 1:
690          subtype = "Funnel, router";
691          break;
692        case 2:
693          subtype = "Filter";
694          break;
695        case 3:
696          subtype = "FIFO, buffer";
697          break;
698        }
699        break;
700      case 3:
701        major = "Trace Source";
702        switch (minor) {
703        case 0:
704          subtype = "other";
705          break;
706        case 1:
707          subtype = "Processor";
708          break;
709        case 2:
710          subtype = "DSP";
711          break;
712        case 3:
713          subtype = "Engine/Coprocessor";
714          break;
715        case 4:
716          subtype = "Bus";
717          break;
718        case 6:
719          subtype = "Software";
720          break;
721        }
722        break;
723      case 4:
724        major = "Debug Control";
725        switch (minor) {
726        case 0:
727          subtype = "other";
728          break;
729        case 1:
730          subtype = "Trigger Matrix";
731          break;
732        case 2:
733          subtype = "Debug Auth";
734          break;
735        case 3:
736          subtype = "Power Requestor";
737          break;
738        }
739        break;
740      case 5:
741        major = "Debug Logic";
742        switch (minor) {
743        case 0:
744          subtype = "other";
745          break;
746        case 1:
747          subtype = "Processor";
748          break;
749        case 2:
750          subtype = "DSP";
751          break;
752        case 3:
753          subtype = "Engine/Coprocessor";
754          break;
755        case 4:
756          subtype = "Bus";
757          break;
758        case 5:
759          subtype = "Memory";
760        }
761        break;
762      case 6:
763        major = "Perfomance Monitor";
764        switch (minor) {
765        case 0:
766          subtype = "other";
767          break;
768        case 1:
769          subtype = "Processor";
770          break;
771        case 2:
772          subtype = "DSP";
773          break;
774        case 3:
775          subtype = "Engine/Coprocessor";
776          break;
777        case 4:
778          subtype = "Bus";
779          break;
780        case 5:
781          subtype = "Memory";
782          break;
783        }
784        break;
785      }
786
787      rtems_debugger_printf("     Type: 0x%02" PRIx32 ", %s, %s\n",
788                            table_type & 0xff, major, subtype);
789      rtems_debugger_printf("     PID[4..0]: %02x %02x %02x %02x %02x\n",
790                            c_pidr[4], c_pidr[3], c_pidr[2], c_pidr[1], c_pidr[0]);
791
792      if (((c_cidr[1] >> 4) & 0x0f) == 1) {
793        arm_debug_dump_rom_table(c_base, depth + 1);
794      }
795    }
796  }
797}
798
799static int
800arm_debug_rom_discover(uint32_t* rom, uint32_t comp, uint32_t** addr, int* index)
801{
802  size_t r = 0;
803  *addr = 0;
804  while ((rom[r] & 1) != 0) {
805    uint32_t* c_base = (uint32_t*) ((intptr_t) rom + (rom[r] & 0xfffff000));
806    uint32_t  c_cid1 = c_base[0xff4 / sizeof(uint32_t)];
807    uint32_t  type;
808    if (((c_cid1 >> 4) & 0x0f) == 1) {
809      if (arm_debug_rom_discover(c_base, comp, addr, index))
810        return true;
811    }
812    type = c_base[0xfcc / sizeof(uint32_t)] & 0xff;
813    if (comp == type) {
814      if (*index > 0)
815        --(*index);
816      else {
817        *addr = c_base;
818        return true;
819      }
820    }
821    ++r;
822  }
823  return false;
824}
825
826static int
827arm_debug_mmap_enable(rtems_debugger_target* target, uint32_t dbgdidr)
828{
829  uint32_t val;
830  int      rc = -1;
831
832#if ARM_CP15
833  void* abort_handler;
834#endif
835
836  /*
837   * File scope as setjmp/longjmp effect the local stack variables.
838   */
839  arm_debug_retries = 5;
840
841  /*
842   * The DBGDSAR (DSAR) is a signed offset from DBGDRAR. Both need to
843   * be valid for the debug register address to be valid. Read the
844   * DBGRAR first.
845   */
846  ARM_CP14_READ(val, 1, 0, 0);
847  if ((val & 3) == 3) {
848    uint32_t* rom = (uint32_t*) (val & 0xfffff000);
849    uint32_t* comp_base = NULL;
850    int       core = (int) _SMP_Get_current_processor();
851
852    if (ARM_DUMP_ROM_TABLES)
853      arm_debug_dump_rom_table(rom, 0);
854
855    debug_registers = NULL;
856
857    if (arm_debug_rom_discover(rom, 0x15, &comp_base, &core)) {
858      debug_registers = comp_base;
859      rtems_debugger_printf("rtems-db: ram debug: ROM Base: %p\n", comp_base);
860    } else {
861      ARM_CP14_READ(val, 2, 0, 0);
862      if ((val & 3) == 3 ) {
863        debug_registers = (void*) ((intptr_t) rom + (val & ~3));
864      }
865    }
866  }
867
868  if (debug_registers == NULL) {
869    debug_registers = rtems_debugger_arm_debug_registers();
870    if (debug_registers == NULL) {
871      rtems_debugger_printf("rtems-db: arm debug: no valid register map\n");
872      return -1;
873    }
874    rtems_debugger_printf("rtems-db: arm debug: BSP Base: %p\n", debug_registers);
875  }
876
877  /*
878   * Make sure the memory mapped registers return the same ID.
879   */
880  if (ARM_MMAP_READ(0) != dbgdidr) {
881    debug_registers = NULL;
882    rtems_debugger_printf("rtems-db: arm debug: debug reg map not verified: " \
883                          "0x%08x\n", ARM_MMAP_READ(0));
884    return -1;
885  }
886
887  if (!arm_debug_authentication(ARM_MMAP_READ(1006)))
888    return -1;
889
890#if ARM_CP15
891  abort_handler =
892    arm_cp15_set_exception_handler(ARM_EXCEPTION_DATA_ABORT,
893                                   arm_debug_unlock_abort);
894#endif
895
896  while (arm_debug_retries-- > 0) {
897    if (setjmp(unlock_abort_jmpbuf) == 0) {
898      /*
899       * If there is a software lock and it is locked unlock it.
900       *
901       * On the TI am335x this can cause a data abort which we catch and retry
902       * which seems to make the debug hardware work.
903       */
904      if (ARM_MMAP_READ(1005) == 3) {
905        ARM_MMAP_WRITE(1004, 0xC5ACCE55);
906      }
907      /*
908       * Are we already in debug mode?
909       */
910      val = ARM_MMAP_READ(34);
911      if ((val & (1 << 15)) == 0) {
912        rtems_debugger_printf("rtems-db: arm debug: enable debug mode\n");
913        val = ARM_MMAP_READ(34);
914        ARM_MMAP_WRITE(34, ARM_MMAP_READ(34) | (1 << 15));
915        arm_debug_retries = 0;
916      }
917    }
918  }
919
920#if ARM_CP15
921  arm_cp15_set_exception_handler(ARM_EXCEPTION_DATA_ABORT, abort_handler);
922#endif
923
924  if (arm_debug_retries > 0) {
925    rtems_debugger_printf("rtems-db: arm debug: using debug register access\n");
926    rc = 0;
927  }
928  else {
929    rtems_debugger_printf("rtems-db: arm debug: cannot enter debug mode\n");
930  }
931
932  val = ARM_MMAP_READ(1006);
933
934  return rc;
935}
936
937static int
938arm_debug_probe(rtems_debugger_target* target)
939{
940  #define ID_VALUE(_i, _h, _l) ((_i >> _l) & ((1 << ((_h - _l) + 1)) -1))
941  uint32_t          val;
942  const char*       vl = "[Invalid version]";
943  const char* const labels[] = {
944    "ARMv6 [v6]",
945    "ARMv6 [v6.1]",
946    "ARMv7 [v7, all CP14 registers]",
947    "ARMv7 [v7, baseline CP14 registers]",
948    "ARMv7 [v7.1]"
949  };
950  int rc = -1;
951
952#if ARM_CP15
953  ARM_CP15_READ(val, 0, 0, 0, 0);
954  rtems_debugger_printf("rtems-db: arm core: Architecture: %d Variant: %d " \
955                        "Implementor: %d Part Number: %d Revision: %d\n",
956                        (val >> 16) & ((1 << (19 - 16 + 1)) - 1),
957                        (val >> 20) & ((1 << (23 - 20 + 1)) - 1),
958                        (val >> 24) & ((1 << (31 - 24 + 1)) - 1),
959                        (val >>  4) & ((1 << (15 -  4 + 1)) - 1),
960                        (val >>  0) & ((1 << ( 3 -  0 + 1)) - 1));
961#endif
962
963  ARM_CP14_READ(val, 0, 0, 0);
964
965  debug_version = ID_VALUE(val, 19, 16);
966  if (debug_version < 1 || debug_version > 5) {
967    rtems_debugger_printf("rtems-db: arm debug: (v%d.%d) not supported\n",
968                          debug_version, debug_revision);
969    errno = EIO;
970    return -1;
971  }
972
973  vl = labels[debug_version - 1];
974  debug_revision = ID_VALUE(val, 3, 0);
975  hw_breakpoints = ID_VALUE(val, 27, 24);
976  hw_watchpoints = ID_VALUE(val, 31, 28);
977
978  rtems_debugger_printf("rtems-db: arm debug: (v%d.%d) %s " \
979                        "breakpoints:%d watchpoints:%d\n",
980                        debug_version, debug_revision, vl,
981                        hw_breakpoints, hw_watchpoints);
982
983  if (!rtems_debugger_arm_debug_configure())
984    return -1;
985
986  switch (debug_version) {
987    case 1:
988    case 2:
989    case 3:
990    case 5:
991    default:
992      rc = arm_debug_mmap_enable(target, val);
993      if (rc != 0)
994        rc =  arm_debug_cp14_enable(target);
995      break;
996    case 4:
997      rc = arm_debug_mmap_enable(target, val);
998      break;
999  }
1000
1001  return rc;
1002}
1003
1004static inline void
1005arm_debug_break_setup(arm_debug_hwbreak* bp,
1006                      uint32_t           address,
1007                      uint32_t           type,
1008                      uint32_t           byte_address_select,
1009                      uint32_t           privilege)
1010{
1011  bp->control = (((type & 0xf) << 20) |
1012                 ((byte_address_select & 0xf) << 5) |
1013                 ((privilege & 0x3) << 1) | 1);
1014  bp->value = (intptr_t) address;
1015}
1016
1017static void
1018arm_debug_break_write_control(int bp, uint32_t control)
1019{
1020  if (bp < 15) {
1021    if (debug_registers != NULL) {
1022      ARM_MMAP_WRITE(80 + bp, control);
1023    }
1024    else {
1025      switch (bp) {
1026      case 0:
1027        ARM_CP14_WRITE(control, 0, 0, 5);
1028        break;
1029      case 1:
1030        ARM_CP14_WRITE(control, 0, 1, 5);
1031        break;
1032      case 2:
1033        ARM_CP14_WRITE(control, 0, 2, 5);
1034        break;
1035      case 3:
1036        ARM_CP14_WRITE(control, 0, 3, 5);
1037        break;
1038      case 4:
1039        ARM_CP14_WRITE(control, 0, 4, 5);
1040        break;
1041      case 5:
1042        ARM_CP14_WRITE(control, 0, 5, 5);
1043        break;
1044      case 6:
1045        ARM_CP14_WRITE(control, 0, 6, 5);
1046        break;
1047      case 7:
1048        ARM_CP14_WRITE(control, 0, 7, 5);
1049        break;
1050      case 8:
1051        ARM_CP14_WRITE(control, 0, 8, 5);
1052        break;
1053      case 9:
1054        ARM_CP14_WRITE(control, 0, 9, 5);
1055        break;
1056      case 10:
1057        ARM_CP14_WRITE(control, 0, 10, 5);
1058        break;
1059      case 11:
1060        ARM_CP14_WRITE(control, 0, 11, 5);
1061        break;
1062      case 12:
1063        ARM_CP14_WRITE(control, 0, 12, 5);
1064        break;
1065      case 13:
1066        ARM_CP14_WRITE(control, 0, 13, 5);
1067        break;
1068      case 14:
1069        ARM_CP14_WRITE(control, 0, 14, 5);
1070        break;
1071      case 15:
1072        ARM_CP14_WRITE(control, 0, 15, 5);
1073        break;
1074      }
1075    }
1076  }
1077}
1078
1079static void
1080arm_debug_break_write_value(int bp, uint32_t value)
1081{
1082  if (bp < 15) {
1083    if (debug_registers != NULL) {
1084      ARM_MMAP_WRITE(64 + bp, value);
1085    }
1086    else {
1087      switch (bp) {
1088      case 0:
1089        ARM_CP14_WRITE(value, 0, 0, 4);
1090        break;
1091      case 1:
1092        ARM_CP14_WRITE(value, 0, 1, 4);
1093        break;
1094      case 2:
1095        ARM_CP14_WRITE(value, 0, 2, 4);
1096        break;
1097      case 3:
1098        ARM_CP14_WRITE(value, 0, 3, 4);
1099        break;
1100      case 4:
1101        ARM_CP14_WRITE(value, 0, 4, 4);
1102        break;
1103      case 5:
1104        ARM_CP14_WRITE(value, 0, 5, 4);
1105        break;
1106      case 6:
1107        ARM_CP14_WRITE(value, 0, 6, 4);
1108        break;
1109      case 7:
1110        ARM_CP14_WRITE(value, 0, 7, 4);
1111        break;
1112      case 8:
1113        ARM_CP14_WRITE(value, 0, 8, 4);
1114        break;
1115      case 9:
1116        ARM_CP14_WRITE(value, 0, 9, 4);
1117        break;
1118      case 10:
1119        ARM_CP14_WRITE(value, 0, 10, 4);
1120        break;
1121      case 11:
1122        ARM_CP14_WRITE(value, 0, 11, 4);
1123        break;
1124      case 12:
1125        ARM_CP14_WRITE(value, 0, 12, 4);
1126        break;
1127      case 13:
1128        ARM_CP14_WRITE(value, 0, 13, 4);
1129        break;
1130      case 14:
1131        ARM_CP14_WRITE(value, 0, 14, 4);
1132        break;
1133      case 15:
1134        ARM_CP14_WRITE(value, 0, 15, 4);
1135        break;
1136      }
1137    }
1138  }
1139}
1140
1141static uint32_t
1142arm_debug_dbgdscr_read(void)
1143{
1144  uint32_t val;
1145  if (debug_registers != NULL) {
1146    val = ARM_MMAP_READ(34);
1147  }
1148  else {
1149    ARM_CP14_READ(val, 0, 1, 0);
1150  }
1151  return val;
1152}
1153
1154static void
1155arm_debug_dbgdscr_write(uint32_t val)
1156{
1157  if (debug_registers != NULL) {
1158    ARM_MMAP_WRITE(34, val);
1159  }
1160  else {
1161    ARM_CP14_WRITE(val, 0, 1, 0);
1162  }
1163}
1164
1165static uint32_t
1166arm_debug_method_of_entry(void)
1167{
1168  return (arm_debug_dbgdscr_read() >> 2) & 0xf;
1169}
1170
1171static void
1172arm_debug_disable_interrupts(void)
1173{
1174  debug_disable_ints = true;
1175}
1176
1177static void
1178arm_debug_commit_interrupt_disable(void)
1179{
1180  if (debug_disable_ints) {
1181    arm_debug_dbgdscr_write(arm_debug_dbgdscr_read() | (1 << 11));
1182    debug_disable_ints = false;
1183  }
1184}
1185
1186static void
1187arm_debug_enable_interrupts(void)
1188{
1189  arm_debug_dbgdscr_write(arm_debug_dbgdscr_read() & ~(1 << 11));
1190}
1191
1192static void
1193arm_debug_break_clear(void)
1194{
1195  rtems_interrupt_lock_context lock_context;
1196  arm_debug_hwbreak*           bp = &hw_breaks[0];
1197  int                          i;
1198  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
1199  for (i = 0; i < hw_breakpoints; ++i, ++bp) {
1200    bp->enabled = false;
1201    bp->loaded = false;
1202  }
1203  rtems_interrupt_lock_release(&target_lock, &lock_context);
1204}
1205
1206static inline void
1207arm_debug_set_context_id(const uint32_t id)
1208{
1209#if ARM_CP15
1210  ARM_CP15_WRITE(id, 0, 13, 0, 1);
1211#endif
1212}
1213
1214/*
1215 * You can only load the hardware breaks points when in the SVC mode or the
1216 * single step inverted break point will trigger.
1217 */
1218static void
1219arm_debug_break_load(void)
1220{
1221  rtems_interrupt_lock_context lock_context;
1222  arm_debug_hwbreak*           bp = &hw_breaks[0];
1223  int                          i;
1224  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
1225  if (bp->enabled && !bp->loaded) {
1226    arm_debug_set_context_id(0xdead1111);
1227    arm_debug_break_write_value(0, bp->value);
1228    arm_debug_break_write_control(0, bp->control);
1229  }
1230  ++bp;
1231  for (i = 1; i < hw_breakpoints; ++i, ++bp) {
1232    if (bp->enabled && !bp->loaded) {
1233      bp->loaded = true;
1234      arm_debug_break_write_value(i, bp->value);
1235      arm_debug_break_write_control(i, bp->control);
1236    }
1237  }
1238  rtems_interrupt_lock_release(&target_lock, &lock_context);
1239}
1240
1241static void
1242arm_debug_break_unload(void)
1243{
1244  rtems_interrupt_lock_context lock_context;
1245  arm_debug_hwbreak*           bp = &hw_breaks[0];
1246  int                          i;
1247  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
1248  arm_debug_set_context_id(0);
1249  for (i = 0; i < hw_breakpoints; ++i, ++bp) {
1250    bp->loaded = false;
1251    arm_debug_break_write_control(i, 0);
1252  }
1253  rtems_interrupt_lock_release(&target_lock, &lock_context);
1254}
1255
1256static void
1257arm_debug_break_dump(void)
1258{
1259#if TARGET_DEBUG
1260  arm_debug_hwbreak* bp = &hw_breaks[0];
1261  int                i;
1262  for (i = 0; i < hw_breakpoints; ++i, ++bp) {
1263    if (bp->enabled) {
1264      target_printk("[} bp: %d: control: %08x addr: %08x\n",
1265                    i, bp->control, bp->value);
1266    }
1267  }
1268#endif
1269}
1270
1271#if NOT_USED_BUT_KEEPING
1272static size_t
1273arm_debug_break_length(void* pc)
1274{
1275  arm_debug_hwbreak* bp = &hw_breaks[0];
1276  int                i;
1277
1278  for (i = 0; i < hw_breakpoints; ++i, ++bp) {
1279    if (bp->enabled && bp->address == pc) {
1280      return bp->length;
1281    }
1282  }
1283  return sizeof(DB_UINT);
1284}
1285#endif
1286
1287int
1288rtems_debugger_target_configure(rtems_debugger_target* target)
1289{
1290  target->capabilities = (RTEMS_DEBUGGER_TARGET_CAP_SWBREAK);
1291  target->reg_num = RTEMS_DEBUGGER_NUMREGS;
1292  target->reg_offset = arm_reg_offsets;
1293  target->breakpoint = &breakpoint[0];
1294  target->breakpoint_size = sizeof(breakpoint);
1295  return arm_debug_probe(target);
1296}
1297
1298static void
1299target_print_frame(CPU_Exception_frame* frame)
1300{
1301  EXC_FRAME_PRINT(target_printk, "[} ", frame);
1302}
1303
1304static const size_t
1305target_exc_offset(CPU_Exception_frame* frame)
1306{
1307  size_t thumb = (FRAME_SR(frame) & (1 << 5)) == 0 ? 0 : 1;
1308  return exc_offsets[thumb][frame->vector];
1309}
1310
1311static void
1312target_exception(CPU_Exception_frame* frame)
1313{
1314#if TARGET_DEBUG
1315#if ARM_CP15
1316  const uint32_t ifsr = arm_cp15_get_instruction_fault_status();
1317#else
1318  const uint32_t ifsr = 0;
1319#endif
1320  const uint32_t mvector = frame->vector;
1321  const uint32_t dbgdscr = arm_debug_dbgdscr_read();
1322#endif
1323
1324  const uint32_t moe = arm_debug_method_of_entry();
1325  const size_t exc_offset = target_exc_offset(frame);
1326
1327  switch (moe){
1328  case ARM_HW_DSCR_MOE_BREAKPOINT_EVENT:
1329  case ARM_HW_DSCR_MOE_BREAKPOINT_INSTR:
1330  case ARM_HW_DSCR_MOE_ASYNC_WATCHPOINT:
1331  case ARM_HW_DSCR_MOE_SYNC_WATCHPOINT:
1332    frame->vector = 2;
1333    break;
1334  case ARM_HW_DSCR_MOE_HALT_REQUEST:
1335  case ARM_HW_DSCR_MOE_EXTERNAL:
1336  case ARM_HW_DSCR_MOE_VECTOR_CATCH_EVENT:
1337  case ARM_HW_DSCR_MOE_OS_UNLOCK_EVENT:
1338  default:
1339    break;
1340  }
1341
1342  target_printk("[} > frame = %08" PRIx32 \
1343                " sig=%d vector=%u (%u) dbgdscr=%08" PRIx32 " moe=%s" \
1344                " ifsr=%08" PRIx32 " pra=%08x\n",
1345                (uint32_t) frame,
1346                rtems_debugger_target_exception_to_signal(frame),
1347                frame->vector, mvector, dbgdscr, arm_moe_label(moe),
1348                ifsr, (intptr_t) frame->register_pc);
1349
1350  frame->register_pc = (void*) ((intptr_t) frame->register_pc - exc_offset);
1351
1352  target_print_frame(frame);
1353
1354  arm_debug_enable_interrupts();
1355  arm_debug_break_clear();
1356
1357  if (!debug_session_active)
1358    _ARM_Exception_default(frame);
1359
1360  switch (rtems_debugger_target_exception(frame)) {
1361  case rtems_debugger_target_exc_consumed:
1362  default:
1363    break;
1364  case rtems_debugger_target_exc_step:
1365    break;
1366  case rtems_debugger_target_exc_cascade:
1367    target_printk("rtems-db: unhandled exception: cascading\n");
1368    _ARM_Exception_default(frame);
1369    break;
1370  }
1371
1372  target_printk("[} < resuming frame = %08" PRIx32 \
1373                " PC = %08" PRIxPTR " CPSR = %08" PRIx32 "\n",
1374                (uint32_t) frame, (intptr_t) frame->register_pc, FRAME_SR(frame));
1375  target_print_frame(frame);
1376  arm_debug_break_dump();
1377}
1378
1379/**
1380 * Exception stack frame size.
1381 *
1382 * The size is the exception stack frame plus the CPSR from the exception. We
1383 * save the CPSR and restore it when we exit the exception.
1384 */
1385#define EXCEPTION_FRAME_SIZE (sizeof(CPU_Exception_frame) + sizeof(uint32_t))
1386
1387/**
1388 * Exception stack frame FPU offsets and sizes.
1389 */
1390#define EXCEPTION_FRAME_FPU_SIZE   ARM_VFP_CONTEXT_SIZE
1391#define EXCEPTION_FRAME_FPU_OFFSET ARM_EXCEPTION_FRAME_VFP_CONTEXT_OFFSET
1392
1393/**
1394 * Exception entry.
1395 *
1396 * We have switched from svc (or even user) to an exception mode. Save the
1397 * current CPSR and create an exception frame on the exception's stack and then
1398 * copy it to the thread's stack. Switch back to the thread's context and mode
1399 * to handle the exception to avoid any stack checks thinking the stack is
1400 * blown. This lets the thread be suspended.
1401 *
1402 * The entry is in two parts, the exception mode entry and the trhead mode
1403 * entry. This lets us disable any hardware breakpoint support. We need to do
1404 * this because it is enabled in PL0 mode.
1405 *
1406 * Note, the code currently assumes cp15 has been set up to match the
1407 *       instruction set being used.
1408 */
1409#define EXCEPTION_ENTRY_EXC()                                           \
1410  __asm__ volatile(                                                     \
1411    ASM_ARM_MODE                                                        \
1412    "sub  sp, %[frame_size]\n"           /* alloc the frame and CPSR */ \
1413    "stm  sp, {r0-r12}\n"                            /* store r0-r12 */ \
1414    "sub  sp, #4\n"                                                     \
1415    "str  lr, [sp]\n"                           /* save the link reg */ \
1416    ASM_THUMB_MODE                                                      \
1417    : ARM_SWITCH_REG_ASM                                                \
1418    : [frame_size] "i" (EXCEPTION_FRAME_SIZE)                           \
1419    : "memory")
1420
1421/*
1422 * FPU entry. Conditionally D16 or D32 support.
1423 */
1424#ifdef ARM_MULTILIB_VFP
1425#ifdef ARM_MULTILIB_VFP_D32
1426#define FPU_ENTRY_VFP_D32                                               \
1427    "vstmia  r5!, {d16-d31}\n"
1428#else  /* ARM_MULTILIB_VFP_D32 */
1429#define FPU_ENTRY_VFP_D32                                               \
1430    "mov    r3, #0\n"                                                   \
1431    "mov    r4, #0\n"                                                   \
1432    "adds   r6, r5, #128\n"                                             \
1433    "3:\n"                                                              \
1434    "stmia  r5!, {r3-r4}\n"                                             \
1435    "cmp    r5, r6\n"                                                   \
1436    "bne    3b\n"
1437#endif /* ARM_MULTILIB_VFP_D32 */
1438#define EXCEPTION_ENTRY_FPU(frame_fpu_size)                             \
1439    "sub    sp, %[frame_fpu_size]\n" /* size includes alignment size */ \
1440    "add    r5, sp, #4\n"                        /* up to align down */ \
1441    "bic    r5, r5, #7\n"                     /* align the FPU frame */ \
1442    "str    r5, [r2]\n"               /* store the FPU frame pointer */ \
1443    "vmrs   r3, FPEXC\n"                                                \
1444    "vmrs   r4, FPSCR\n"                                                \
1445    "stmia  r5!, {r3-r4}\n"                                             \
1446    "vstmia r5!, {d0-d15}\n"                                            \
1447    FPU_ENTRY_VFP_D32
1448#else  /* ARM_MULTILIB_VFP */
1449#define EXCEPTION_ENTRY_FPU(frame_fpu_size)
1450#endif /* ARM_MULTILIB_VFP */
1451
1452#define ARM_CLEAR_THUMB_MODE "bic  r1, r1, %[psr_t]\n" /* clear thumb */
1453
1454#define EXCEPTION_ENTRY_THREAD(_frame)                                  \
1455  __asm__ volatile(                                                     \
1456    ASM_ARM_MODE                                                        \
1457    "ldr  lr, [sp]\n"                        /* recover the link reg */ \
1458    "add  sp, #4\n"                                                     \
1459    "add  r0, sp, %[r0_r12_size]\n"       /* get the sp in the frame */ \
1460    "mrs  r1, spsr\n"                            /* get the saved sr */ \
1461    "mov  r6, r1\n"                            /* stash it for later */ \
1462    ARM_CLEAR_THUMB_MODE                         /* clear thumb mode */ \
1463    "orr  r1, r1, %[psr_i]\n"                           /* mask irqs */ \
1464    "mrs  r2, cpsr\n"                          /* get the current sr */ \
1465    "str  r2, [sp, %[frame_cpsr]]\n"          /* save for exc return */ \
1466    "msr  cpsr, r1\n"                         /* switch to user mode */ \
1467    "mov  r3, sp\n"                         /* get the stack pointer */ \
1468    "mov  r4, lr\n"                              /* get the link reg */ \
1469    "msr  cpsr, r2\n"                            /* back to exc mode */ \
1470    "mov  r5, lr\n"                                   /* get the PRA */ \
1471    "stm  r0, {r3-r6}\n"                      /* save into the frame */ \
1472    "sub  r4, r3, %[frame_size]\n"            /* destination address */ \
1473    "mov  r6, r4\n"                                /* save the frame */ \
1474    "sub  r4, #1\n"                          /* one before the start */ \
1475    "add  r3, #1\n"                              /* one past the end */ \
1476    "sub  r5, sp, #1\n"                            /* source address */ \
1477    "1:\n"                                                              \
1478    "ldrb r0, [r5, #1]!\n"                             /* get a byte */ \
1479    "strb r0, [r4, #1]!\n"                           /* put the byte */ \
1480    "cmp  r3, r4\n"                                      /* the end? */ \
1481    "bne  1b\n"                                                         \
1482    "add  sp, %[frame_size]\n"            /* free the frame and CPSR */ \
1483    "mrs  r1, spsr\n"                   /* get the thread's saved sr */ \
1484    "orr  r2, r1, %[psr_i]\n"                           /* mask irqs */ \
1485    "msr  cpsr, r2\n"         /* switch back to the thread's context */ \
1486    "sub  sp, %[frame_size]\n"          /* alloc in the thread stack */ \
1487    "mov  %[o_frame], sp\n"                        /* save the frame */ \
1488    "add  r2, sp, %[o_frame_fpu]\n"            /* get the FPU offset */ \
1489    "mov  r3, #0\n"                                                     \
1490    "str  r3, [r2]\n"                 /* clear the FPU frame pointer */ \
1491    EXCEPTION_ENTRY_FPU(frame_fpu_size)                                 \
1492    "bic  r1, r1, %[psr_i]\n"        /* clear irq mask, debug checks */ \
1493    "msr  cpsr, r1\n"       /* restore the state with irq mask clear */ \
1494    ASM_THUMB_MODE                                                      \
1495    : ARM_SWITCH_REG_ASM_L                                              \
1496      [o_frame] "=r" (_frame)                                           \
1497    : [psr_t] "i" (ARM_PSR_T),                                          \
1498      [psr_i] "i" (ARM_PSR_I),                                          \
1499      [r0_r12_size] "i" (13 * sizeof(uint32_t)),                        \
1500      [frame_cpsr] "i" (EXCEPTION_FRAME_SIZE - sizeof(uint32_t)),       \
1501      [frame_size] "i" (EXCEPTION_FRAME_SIZE),                          \
1502      [o_frame_fpu] "i" (EXCEPTION_FRAME_FPU_OFFSET),                   \
1503      [frame_fpu_size] "i" (EXCEPTION_FRAME_FPU_SIZE + 4)               \
1504    : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory")
1505
1506/*
1507 * FPU exit. Conditionally D16 or D32 support.
1508 */
1509#ifdef ARM_MULTILIB_VFP
1510#ifdef ARM_MULTILIB_VFP_D32
1511#define FPU_EXIT_VFP_D32                                                \
1512    "vldmia r0, {d16-d31}\n"
1513#else  /* ARM_MULTILIB_VFP_D32 */
1514#define FPU_EXIT_VFP_D32
1515#endif /* ARM_MULTILIB_VFP_D32 */
1516#define EXCEPTION_EXIT_FPU(frame_fpu_size)                              \
1517    "ldmia  r0!, {r1-r2}\n"                                             \
1518    "vldmia r0!, {d0-d15}\n"                                            \
1519    FPU_EXIT_VFP_D32                                                    \
1520    "vmsr   FPEXC, r1\n"                                                \
1521    "vmsr   FPSCR, r2\n"                                                \
1522    "add    sp, %[frame_fpu_size]\n" /* size includes alignment size */
1523#else  /* ARM_MULTILIB_VFP */
1524#define EXCEPTION_EXIT_FPU(frame_fpu_size)
1525#endif /* ARM_MULTILIB_VFP */
1526
1527/**
1528 * Exception exit.
1529 *
1530 * The thread is to be resumed so we are still in the thread's mode. Copy the
1531 * exception frame from the thread's stack back to the exception's stack and
1532 * restore the thread's context before returning from the exception to the
1533 * thread.
1534 *
1535 * Note, the code currently assumes cp15 has been set up to match the
1536 *       instruction set being used.
1537 */
1538#define EXCEPTION_EXIT_THREAD(_frame)                                   \
1539  __asm__ volatile(                                                     \
1540    ASM_ARM_MODE                                                        \
1541    "mov  r0, %[i_frame]\n"                         /* get the frame */ \
1542    "ldr  r0, [r0, %[frame_fpu]]\n"     /* recover FPU frame pointer */ \
1543    EXCEPTION_EXIT_FPU(frame_fpu_size)                                  \
1544    "ldr  r2, [sp, %[frame_cpsr]]\n" /* recover exc CPSR from thread */ \
1545    "mov  r0, sp\n"                  /* get the thread frame pointer */ \
1546    "msr  cpsr, r2\n"            /* switch back to the exc's context */ \
1547    "add  r3, sp, #1\n"                               /* get the end */ \
1548    "sub  sp, %[frame_size]\n"                    /* alloc the frame */ \
1549    "sub  r4, sp, #1\n"                       /* destination address */ \
1550    "sub  r5, r0, #1\n"                            /* source address */ \
1551    "1:\n"                                                              \
1552    "ldrb r1, [r5, #1]!\n"                             /* get a byte */ \
1553    "strb r1, [r4, #1]!\n"                           /* put the byte */ \
1554    "cmp  r3, r4\n"                                      /* the end? */ \
1555    "bne  1b\n"                                                         \
1556    "mov  r0, %[i_frame]\n"                         /* get the frame */ \
1557    "add  r1, r0, %[r0_r12_size]\n"       /* get the sp in the frame */ \
1558    "ldm  r1, {r3-r6}\n"                 /* recover sp, lr, pc, cpsr */ \
1559    "orr  r1, r6, %[psr_i]\n"  /* get the thread's psr and mask irqs */ \
1560    "msr  cpsr, r1\n"                         /* switch to user mode */ \
1561    "mov  sp, r3\n"                         /* set the stack pointer */ \
1562    "mov  lr, r4\n"                              /* set the link reg */ \
1563    "msr  cpsr, r2\n"            /* switch back to the exc's context */ \
1564    "msr  spsr, r6\n"                       /* set the thread's CPSR */ \
1565    "sub  sp, #4\n"                                                     \
1566    "mov  lr, r5\n"                                    /* get the PC */ \
1567    "str  lr, [sp]\n"                           /* save the link reg */ \
1568    ASM_THUMB_MODE                                                      \
1569    : ARM_SWITCH_REG_ASM                                                \
1570    : [psr_i] "i" (ARM_PSR_I),                                          \
1571      [r0_r12_size] "i" (13 * sizeof(uint32_t)),                        \
1572      [frame_cpsr] "i" (EXCEPTION_FRAME_SIZE - sizeof(uint32_t)),       \
1573      [frame_size] "i" (EXCEPTION_FRAME_SIZE),                          \
1574      [frame_fpu] "i" (EXCEPTION_FRAME_FPU_OFFSET),                     \
1575      [frame_fpu_size] "i" (EXCEPTION_FRAME_FPU_SIZE + 4),              \
1576      [i_frame] "r" (_frame)                                            \
1577    : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory")
1578
1579#define EXCEPTION_EXIT_EXC()                                            \
1580  __asm__ volatile(                                                     \
1581    ASM_ARM_MODE                                                        \
1582    "ldr  lr, [sp]\n"                        /* recover the link reg */ \
1583    "add  sp, #4\n"                                                     \
1584    "ldm  sp, {r0-r12}\n"            /* restore the thread's context */ \
1585    "add  sp, %[frame_size]\n"                     /* free the frame */ \
1586    "subs pc, lr, #0\n"                       /* return from the exc */ \
1587    :                                                                   \
1588    : [frame_size] "i" (EXCEPTION_FRAME_SIZE)                           \
1589    : "memory")
1590
1591/*
1592 * This is used to catch faulting accesses.
1593 */
1594#if ARM_CP15
1595static void __attribute__((naked))
1596arm_debug_unlock_abort(void)
1597{
1598  CPU_Exception_frame* frame;
1599  ARM_SWITCH_REG;
1600  EXCEPTION_ENTRY_EXC();
1601  EXCEPTION_ENTRY_THREAD(frame);
1602  longjmp(unlock_abort_jmpbuf, -1);
1603}
1604#endif
1605
1606static void __attribute__((naked))
1607target_exception_undefined_instruction(void)
1608{
1609  CPU_Exception_frame* frame;
1610  ARM_SWITCH_REG;
1611  EXCEPTION_ENTRY_EXC();
1612  arm_debug_break_unload();
1613  arm_debug_enable_interrupts();
1614  EXCEPTION_ENTRY_THREAD(frame);
1615  frame->vector = 1;
1616  target_exception(frame);
1617  EXCEPTION_EXIT_THREAD(frame);
1618  arm_debug_commit_interrupt_disable();
1619  arm_debug_break_load();
1620  EXCEPTION_EXIT_EXC();
1621}
1622
1623static void __attribute__((naked))
1624target_exception_supervisor_call(void)
1625{
1626  CPU_Exception_frame* frame;
1627  ARM_SWITCH_REG;
1628  /*
1629   * The PC offset needs to be reviewed so we move past a svc
1630   * instruction. This can then be used as a user breakpoint. The issue is
1631   * this exception is used by the BKPT instruction in the prefetch abort
1632   * handler to signal a TRAP.
1633   */
1634  EXCEPTION_ENTRY_EXC();
1635  arm_debug_break_unload();
1636  arm_debug_enable_interrupts();
1637  EXCEPTION_ENTRY_THREAD(frame);
1638  frame->vector = 2;
1639  target_exception(frame);
1640  EXCEPTION_EXIT_THREAD(frame);
1641  arm_debug_commit_interrupt_disable();
1642  arm_debug_break_load();
1643  EXCEPTION_EXIT_EXC();
1644}
1645
1646static void __attribute__((naked))
1647target_exception_prefetch_abort(void)
1648{
1649  CPU_Exception_frame* frame;
1650  ARM_SWITCH_REG;
1651  EXCEPTION_ENTRY_EXC();
1652  arm_debug_break_unload();
1653  arm_debug_enable_interrupts();
1654  EXCEPTION_ENTRY_THREAD(frame);
1655  frame->vector = 3;
1656  target_exception(frame);
1657  EXCEPTION_EXIT_THREAD(frame);
1658  arm_debug_commit_interrupt_disable();
1659  arm_debug_break_load();
1660  EXCEPTION_EXIT_EXC();
1661}
1662
1663static void __attribute__((naked))
1664target_exception_data_abort(void)
1665{
1666  CPU_Exception_frame* frame;
1667  ARM_SWITCH_REG;
1668  EXCEPTION_ENTRY_EXC();
1669  arm_debug_break_unload();
1670  arm_debug_enable_interrupts();
1671  EXCEPTION_ENTRY_THREAD(frame);
1672  frame->vector = 4;
1673  target_exception(frame);
1674  EXCEPTION_EXIT_THREAD(frame);
1675  arm_debug_commit_interrupt_disable();
1676  arm_debug_break_load();
1677  EXCEPTION_EXIT_EXC();
1678}
1679
1680#if ARM_CP15
1681#if __ARM_ARCH_PROFILE == 'A'
1682/**
1683 * The init value for the text section.
1684 */
1685static uint32_t text_section_flags;
1686
1687/* Defined by linkcmds.base */
1688extern char bsp_section_text_begin[];
1689extern char bsp_section_text_end[];
1690
1691static void
1692rtems_debugger_target_set_mmu(void)
1693{
1694  void* text_begin;
1695  void* text_end;
1696  text_begin = &bsp_section_text_begin[0];
1697  text_end = &bsp_section_text_end[0];
1698  target_printk("[} MMU edit: text_begin: %p text_end: %p\n",
1699                text_begin, text_end);
1700  text_section_flags =
1701    arm_cp15_set_translation_table_entries(text_begin,
1702                                           text_end,
1703                                           ARMV7_MMU_DATA_READ_WRITE_CACHED);
1704}
1705#else
1706static void
1707rtems_debugger_target_set_mmu(void)
1708{
1709}
1710#endif
1711
1712static void
1713rtems_debugger_target_set_vectors(void)
1714{
1715  arm_cp15_set_exception_handler(ARM_EXCEPTION_UNDEF,
1716                                 target_exception_undefined_instruction);
1717  arm_cp15_set_exception_handler(ARM_EXCEPTION_SWI,
1718                                 target_exception_supervisor_call);
1719  arm_cp15_set_exception_handler(ARM_EXCEPTION_PREF_ABORT,
1720                                 target_exception_prefetch_abort);
1721  arm_cp15_set_exception_handler(ARM_EXCEPTION_DATA_ABORT,
1722                                 target_exception_data_abort);
1723}
1724#else
1725static void
1726rtems_debugger_target_set_vectors(void)
1727{
1728  /*
1729   * Dummy, please add support for your ARM variant.
1730   */
1731  void* ui = target_exception_undefined_instruction;
1732  void* sc = target_exception_supervisor_call;
1733  void* pa = target_exception_prefetch_abort;
1734  void* da = target_exception_data_abort;
1735  (void) ui;
1736  (void) sc;
1737  (void) pa;
1738  (void) da;
1739}
1740
1741static void
1742rtems_debugger_target_set_mmu(void)
1743{
1744}
1745#endif
1746
1747static bool
1748rtems_debugger_is_int_reg(size_t reg)
1749{
1750  const size_t size = arm_reg_offsets[reg + 1] - arm_reg_offsets[reg];
1751  return size == RTEMS_DEBUGGER_REG_BYTES;
1752}
1753
1754static void
1755rtems_debugger_set_int_reg(rtems_debugger_thread* thread,
1756                           size_t                 reg,
1757                           const uint32_t         value)
1758{
1759  const size_t offset = arm_reg_offsets[reg];
1760  /*
1761   * Use memcpy to avoid alignment issues.
1762   */
1763  memcpy(&thread->registers[offset], &value, sizeof(uint32_t));
1764}
1765
1766static const uint32_t
1767rtems_debugger_get_int_reg(rtems_debugger_thread* thread, size_t reg)
1768{
1769  const size_t offset = arm_reg_offsets[reg];
1770  uint32_t     value;
1771  memcpy(&value, &thread->registers[offset], sizeof(uint32_t));
1772  return value;
1773}
1774
1775int
1776rtems_debugger_target_enable(void)
1777{
1778  rtems_interrupt_lock_context lock_context;
1779  debug_session_active = true;
1780  arm_debug_break_unload();
1781  arm_debug_break_clear();
1782  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
1783  rtems_debugger_target_set_mmu();
1784  rtems_debugger_target_set_vectors();
1785  rtems_interrupt_lock_release(&target_lock, &lock_context);
1786  return 0;
1787}
1788
1789int
1790rtems_debugger_target_disable(void)
1791{
1792  rtems_interrupt_lock_context lock_context;
1793#if DOES_NOT_WORK
1794  void*                        text_begin;
1795  void*                        text_end;
1796#endif
1797  arm_debug_break_unload();
1798  arm_debug_break_clear();
1799  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
1800  debug_session_active = false;
1801#if DOES_NOT_WORK
1802  text_begin = &bsp_section_text_begin[0];
1803  text_end = &bsp_section_text_end[0];
1804  arm_cp15_set_translation_table_entries(text_begin,
1805                                         text_end,
1806                                         text_section_flags);
1807#endif
1808  rtems_interrupt_lock_release(&target_lock, &lock_context);
1809  return 0;
1810}
1811
1812int
1813rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
1814{
1815  if (!rtems_debugger_thread_flag(thread,
1816                                  RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID)) {
1817    static const uint32_t good_address = (uint32_t) &good_address;
1818    int                   i;
1819
1820    memset(&thread->registers[0], 0, RTEMS_DEBUGGER_NUMREGBYTES);
1821
1822    for (i = 0; i < RTEMS_DEBUGGER_NUMREGS; ++i) {
1823      if (rtems_debugger_is_int_reg(i))
1824        rtems_debugger_set_int_reg(thread, i, (uint32_t) &good_address);
1825    }
1826
1827    if (thread->frame) {
1828      CPU_Exception_frame* frame = thread->frame;
1829
1830      /*
1831       * Assume interrupts are not masked and if masked set them to the saved
1832       * value.
1833       */
1834      FRAME_SR(frame) &= ~CPSR_INTS_MASK;
1835
1836      if (rtems_debugger_thread_flag(thread,
1837                                     RTEMS_DEBUGGER_THREAD_FLAG_INTS_DISABLED)) {
1838        FRAME_SR(frame) |=
1839          (thread->flags >> RTEMS_DEBUGGER_THREAD_FLAG_TARGET_BASE) & CPSR_INTS_MASK;
1840        thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_INTS_DISABLED;
1841      }
1842
1843      rtems_debugger_set_int_reg(thread, REG_R0,   frame->register_r0);
1844      rtems_debugger_set_int_reg(thread, REG_R1,   frame->register_r1);
1845      rtems_debugger_set_int_reg(thread, REG_R2,   frame->register_r2);
1846      rtems_debugger_set_int_reg(thread, REG_R3,   frame->register_r3);
1847      rtems_debugger_set_int_reg(thread, REG_R4,   frame->register_r4);
1848      rtems_debugger_set_int_reg(thread, REG_R5,   frame->register_r5);
1849      rtems_debugger_set_int_reg(thread, REG_R6,   frame->register_r6);
1850      rtems_debugger_set_int_reg(thread, REG_R7,   frame->register_r7);
1851      rtems_debugger_set_int_reg(thread, REG_R8,   frame->register_r8);
1852      rtems_debugger_set_int_reg(thread, REG_R9,   frame->register_r9);
1853      rtems_debugger_set_int_reg(thread, REG_R10,  frame->register_r10);
1854      rtems_debugger_set_int_reg(thread, REG_R11,  frame->register_r11);
1855      rtems_debugger_set_int_reg(thread, REG_R12,  frame->register_r12);
1856      rtems_debugger_set_int_reg(thread, REG_SP,   frame->register_sp);
1857      rtems_debugger_set_int_reg(thread, REG_LR,   (uint32_t) frame->register_lr);
1858      rtems_debugger_set_int_reg(thread, REG_PC,   (uint32_t) frame->register_pc);
1859      rtems_debugger_set_int_reg(thread, REG_CPSR, FRAME_SR(frame));
1860      /*
1861       * Get the signal from the frame.
1862       */
1863      thread->signal = rtems_debugger_target_exception_to_signal(frame);
1864    }
1865    else {
1866#if defined(ARM_MULTILIB_ARCH_V4)
1867      rtems_debugger_set_int_reg(thread, REG_R4,  thread->tcb->Registers.register_r4);
1868      rtems_debugger_set_int_reg(thread, REG_R5,  thread->tcb->Registers.register_r5);
1869      rtems_debugger_set_int_reg(thread, REG_R6,  thread->tcb->Registers.register_r6);
1870      rtems_debugger_set_int_reg(thread, REG_R7,  thread->tcb->Registers.register_r7);
1871      rtems_debugger_set_int_reg(thread, REG_R8,  thread->tcb->Registers.register_r8);
1872      rtems_debugger_set_int_reg(thread, REG_R9,  thread->tcb->Registers.register_r9);
1873      rtems_debugger_set_int_reg(thread, REG_R10, thread->tcb->Registers.register_r10);
1874      rtems_debugger_set_int_reg(thread, REG_R11, thread->tcb->Registers.register_fp);
1875      rtems_debugger_set_int_reg(thread, REG_LR,  (intptr_t) thread->tcb->Registers.register_lr);
1876      rtems_debugger_set_int_reg(thread, REG_PC,  (intptr_t) thread->tcb->Registers.register_lr);
1877      rtems_debugger_set_int_reg(thread, REG_SP,  (intptr_t) thread->tcb->Registers.register_sp);
1878#elif defined(ARM_MULTILIB_ARCH_V7M)
1879      rtems_debugger_set_int_reg(thread, REG_R4,  thread->tcb->Registers.register_r4);
1880      rtems_debugger_set_int_reg(thread, REG_R5,  thread->tcb->Registers.register_r5);
1881      rtems_debugger_set_int_reg(thread, REG_R6,  thread->tcb->Registers.register_r6);
1882      rtems_debugger_set_int_reg(thread, REG_R7,  thread->tcb->Registers.register_r7);
1883      rtems_debugger_set_int_reg(thread, REG_R8,  thread->tcb->Registers.register_r8);
1884      rtems_debugger_set_int_reg(thread, REG_R9,  thread->tcb->Registers.register_r9);
1885      rtems_debugger_set_int_reg(thread, REG_R10, thread->tcb->Registers.register_r10);
1886      rtems_debugger_set_int_reg(thread, REG_R11, thread->tcb->Registers.register_r11);
1887      rtems_debugger_set_int_reg(thread, REG_LR,  (intptr_t) thread->tcb->Registers.register_lr);
1888      rtems_debugger_set_int_reg(thread, REG_PC,  (intptr_t) thread->tcb->Registers.register_lr);
1889      rtems_debugger_set_int_reg(thread, REG_SP,  (intptr_t) thread->tcb->Registers.register_sp);
1890#endif
1891      /*
1892       * Blocked threads have no signal.
1893       */
1894      thread->signal = 0;
1895    }
1896
1897    thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID;
1898    thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
1899  }
1900
1901  return 0;
1902}
1903
1904int
1905rtems_debugger_target_write_regs(rtems_debugger_thread* thread)
1906{
1907  if (rtems_debugger_thread_flag(thread,
1908                                 RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY)) {
1909    /*
1910     * Only write to debugger controlled exception threads. Do not touch the
1911     * registers for threads blocked in the context switcher.
1912     */
1913    if (rtems_debugger_thread_flag(thread,
1914                                   RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
1915      CPU_Exception_frame* frame = thread->frame;
1916      frame->register_r0  = rtems_debugger_get_int_reg(thread, REG_R0);
1917      frame->register_r1  = rtems_debugger_get_int_reg(thread, REG_R1);
1918      frame->register_r2  = rtems_debugger_get_int_reg(thread, REG_R2);
1919      frame->register_r3  = rtems_debugger_get_int_reg(thread, REG_R3);
1920      frame->register_r4  = rtems_debugger_get_int_reg(thread, REG_R4);
1921      frame->register_r5  = rtems_debugger_get_int_reg(thread, REG_R5);
1922      frame->register_r6  = rtems_debugger_get_int_reg(thread, REG_R6);
1923      frame->register_r7  = rtems_debugger_get_int_reg(thread, REG_R7);
1924      frame->register_r8  = rtems_debugger_get_int_reg(thread, REG_R8);
1925      frame->register_r9  = rtems_debugger_get_int_reg(thread, REG_R9);
1926      frame->register_r10 = rtems_debugger_get_int_reg(thread, REG_R10);
1927      frame->register_r11 = rtems_debugger_get_int_reg(thread, REG_R11);
1928      frame->register_r12 = rtems_debugger_get_int_reg(thread, REG_R12);
1929      frame->register_sp  = rtems_debugger_get_int_reg(thread, REG_SP);
1930      frame->register_lr  = (void*) rtems_debugger_get_int_reg(thread, REG_LR);
1931      frame->register_pc  = (void*) rtems_debugger_get_int_reg(thread, REG_PC);
1932      FRAME_SR(frame)     = rtems_debugger_get_int_reg(thread, REG_CPSR);
1933    }
1934    thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
1935  }
1936  return 0;
1937}
1938
1939DB_UINT
1940rtems_debugger_target_reg_pc(rtems_debugger_thread* thread)
1941{
1942  int r;
1943  r = rtems_debugger_target_read_regs(thread);
1944  if (r >= 0) {
1945    return rtems_debugger_get_int_reg(thread, REG_PC);
1946  }
1947  return 0;
1948}
1949
1950DB_UINT
1951rtems_debugger_target_frame_pc(CPU_Exception_frame* frame)
1952{
1953  return (DB_UINT) frame->register_pc;
1954}
1955
1956DB_UINT
1957rtems_debugger_target_reg_sp(rtems_debugger_thread* thread)
1958{
1959  int r;
1960  r = rtems_debugger_target_read_regs(thread);
1961  if (r >= 0) {
1962    return rtems_debugger_get_int_reg(thread, REG_SP);
1963  }
1964  return 0;
1965}
1966
1967DB_UINT
1968rtems_debugger_target_tcb_sp(rtems_debugger_thread* thread)
1969{
1970  return (DB_UINT) thread->tcb->Registers.register_sp;
1971}
1972
1973int
1974rtems_debugger_target_thread_stepping(rtems_debugger_thread* thread)
1975{
1976  if (rtems_debugger_thread_flag(thread, RTEMS_DEBUGGER_THREAD_FLAG_STEP_INSTR)) {
1977    /*
1978     * Single stepping and range stepping uses hardware debug breakpoint
1979     * 0. This is reserved for single stepping.
1980     */
1981    CPU_Exception_frame* frame = thread->frame;
1982    arm_debug_hwbreak*   bp = &hw_breaks[0];
1983
1984    target_printk("[} stepping: %s\n", bp->enabled ? "yes" : "no");
1985
1986    if (!bp->enabled) {
1987      const uint32_t addr = (intptr_t) frame->register_pc;
1988      const bool     thumb = (FRAME_SR(frame) & (1 << 5)) != 0 ? true : false;
1989      uint32_t       bas;
1990
1991      bp->enabled = true;
1992      bp->loaded = false;
1993      bp->address = frame->register_pc;
1994      bp->frame = frame;
1995      bp->length = sizeof(uint32_t);
1996
1997      if (thumb) {
1998        uint16_t instr = *((uint16_t*) frame->register_pc);
1999        switch (instr & 0xf800) {
2000        case 0xe800:
2001        case 0xf000:
2002        case 0xf800:
2003          break;
2004        default:
2005          bp->length = sizeof(uint16_t);
2006          break;
2007        }
2008      }
2009
2010      /*
2011       * See table C3-2 Effect of byte address selection on Breakpoint
2012       * generation and "Instruction address comparision programming
2013       * examples.
2014       */
2015      if (thumb) {
2016        if ((addr & (1 << 1)) == 0) {
2017          bas = 0x3; /* b0011 */
2018        }
2019        else {
2020          bas = 0xc; /* b1100 */
2021        }
2022      }
2023      else {
2024        bas = 0xf; /* b1111 */
2025      }
2026
2027      arm_debug_break_setup(bp,
2028                            addr & ~0x3,
2029                            ARM_HW_BP_UNLINKED_INSTR_MISMATCH,
2030                            bas,
2031                            ARM_HW_BP_PRIV_PL0_SUP_SYS);
2032
2033      arm_debug_disable_interrupts();
2034    }
2035  }
2036  return 0;
2037}
2038
2039int
2040rtems_debugger_target_exception_to_signal(CPU_Exception_frame* frame)
2041{
2042  int sig = RTEMS_DEBUGGER_SIGNAL_HUP;
2043#if defined(ARM_MULTILIB_ARCH_V4)
2044  switch (frame->vector) {
2045  case ARM_EXCEPTION_RESET:
2046  case ARM_EXCEPTION_SWI:
2047    sig = RTEMS_DEBUGGER_SIGNAL_TRAP;
2048    break;
2049  case ARM_EXCEPTION_UNDEF:
2050    sig = RTEMS_DEBUGGER_SIGNAL_ILL;
2051    break;
2052  case ARM_EXCEPTION_FIQ:
2053    sig = RTEMS_DEBUGGER_SIGNAL_FPE;
2054    break;
2055  case ARM_EXCEPTION_PREF_ABORT:
2056  case ARM_EXCEPTION_DATA_ABORT:
2057    sig = RTEMS_DEBUGGER_SIGNAL_SEGV;
2058    break;
2059  case ARM_EXCEPTION_RESERVED:
2060  case ARM_EXCEPTION_IRQ:
2061    sig = RTEMS_DEBUGGER_SIGNAL_BUS;
2062    break;
2063  default:
2064    break;
2065  }
2066#endif
2067  return sig;
2068}
2069
2070void
2071rtems_debugger_target_exception_print(CPU_Exception_frame* frame)
2072{
2073  EXC_FRAME_PRINT(rtems_debugger_printf, "", frame);
2074}
2075
2076int
2077rtems_debugger_target_hwbreak_insert(void)
2078{
2079  /*
2080   * Do nothing, load on exit of the exception handler.
2081   */
2082  return 0;
2083}
2084
2085int
2086rtems_debugger_target_hwbreak_remove(void)
2087{
2088  arm_debug_break_unload();
2089  return 0;
2090}
2091
2092int
2093rtems_debugger_target_hwbreak_control(rtems_debugger_target_watchpoint wp,
2094                                      bool                             insert,
2095                                      DB_UINT                          addr,
2096                                      DB_UINT                          kind)
2097{
2098  /*
2099   * To do.
2100   */
2101  return 0;
2102}
2103
2104int
2105rtems_debugger_target_cache_sync(rtems_debugger_target_swbreak* swbreak)
2106{
2107  /*
2108   * Flush the data cache and invalidate the instruction cache.
2109   */
2110  rtems_cache_flush_multiple_data_lines(swbreak->address,
2111                                        sizeof(breakpoint));
2112  rtems_cache_instruction_sync_after_code_change(swbreak->address,
2113                                                 sizeof(breakpoint));
2114  return 0;
2115}
Note: See TracBrowser for help on using the repository browser.