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

5
Last change on this file since df256505 was df256505, checked in by Chris Johns <chrisj@…>, on 08/11/19 at 22:56:37

libdebugger/arm: Support ROM tables.

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