Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:15

0001 /*
0002  * Copyright (c) 2016-2019 Chris Johns <chrisj@rtems.org>.
0003  * All rights reserved.
0004  *
0005  * Redistribution and use in source and binary forms, with or without
0006  * modification, are permitted provided that the following conditions
0007  * are met:
0008  * 1. Redistributions of source code must retain the above copyright
0009  *    notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *    notice, this list of conditions and the following disclaimer in the
0012  *    documentation and/or other materials provided with the distribution.
0013  *
0014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0015  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0016  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0017  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0018  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0019  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0020  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0021  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0022  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0023  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0024  * SUCH DAMAGE.
0025  */
0026 
0027 #define TARGET_DEBUG 0
0028 
0029 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032 
0033 #include <errno.h>
0034 #include <inttypes.h>
0035 #include <stdlib.h>
0036 
0037 /* Defined by linkcmds.base. This should be taken from <bsp/linker-symbols.h> */
0038 extern char bsp_section_start_begin[];
0039 extern char bsp_section_start_end[];
0040 extern char bsp_section_text_begin[];
0041 extern char bsp_section_text_end[];
0042 extern char bsp_section_fast_text_begin[];
0043 extern char bsp_section_fast_text_end[];
0044 
0045 #include <libcpu/mmu-vmsav8-64.h>
0046 
0047 #include <rtems.h>
0048 #include <rtems/score/aarch64-system-registers.h>
0049 #include <rtems/score/cpu.h>
0050 #include <rtems/score/threadimpl.h>
0051 
0052 #include <rtems/debugger/rtems-debugger-bsp.h>
0053 
0054 #include "rtems-debugger-target.h"
0055 #include "rtems-debugger-threads.h"
0056 
0057 #if TARGET_DEBUG
0058 #include <rtems/bspIo.h>
0059 #endif
0060 
0061 /*
0062  * Structure used to manage a task executing a function on available cores on
0063  * a scheduler.
0064  */
0065 typedef struct {
0066   rtems_id allCPUsBarrier;
0067   rtems_task_entry work_function;
0068   rtems_task_argument arg;
0069   rtems_status_code sc;
0070 } run_across_cpus_context;
0071 
0072 /*
0073  * The function that runs as the body of the task which moves itself among the
0074  * various cores registered to a scheduler.
0075  */
0076 static rtems_task run_across_cpus_task( rtems_task_argument arg )
0077 {
0078   uint32_t                 released = 0;
0079   rtems_status_code        sc;
0080   run_across_cpus_context *ctx = (run_across_cpus_context *) arg;
0081   cpu_set_t                set;
0082   cpu_set_t                scheduler_set;
0083   rtems_id                 scheduler_id;
0084 
0085   sc = rtems_task_get_scheduler( RTEMS_SELF, &scheduler_id );
0086 
0087   if ( sc != RTEMS_SUCCESSFUL ) {
0088     ctx->sc = sc;
0089     rtems_task_exit();
0090   }
0091 
0092   CPU_ZERO( &scheduler_set );
0093   sc = rtems_scheduler_get_processor_set(
0094     scheduler_id,
0095     sizeof( scheduler_set ),
0096     &scheduler_set
0097   );
0098 
0099   if ( sc != RTEMS_SUCCESSFUL ) {
0100     ctx->sc = sc;
0101     rtems_task_exit();
0102   }
0103 
0104   for (
0105     int cpu_index = 0;
0106     cpu_index < rtems_scheduler_get_processor_maximum();
0107     cpu_index++
0108   ) {
0109     if ( !CPU_ISSET( cpu_index, &scheduler_set ) ) {
0110       continue;
0111     }
0112 
0113     CPU_ZERO( &set );
0114     CPU_SET( cpu_index, &set );
0115     sc = rtems_task_set_affinity( RTEMS_SELF, sizeof( set ), &set );
0116 
0117     if ( sc != RTEMS_SUCCESSFUL ) {
0118       ctx->sc = sc;
0119       rtems_task_exit();
0120     }
0121 
0122     /* execute task on selected CPU */
0123     ctx->work_function( ctx->arg );
0124   }
0125 
0126   sc = rtems_barrier_release( ctx->allCPUsBarrier, &released );
0127 
0128   if ( sc != RTEMS_SUCCESSFUL ) {
0129     ctx->sc = sc;
0130   }
0131 
0132   rtems_task_exit();
0133 }
0134 
0135 /*
0136  * The function used to run a provided function with arbitrary argument across
0137  * all cores registered to the current scheduler. This is similar to the Linux
0138  * kernel's on_each_cpu() call and always waits for the task to complete before
0139  * returning.
0140  */
0141 static rtems_status_code run_across_cpus(
0142   rtems_task_entry    task_entry,
0143   rtems_task_argument arg
0144 )
0145 {
0146   rtems_status_code       sc;
0147   rtems_id                Task_id;
0148   run_across_cpus_context ctx;
0149 
0150   ctx.work_function = task_entry;
0151   ctx.arg = arg;
0152   ctx.sc = RTEMS_SUCCESSFUL;
0153 
0154   memset( &ctx.allCPUsBarrier, 0, sizeof( ctx.allCPUsBarrier ) );
0155   sc = rtems_barrier_create(
0156     rtems_build_name( 'B', 'c', 'p', 'u' ),
0157     RTEMS_BARRIER_MANUAL_RELEASE,
0158     2,
0159     &ctx.allCPUsBarrier
0160   );
0161 
0162   if ( sc != RTEMS_SUCCESSFUL ) {
0163     return sc;
0164   }
0165 
0166   sc = rtems_task_create(
0167     rtems_build_name( 'T', 'c', 'p', 'u' ),
0168     1,
0169     RTEMS_MINIMUM_STACK_SIZE * 2,
0170     RTEMS_DEFAULT_MODES,
0171     RTEMS_FLOATING_POINT | RTEMS_DEFAULT_ATTRIBUTES,
0172     &Task_id
0173   );
0174 
0175   if ( sc != RTEMS_SUCCESSFUL ) {
0176     rtems_barrier_delete( ctx.allCPUsBarrier );
0177     return sc;
0178   }
0179 
0180   sc = rtems_task_start(
0181     Task_id,
0182     run_across_cpus_task,
0183     ( rtems_task_argument ) & ctx
0184   );
0185 
0186   if ( sc != RTEMS_SUCCESSFUL ) {
0187     rtems_task_delete( Task_id );
0188     rtems_barrier_delete( ctx.allCPUsBarrier );
0189     return sc;
0190   }
0191 
0192   /* wait on task */
0193   sc = rtems_barrier_wait( ctx.allCPUsBarrier, RTEMS_NO_TIMEOUT );
0194 
0195   if ( sc != RTEMS_SUCCESSFUL ) {
0196     rtems_task_delete( Task_id );
0197     rtems_barrier_delete( ctx.allCPUsBarrier );
0198     return sc;
0199   }
0200 
0201   rtems_barrier_delete( ctx.allCPUsBarrier );
0202 
0203   if ( ctx.sc != RTEMS_SUCCESSFUL ) {
0204     return ctx.sc;
0205   }
0206 
0207   return sc;
0208 }
0209 
0210 /*
0211  * Number of registers.
0212  */
0213 #define RTEMS_DEBUGGER_NUMREGS 68
0214 
0215 /*
0216  * Number of bytes per type of register.
0217  */
0218 #define RTEMS_DEBUGGER_REG_BYTES    8
0219 
0220 /* Debugger registers layout. See aarch64-core.xml in GDB source. */
0221 #define REG_X0    0
0222 #define REG_X1    1
0223 #define REG_X2    2
0224 #define REG_X3    3
0225 #define REG_X4    4
0226 #define REG_X5    5
0227 #define REG_X6    6
0228 #define REG_X7    7
0229 #define REG_X8    8
0230 #define REG_X9    9
0231 #define REG_X10   10
0232 #define REG_X11   11
0233 #define REG_X12   12
0234 #define REG_X13   13
0235 #define REG_X14   14
0236 #define REG_X15   15
0237 #define REG_X16   16
0238 #define REG_X17   17
0239 #define REG_X18   18
0240 #define REG_X19   19
0241 #define REG_X20   20
0242 #define REG_X21   21
0243 #define REG_X22   22
0244 #define REG_X23   23
0245 #define REG_X24   24
0246 #define REG_X25   25
0247 #define REG_X26   26
0248 #define REG_X27   27
0249 #define REG_X28   28
0250 #define REG_FP    29
0251 #define REG_LR    30
0252 #define REG_SP    31
0253 /*
0254  * PC isn't a real directly accessible register on AArch64, but is exposed via
0255  * ELR_EL1 in exception context.
0256  */
0257 #define REG_PC    32
0258 /* CPSR is defined as 32-bit by GDB */
0259 #define REG_CPS   33
0260 /* Debugger registers layout. See aarch64-fpu.xml in GDB source. */
0261 #define REG_V0    34
0262 #define REG_V1    35
0263 #define REG_V2    36
0264 #define REG_V3    37
0265 #define REG_V4    38
0266 #define REG_V5    39
0267 #define REG_V6    40
0268 #define REG_V7    41
0269 #define REG_V8    42
0270 #define REG_V9    43
0271 #define REG_V10   44
0272 #define REG_V11   45
0273 #define REG_V12   46
0274 #define REG_V13   47
0275 #define REG_V14   48
0276 #define REG_V15   49
0277 #define REG_V16   50
0278 #define REG_V17   51
0279 #define REG_V18   52
0280 #define REG_V19   53
0281 #define REG_V20   54
0282 #define REG_V21   55
0283 #define REG_V22   56
0284 #define REG_V23   57
0285 #define REG_V24   58
0286 #define REG_V25   59
0287 #define REG_V26   60
0288 #define REG_V27   61
0289 #define REG_V28   62
0290 #define REG_V29   63
0291 #define REG_V30   64
0292 #define REG_V31   65
0293 /* FPSR and FPCR are defined as 32-bit by GDB */
0294 #define REG_FPS   66
0295 #define REG_FPC   67
0296 
0297 /**
0298  * Register offset table with the total as the last entry.
0299  *
0300  * Check this table in gdb with the command:
0301  *
0302  *   maint print registers
0303  */
0304 static const size_t aarch64_reg_offsets[ RTEMS_DEBUGGER_NUMREGS + 1 ] = {
0305   REG_X0 * 8,
0306   REG_X1 * 8,
0307   REG_X2 * 8,
0308   REG_X3 * 8,
0309   REG_X4 * 8,
0310   REG_X5 * 8,
0311   REG_X6 * 8,
0312   REG_X7 * 8,
0313   REG_X8 * 8,
0314   REG_X9 * 8,
0315   REG_X10 * 8,
0316   REG_X11 * 8,
0317   REG_X12 * 8,
0318   REG_X13 * 8,
0319   REG_X14 * 8,
0320   REG_X15 * 8,
0321   REG_X16 * 8,
0322   REG_X17 * 8,
0323   REG_X18 * 8,
0324   REG_X19 * 8,
0325   REG_X20 * 8,
0326   REG_X21 * 8,
0327   REG_X22 * 8,
0328   REG_X23 * 8,
0329   REG_X24 * 8,
0330   REG_X25 * 8,
0331   REG_X26 * 8,
0332   REG_X27 * 8,
0333   REG_X28 * 8,
0334   REG_FP * 8,
0335   REG_LR * 8,
0336   REG_SP * 8,
0337   REG_PC * 8,
0338   REG_CPS * 8,
0339 /* Floating point registers, CPS is 32-bit */
0340 #define V0_OFFSET ( REG_CPS * 8 + 4 )
0341   V0_OFFSET,
0342   V0_OFFSET + 16 * ( REG_V1 - REG_V0 ),
0343   V0_OFFSET + 16 * ( REG_V2 - REG_V0 ),
0344   V0_OFFSET + 16 * ( REG_V3 - REG_V0 ),
0345   V0_OFFSET + 16 * ( REG_V4 - REG_V0 ),
0346   V0_OFFSET + 16 * ( REG_V5 - REG_V0 ),
0347   V0_OFFSET + 16 * ( REG_V6 - REG_V0 ),
0348   V0_OFFSET + 16 * ( REG_V7 - REG_V0 ),
0349   V0_OFFSET + 16 * ( REG_V8 - REG_V0 ),
0350   V0_OFFSET + 16 * ( REG_V9 - REG_V0 ),
0351   V0_OFFSET + 16 * ( REG_V10 - REG_V0 ),
0352   V0_OFFSET + 16 * ( REG_V11 - REG_V0 ),
0353   V0_OFFSET + 16 * ( REG_V12 - REG_V0 ),
0354   V0_OFFSET + 16 * ( REG_V13 - REG_V0 ),
0355   V0_OFFSET + 16 * ( REG_V14 - REG_V0 ),
0356   V0_OFFSET + 16 * ( REG_V15 - REG_V0 ),
0357   V0_OFFSET + 16 * ( REG_V16 - REG_V0 ),
0358   V0_OFFSET + 16 * ( REG_V17 - REG_V0 ),
0359   V0_OFFSET + 16 * ( REG_V18 - REG_V0 ),
0360   V0_OFFSET + 16 * ( REG_V19 - REG_V0 ),
0361   V0_OFFSET + 16 * ( REG_V20 - REG_V0 ),
0362   V0_OFFSET + 16 * ( REG_V21 - REG_V0 ),
0363   V0_OFFSET + 16 * ( REG_V22 - REG_V0 ),
0364   V0_OFFSET + 16 * ( REG_V23 - REG_V0 ),
0365   V0_OFFSET + 16 * ( REG_V24 - REG_V0 ),
0366   V0_OFFSET + 16 * ( REG_V25 - REG_V0 ),
0367   V0_OFFSET + 16 * ( REG_V26 - REG_V0 ),
0368   V0_OFFSET + 16 * ( REG_V27 - REG_V0 ),
0369   V0_OFFSET + 16 * ( REG_V28 - REG_V0 ),
0370   V0_OFFSET + 16 * ( REG_V29 - REG_V0 ),
0371   V0_OFFSET + 16 * ( REG_V30 - REG_V0 ),
0372   V0_OFFSET + 16 * ( REG_V31 - REG_V0 ),
0373 /* FPSR and FPCR are defined as 32-bit by GDB */
0374 #define FPS_OFFSET ( V0_OFFSET + 16 * ( REG_V31 - REG_V0 ) + 16 )
0375   FPS_OFFSET,
0376 /* FPC follows FPS */
0377   FPS_OFFSET + 4,
0378 /* Total size */
0379   FPS_OFFSET + 8,
0380 };
0381 
0382 /*
0383  * Number of bytes of registers.
0384  */
0385 #define RTEMS_DEBUGGER_NUMREGBYTES \
0386   aarch64_reg_offsets[ RTEMS_DEBUGGER_NUMREGS ]
0387 
0388 /**
0389  * Print the exception frame.
0390  */
0391 #define EXC_FRAME_PRINT( _out, _prefix, _frame ) \
0392   do { \
0393     _out( \
0394       _prefix "  X0 = %016" PRIx64 "  X1 = %016" PRIx64 \
0395       "  X2 = %016" PRIx64 "  X3 = %016" PRIx64 "\n", \
0396       _frame->register_x0, \
0397       _frame->register_x1, \
0398       _frame->register_x2, \
0399       _frame->register_x3 \
0400     ); \
0401     _out( \
0402       _prefix "  X4 = %016" PRIx64 "  X5 = %016" PRIx64 \
0403       "  X6 = %016" PRIx64 "  X7 = %016" PRIx64 "\n", \
0404       _frame->register_x4, \
0405       _frame->register_x5, \
0406       _frame->register_x6, \
0407       _frame->register_x7 \
0408     ); \
0409     _out( \
0410       _prefix "  X8 = %016" PRIx64 "  X9 = %016" PRIx64 \
0411       " X10 = %016" PRIx64 " X11 = %016" PRIx64 "\n", \
0412       _frame->register_x8, \
0413       _frame->register_x9, \
0414       _frame->register_x10, \
0415       _frame->register_x11 \
0416     ); \
0417     _out( \
0418       _prefix " X12 = %016" PRIx64 " X13 = %016" PRIx64 \
0419       " X14 = %016" PRIx64 " X15 = %016" PRIx64 "\n", \
0420       _frame->register_x12, \
0421       _frame->register_x13, \
0422       _frame->register_x14, \
0423       _frame->register_x15 \
0424     ); \
0425     _out( \
0426       _prefix " X16 = %016" PRIx64 " X17 = %016" PRIx64 \
0427       " X18 = %016" PRIx64 " X19 = %016" PRIx64 "\n", \
0428       _frame->register_x16, \
0429       _frame->register_x17, \
0430       _frame->register_x18, \
0431       _frame->register_x19 \
0432     ); \
0433     _out( \
0434       _prefix " X20 = %016" PRIx64 " X21 = %016" PRIx64 \
0435       " X22 = %016" PRIx64 " X23 = %016" PRIx64 "\n", \
0436       _frame->register_x20, \
0437       _frame->register_x21, \
0438       _frame->register_x22, \
0439       _frame->register_x23 \
0440     ); \
0441     _out( \
0442       _prefix " X24 = %016" PRIx64 " X25 = %016" PRIx64 \
0443       " X26 = %016" PRIx64 " X27 = %016" PRIx64 "\n", \
0444       _frame->register_x24, \
0445       _frame->register_x25, \
0446       _frame->register_x26, \
0447       _frame->register_x27 \
0448     ); \
0449     _out( \
0450       _prefix " X28 = %016" PRIx64 "  FP = %016" PRIx64 \
0451       "  LR = %016" PRIxPTR "  SP = %016" PRIxPTR "\n", \
0452       _frame->register_x28, \
0453       _frame->register_fp, \
0454       (intptr_t) _frame->register_lr, \
0455       (intptr_t) _frame->register_sp \
0456     ); \
0457     _out( \
0458       _prefix "  PC = %016" PRIxPTR "\n", \
0459       (intptr_t) _frame->register_pc \
0460     ); \
0461     _out( \
0462       _prefix " CPSR = %08" PRIx64 " %c%c%c%c%c%c%c%c%c" \
0463       " M:%" PRIx64 " %s\n", \
0464       _frame->register_cpsr, \
0465       ( _frame->register_cpsr & ( 1 << 31 ) ) != 0 ? 'N' : '-', \
0466       ( _frame->register_cpsr & ( 1 << 30 ) ) != 0 ? 'Z' : '-', \
0467       ( _frame->register_cpsr & ( 1 << 29 ) ) != 0 ? 'C' : '-', \
0468       ( _frame->register_cpsr & ( 1 << 28 ) ) != 0 ? 'V' : '-', \
0469       ( _frame->register_cpsr & ( 1 << 21 ) ) != 0 ? 'S' : '-', \
0470       ( _frame->register_cpsr & ( 1 << 9 ) ) != 0 ? 'D' : '-', \
0471       ( _frame->register_cpsr & ( 1 << 8 ) ) != 0 ? 'A' : '-', \
0472       ( _frame->register_cpsr & ( 1 << 7 ) ) != 0 ? 'I' : '-', \
0473       ( _frame->register_cpsr & ( 1 << 6 ) ) != 0 ? 'F' : '-', \
0474       _frame->register_cpsr & 0x1f, \
0475       aarch64_mode_label( _frame->register_cpsr & 0x1f ) \
0476     ); \
0477   } while ( 0 )
0478 
0479 /**
0480  * The breakpoint instruction.
0481  */
0482 static const uint8_t breakpoint[ 4 ] = { 0x00, 0x00, 0x20, 0xd4 };
0483 
0484 /**
0485  * Target lock.
0486  */
0487 RTEMS_INTERRUPT_LOCK_DEFINE( static, target_lock, "target_lock" )
0488 
0489 /**
0490  * Is a session active?
0491  */
0492 static bool debug_session_active;
0493 
0494 /*
0495  * AArch64 debug hardware.
0496  */
0497 static uint64_t hw_breakpoints;
0498 static uint64_t hw_watchpoints;
0499 
0500 #ifdef HARDWARE_BREAKPOINTS_NOT_USED
0501 /**
0502  * Hardware break and watch points.
0503  */
0504 typedef struct {
0505   bool enabled;
0506   bool loaded;
0507   void *address;
0508   size_t length;
0509   CPU_Exception_frame *frame;
0510   uint64_t control;
0511   uint64_t value;
0512 } aarch64_debug_hwbreak;
0513 
0514 /*
0515  * AArch64 guarantees that 2-16 breakpoints will be available in:
0516  * DBGBCR<0-15>_EL1 (control)
0517  *   BT: BSP_FLD64(val, 20, 23) (breakpoint type, always 0x0 or 0x4, address match or mismatch)
0518  *   LBN: BSP_FLD64(val, 16, 19) (linked breakpoint number, always 0x0, not relevant given above)
0519  *   SSC: BSP_FLD64(val, 14, 15) (security state control, only 0x0 relevant)
0520  *   HMC: BSP_BIT64(13) (higher mode control, only 0x0 relevant)
0521  *   BAS: BSP_FLD64(val, 5, 8) (byte address select, always 0xF, other values denote debugging of AArch32 code)
0522  *   PMC: BSP_FLD64(val, 1, 2) (privelege mode control, only 0x1 relevant)
0523  *   E: BSP_BIT64(0) (enable, 0x1 when in use, 0x0 when disabled)
0524  * DBGBVR<0-15>_EL1 (value, address)
0525  * ID_AA64DFR0_EL1
0526  *   WRPs: BSP_FLD64(val, 20, 23) (watchpoints implemented - 1, 0x0 reserved so minimum 2)
0527  *   BRPs: BSP_FLD64(val, 12, 15) (breakpoints implemented - 1, 0x0 reserved so minimum 2)
0528  *   DebugVer: BSP_FLD64(val, 0, 3) (0x6 - 8, 0x7 - 8 w/ VHE, 0x8 - 8.2, 0x9 - 8.4)
0529  */
0530 #define AARCH64_HW_BREAKPOINT_MAX ( 16 )
0531 
0532 /*
0533  * Types of break points.
0534  */
0535 #define AARCH64_HW_BP_TYPE_UNLINKED_INSTR_MATCH ( 0x0 << 20 )
0536 #define AARCH64_HW_BP_TYPE_UNLINKED_INSTR_MISMATCH ( 0x4 << 20 )
0537 
0538 /*
0539  * Byte Address Select
0540  */
0541 #define AARCH64_HW_BP_BAS_A64 ( 0xF << 5 )
0542 
0543 /*
0544  * Privilege level, corresponds to PMC at 2:1
0545  */
0546 #define AARCH64_HW_BP_PRIV_EL1 ( 0x1 << 1 )
0547 
0548 /*
0549  * Breakpoint enable.
0550  */
0551 #define AARCH64_HW_BP_ENABLE ( 0x1 )
0552 
0553 static aarch64_debug_hwbreak hw_breaks[ AARCH64_HW_BREAKPOINT_MAX ];
0554 #endif
0555 
0556 /*
0557  * Target debugging support. Use this to debug the backend.
0558  */
0559 #if TARGET_DEBUG
0560 
0561 void rtems_debugger_printk_lock( rtems_interrupt_lock_context *lock_context );
0562 
0563 void rtems_debugger_printk_unlock(
0564   rtems_interrupt_lock_context *lock_context
0565 );
0566 
0567 static void target_printk( const char *format, ... ) RTEMS_PRINTFLIKE( 1, 2 );
0568 
0569 static void target_printk( const char *format, ... )
0570 {
0571   rtems_interrupt_lock_context lock_context;
0572   va_list                      ap;
0573 
0574   va_start( ap, format );
0575   rtems_debugger_printk_lock( &lock_context );
0576   vprintk( format, ap );
0577   rtems_debugger_printk_unlock( &lock_context );
0578   va_end( ap );
0579 }
0580 
0581 #else
0582 #define target_printk( _fmt, ... )
0583 #endif
0584 
0585 static const char *aarch64_mode_label( int mode )
0586 {
0587   switch ( mode ) {
0588    case 0x0:
0589      return "EL0t";
0590    case 0x4:
0591      return "EL1t";
0592    case 0x5:
0593      return "EL1h";
0594   }
0595 
0596   return "---";
0597 }
0598 
0599 static int aarch64_debug_probe( rtems_debugger_target *target )
0600 {
0601   int                debug_version;
0602   uint64_t           val;
0603   const char        *vl = "[Invalid version]";
0604   const char * const labels[] = {
0605     NULL,
0606     NULL,
0607     NULL,
0608     NULL,
0609     NULL,
0610     NULL,
0611     "ARMv8.0",
0612     "ARMv8.0+VHE",
0613     "ARMv8.2",
0614     "ARMv8.4"
0615   };
0616 
0617   val = _AArch64_Read_midr_el1();
0618   rtems_debugger_printf(
0619     "rtems-db: aarch64 core: Architecture: %" PRIu64 " Variant: %" PRIu64 " " \
0620     "Implementor: %" PRIu64 " Part Number: %" PRIu64 " Revision: %" PRIu64 "\n",
0621     AARCH64_MIDR_EL1_ARCHITECTURE_GET( val ),
0622     AARCH64_MIDR_EL1_VARIANT_GET( val ),
0623     AARCH64_MIDR_EL1_IMPLEMENTER_GET( val ),
0624     AARCH64_MIDR_EL1_PARTNUM_GET( val ),
0625     AARCH64_MIDR_EL1_REVISION_GET( val )
0626   );
0627 
0628   val = _AArch64_Read_id_aa64dfr0_el1();
0629 
0630   debug_version = AARCH64_ID_AA64DFR0_EL1_DEBUGVER_GET( val );
0631 
0632   if ( debug_version < 6 || debug_version > 9 ) {
0633     rtems_debugger_printf(
0634       "rtems-db: aarch64 debug: %d not supported\n",
0635       debug_version
0636     );
0637     errno = EIO;
0638     return -1;
0639   }
0640 
0641   vl = labels[ debug_version ];
0642   hw_breakpoints = AARCH64_ID_AA64DFR0_EL1_BRPS_GET( val );
0643   hw_watchpoints = AARCH64_ID_AA64DFR0_EL1_WRPS_GET( val );
0644 
0645   rtems_debugger_printf(
0646     "rtems-db: aarch64 debug: %s (%d) " \
0647     "breakpoints:%" PRIu64 " watchpoints:%" PRIu64 "\n",
0648     vl,
0649     debug_version,
0650     hw_breakpoints,
0651     hw_watchpoints
0652   );
0653 
0654   return 0;
0655 }
0656 
0657 #ifdef HARDWARE_BREAKPOINTS_NOT_USED
0658 static void aarch64_debug_break_write_control( int bp, uint64_t control )
0659 {
0660   if ( bp < 15 ) {
0661     switch ( bp ) {
0662      case 0:
0663        _AArch64_Write_dbgbcr0_el1( control );
0664        break;
0665      case 1:
0666        _AArch64_Write_dbgbcr1_el1( control );
0667        break;
0668      case 2:
0669        _AArch64_Write_dbgbcr2_el1( control );
0670        break;
0671      case 3:
0672        _AArch64_Write_dbgbcr3_el1( control );
0673        break;
0674      case 4:
0675        _AArch64_Write_dbgbcr4_el1( control );
0676        break;
0677      case 5:
0678        _AArch64_Write_dbgbcr5_el1( control );
0679        break;
0680      case 6:
0681        _AArch64_Write_dbgbcr6_el1( control );
0682        break;
0683      case 7:
0684        _AArch64_Write_dbgbcr7_el1( control );
0685        break;
0686      case 8:
0687        _AArch64_Write_dbgbcr8_el1( control );
0688        break;
0689      case 9:
0690        _AArch64_Write_dbgbcr9_el1( control );
0691        break;
0692      case 10:
0693        _AArch64_Write_dbgbcr10_el1( control );
0694        break;
0695      case 11:
0696        _AArch64_Write_dbgbcr11_el1( control );
0697        break;
0698      case 12:
0699        _AArch64_Write_dbgbcr12_el1( control );
0700        break;
0701      case 13:
0702        _AArch64_Write_dbgbcr13_el1( control );
0703        break;
0704      case 14:
0705        _AArch64_Write_dbgbcr14_el1( control );
0706        break;
0707      case 15:
0708        _AArch64_Write_dbgbcr15_el1( control );
0709        break;
0710     }
0711   }
0712 }
0713 
0714 static void aarch64_debug_break_write_value( int bp, uint64_t value )
0715 {
0716   if ( bp < 15 ) {
0717     switch ( bp ) {
0718      case 0:
0719        _AArch64_Write_dbgbvr0_el1( value );
0720        break;
0721      case 1:
0722        _AArch64_Write_dbgbvr1_el1( value );
0723        break;
0724      case 2:
0725        _AArch64_Write_dbgbvr2_el1( value );
0726        break;
0727      case 3:
0728        _AArch64_Write_dbgbvr3_el1( value );
0729        break;
0730      case 4:
0731        _AArch64_Write_dbgbvr4_el1( value );
0732        break;
0733      case 5:
0734        _AArch64_Write_dbgbvr5_el1( value );
0735        break;
0736      case 6:
0737        _AArch64_Write_dbgbvr6_el1( value );
0738        break;
0739      case 7:
0740        _AArch64_Write_dbgbvr7_el1( value );
0741        break;
0742      case 8:
0743        _AArch64_Write_dbgbvr8_el1( value );
0744        break;
0745      case 9:
0746        _AArch64_Write_dbgbvr9_el1( value );
0747        break;
0748      case 10:
0749        _AArch64_Write_dbgbvr10_el1( value );
0750        break;
0751      case 11:
0752        _AArch64_Write_dbgbvr11_el1( value );
0753        break;
0754      case 12:
0755        _AArch64_Write_dbgbvr12_el1( value );
0756        break;
0757      case 13:
0758        _AArch64_Write_dbgbvr13_el1( value );
0759        break;
0760      case 14:
0761        _AArch64_Write_dbgbvr14_el1( value );
0762        break;
0763      case 15:
0764        _AArch64_Write_dbgbvr15_el1( value );
0765        break;
0766     }
0767   }
0768 }
0769 
0770 static inline void aarch64_debug_break_setup(
0771   uint8_t  index,
0772   uint64_t address
0773 )
0774 {
0775   aarch64_debug_hwbreak *bp = &hw_breaks[ index ];
0776 
0777   bp->control = AARCH64_HW_BP_TYPE_UNLINKED_INSTR_MISMATCH |
0778                 AARCH64_HW_BP_BAS_A64 |
0779                 AARCH64_HW_BP_PRIV_EL1 |
0780                 AARCH64_HW_BP_ENABLE;
0781   uint64_t address_mask = 0x3;
0782 
0783   bp->value = (intptr_t) ( address & ~address_mask );
0784   aarch64_debug_break_write_value( index, bp->value );
0785   aarch64_debug_break_write_control( index, bp->control );
0786 }
0787 
0788 static void aarch64_debug_break_clear( void )
0789 {
0790   rtems_interrupt_lock_context lock_context;
0791   aarch64_debug_hwbreak       *bp = &hw_breaks[ 0 ];
0792   int                          i;
0793 
0794   rtems_interrupt_lock_acquire( &target_lock, &lock_context );
0795 
0796   for ( i = 0; i < hw_breakpoints; ++i, ++bp ) {
0797     bp->enabled = false;
0798     bp->loaded = false;
0799   }
0800 
0801   rtems_interrupt_lock_release( &target_lock, &lock_context );
0802 }
0803 
0804 static void aarch64_debug_break_load( void )
0805 {
0806   rtems_interrupt_lock_context lock_context;
0807   aarch64_debug_hwbreak       *bp = &hw_breaks[ 0 ];
0808   int                          i;
0809 
0810   rtems_interrupt_lock_acquire( &target_lock, &lock_context );
0811 
0812   if ( bp->enabled && !bp->loaded ) {
0813     aarch64_debug_set_context_id( 0xdead1111 );
0814     aarch64_debug_break_write_value( 0, bp->value );
0815     aarch64_debug_break_write_control( 0, bp->control );
0816   }
0817 
0818   ++bp;
0819 
0820   for ( i = 1; i < hw_breakpoints; ++i, ++bp ) {
0821     if ( bp->enabled && !bp->loaded ) {
0822       bp->loaded = true;
0823       aarch64_debug_break_write_value( i, bp->value );
0824       aarch64_debug_break_write_control( i, bp->control );
0825     }
0826   }
0827 
0828   rtems_interrupt_lock_release( &target_lock, &lock_context );
0829 }
0830 
0831 static void aarch64_debug_break_unload( void )
0832 {
0833   rtems_interrupt_lock_context lock_context;
0834   aarch64_debug_hwbreak       *bp = &hw_breaks[ 0 ];
0835   int                          i;
0836 
0837   rtems_interrupt_lock_acquire( &target_lock, &lock_context );
0838   aarch64_debug_set_context_id( 0 );
0839 
0840   for ( i = 0; i < hw_breakpoints; ++i, ++bp ) {
0841     bp->loaded = false;
0842     aarch64_debug_break_write_control( i, 0 );
0843   }
0844 
0845   rtems_interrupt_lock_release( &target_lock, &lock_context );
0846 }
0847 
0848 static void aarch64_debug_break_dump( void )
0849 {
0850 #if TARGET_DEBUG
0851   aarch64_debug_hwbreak *bp = &hw_breaks[ 0 ];
0852   int                    i;
0853 
0854   for ( i = 0; i < hw_breakpoints; ++i, ++bp ) {
0855     if ( bp->enabled ) {
0856       target_printk(
0857         "[} bp: %d: control: %016" PRIx64 " addr: %016" PRIxPTR "\n",
0858         i,
0859         bp->control,
0860         (uintptr_t) bp->value
0861       );
0862     }
0863   }
0864 
0865 #endif
0866 }
0867 #endif
0868 
0869 static void aarch64_debug_disable_interrupts( void )
0870 {
0871   __asm__ volatile ( "msr DAIFSet, #0x2" );
0872 }
0873 
0874 static void aarch64_debug_enable_interrupts( void )
0875 {
0876   __asm__ volatile ( "msr DAIFClr, #2\n" );
0877 }
0878 
0879 static void aarch64_debug_disable_debug_exceptions( void )
0880 {
0881   __asm__ volatile ( "msr DAIFSet, #0x8" );
0882 }
0883 
0884 static inline void aarch64_debug_set_context_id( const uint32_t id )
0885 {
0886   _AArch64_Write_contextidr_el1( id );
0887 }
0888 
0889 int rtems_debugger_target_configure( rtems_debugger_target *target )
0890 {
0891   target->capabilities = ( RTEMS_DEBUGGER_TARGET_CAP_SWBREAK );
0892   target->reg_num = RTEMS_DEBUGGER_NUMREGS;
0893   target->reg_offset = aarch64_reg_offsets;
0894   target->breakpoint = &breakpoint[ 0 ];
0895   target->breakpoint_size = sizeof( breakpoint );
0896   return aarch64_debug_probe( target );
0897 }
0898 
0899 static void target_print_frame( CPU_Exception_frame *frame )
0900 {
0901   EXC_FRAME_PRINT( target_printk, "[} ", frame );
0902 }
0903 
0904 /* returns true if cascade is required */
0905 static bool target_exception( CPU_Exception_frame *frame )
0906 {
0907   target_printk(
0908     "[} > frame = %016" PRIxPTR \
0909     " sig=%d" \
0910     " pra=%016" PRIxPTR "\n" \
0911     "[} >   esr=%016" PRIx64 \
0912     " far=%016" PRIxPTR "\n",
0913     (uintptr_t) frame,
0914     rtems_debugger_target_exception_to_signal( frame ),
0915     (uintptr_t) frame->register_pc,
0916     (uint64_t) frame->register_syndrome,
0917     (uintptr_t) frame->register_fault_address
0918   );
0919 
0920   target_print_frame( frame );
0921 
0922   switch ( rtems_debugger_target_exception( frame ) ) {
0923    case rtems_debugger_target_exc_consumed:
0924    default:
0925      break;
0926    case rtems_debugger_target_exc_step:
0927      break;
0928    case rtems_debugger_target_exc_cascade:
0929      target_printk( "rtems-db: unhandled exception: cascading\n" );
0930      /* Continue in fatal error handler chain */
0931      return true;
0932      break;
0933   }
0934 
0935   target_printk(
0936     "[} < resuming frame = %016" PRIxPTR "\n",
0937     (uintptr_t) frame
0938   );
0939   target_print_frame( frame );
0940 
0941 #if TARGET_DEBUG
0942   uint64_t mdscr = _AArch64_Read_mdscr_el1();
0943 #endif
0944   target_printk(
0945     "[} global stepping: %s\n",
0946     mdscr & AARCH64_MDSCR_EL1_SS ? "yes" : "no"
0947   );
0948   target_printk(
0949     "[} kernel self-debug: %s\n",
0950     mdscr & AARCH64_MDSCR_EL1_KDE ? "yes" : "no"
0951   );
0952   target_printk(
0953     "[} non-step/non-BRK debug events: %s\n",
0954     mdscr & AARCH64_MDSCR_EL1_MDE ? "yes" : "no"
0955   );
0956   target_printk(
0957     "[} OSLSR(should be 0x8): 0x%016" PRIx64 "\n",
0958     _AArch64_Read_oslsr_el1()
0959   );
0960 #ifdef HARDWARE_BREAKPOINTS_NOT_USED
0961   aarch64_debug_break_dump();
0962 #endif
0963   return false;
0964 }
0965 
0966 #define xstr( a ) str( a )
0967 #define str( a ) #a
0968 #define FRAME_SIZE_STR xstr( AARCH64_EXCEPTION_FRAME_SIZE )
0969 
0970 /*
0971  * This block of assembly must have a target branch function because GCC
0972  * requires that SP not accumulate changes across an ASM block. Instead of
0973  * changing the SP, we branch to a new function and never return since it was
0974  * never going to return anyway.
0975  */
0976 #define SWITCH_STACKS_AND_ALLOC( new_mode, old_frame, jump_target )                              \
0977   __asm__ volatile (                                                                            \
0978   "msr spsel, #" new_mode "\n"                         /* switch to thread stack */            \
0979   "sub sp, sp, #" FRAME_SIZE_STR "\n"   /* reserve space for CEF */             \
0980   "mov x0, sp\n"                                       /* Set x0 to the new exception frame */ \
0981   "mov x1, %[old_frame]\n"                             /* Set x1 to the old exception frame */ \
0982   "b " #jump_target "\n"                               /* Jump to the specified function */    \
0983   :                                                                                          \
0984   : [ old_frame ] "r" ( old_frame )                                                              \
0985   : "x0", "x1" )
0986 
0987 #define SWITCH_STACKS_AND_ALLOC_WITH_CASCADE( new_mode, app_frame, \
0988                                               jump_target )                 \
0989   __asm__ volatile (                                                                            \
0990   "msr spsel, #" new_mode "\n"                         /* switch to thread stack */            \
0991   "sub sp, sp, #" FRAME_SIZE_STR "\n"   /* reserve space for CEF */             \
0992   "mov x0, sp\n"                                       /* Set x0 to the new exception frame */ \
0993   "mov x1, %[app_frame]\n"                             /* Set x1 to the old exception frame */ \
0994   "mov x2, %[needs_cascade]\n"                         /* pass on whether cascade is needed */ \
0995   "b " #jump_target "\n"                               /* Jump to the specified function */    \
0996   :                                                                                          \
0997   : [ app_frame ] "r" ( app_frame ),                                                             \
0998   [ needs_cascade ] "r" ( needs_cascade )                                                      \
0999   : "x0", "x1" )
1000 
1001 /*
1002  * This block does not have an overall effect on SP since the spsel mode change
1003  * preserves the original SP
1004  */
1005 #define DROP_OLD_FRAME( old_frame, old_mode, new_mode )                                                 \
1006   __asm__ volatile (                                                                                   \
1007   "msr spsel, #" old_mode "\n"                         /* switch to exception stack */                \
1008   "mov sp, %0\n"                                       /* Reset SP to the beginning of the CEF */     \
1009   "add sp, sp, #" FRAME_SIZE_STR "\n"   /* release space for CEF on exception stack */ \
1010   "msr spsel, #" new_mode "\n"                         /* switch to thread stack */                   \
1011   :                                                                                                 \
1012   : "r" ( old_frame ) )                                                                             \
1013 
1014 #define THREAD_MODE "1"
1015 #define EXCEPTION_MODE "0"
1016 
1017 void target_exception_stack_stage_3(
1018   CPU_Exception_frame *exc_frame,
1019   CPU_Exception_frame *app_frame,
1020   bool                 needs_cascade
1021 );
1022 
1023 void target_exception_stack_stage_3(
1024   CPU_Exception_frame *exc_frame,
1025   CPU_Exception_frame *app_frame,
1026   bool                 needs_cascade
1027 )
1028 {
1029   _AArch64_Exception_frame_copy( exc_frame, app_frame );
1030   DROP_OLD_FRAME( app_frame, THREAD_MODE, EXCEPTION_MODE );
1031 
1032   if ( needs_cascade ) {
1033     /* does not return */
1034     _AArch64_Exception_default( exc_frame );
1035   }
1036 
1037   /* does not return */
1038   _CPU_Exception_resume( exc_frame );
1039 }
1040 
1041 void target_exception_stack_stage_2(
1042   CPU_Exception_frame *app_frame,
1043   CPU_Exception_frame *exc_frame
1044 );
1045 
1046 void target_exception_stack_stage_2(
1047   CPU_Exception_frame *app_frame,
1048   CPU_Exception_frame *exc_frame
1049 )
1050 {
1051   _AArch64_Exception_frame_copy( app_frame, exc_frame );
1052   DROP_OLD_FRAME( exc_frame, EXCEPTION_MODE, THREAD_MODE );
1053   /* breakpoints must be disabled here since other tasks could run that don't have debug masked */
1054 #ifdef HARDWARE_BREAKPOINTS_NOT_USED
1055   aarch64_debug_break_unload();
1056 #endif
1057   /* enable interrupts here to allow this thread to be suspended as necessary */
1058   aarch64_debug_enable_interrupts();
1059   bool needs_cascade = target_exception( app_frame );
1060 
1061   /* disable interrupts to return to normal operation */
1062   aarch64_debug_disable_interrupts();
1063   /* re-enable breakpoints disabled above */
1064 #ifdef HARDWARE_BREAKPOINTS_NOT_USED
1065   aarch64_debug_break_load();
1066 #endif
1067   SWITCH_STACKS_AND_ALLOC_WITH_CASCADE(
1068     EXCEPTION_MODE,
1069     app_frame,
1070     target_exception_stack_stage_3
1071   );
1072 }
1073 
1074 /* not allowed to return since it unwinds the stack */
1075 static void target_exception_thread_stack( CPU_Exception_frame *old_frame )
1076 {
1077   SWITCH_STACKS_AND_ALLOC(
1078     THREAD_MODE,
1079     old_frame,
1080     target_exception_stack_stage_2
1081   );
1082 }
1083 
1084 static void target_exception_application( CPU_Exception_frame *ef )
1085 {
1086   /* Continue in fatal error handler chain */
1087   if ( !debug_session_active ) {
1088     /* does not return */
1089     _AArch64_Exception_default( ef );
1090   }
1091 
1092   /*
1093    * Set CPSR.D to disable single-step operation, this will be cleared before
1094    * the thread is resumed if necessary.
1095    */
1096   ef->register_cpsr |= AARCH64_DSPSR_EL0_D;
1097 
1098   /*
1099    * Switching to the user stack is not possible if the stack pointer is bad.
1100    * This should be a relatively rare occurrance and signals a severe problem
1101    * with the application code or system.
1102    */
1103   if ( AARCH64_ESR_EL1_EC_GET( ef->register_syndrome ) == 0x26 ) {
1104     if ( target_exception( ef ) ) {
1105       /* does not return */
1106       _AArch64_Exception_default( ef );
1107     }
1108 
1109     /* does not return */
1110     _CPU_Exception_resume( ef );
1111   }
1112 
1113   target_exception_thread_stack( ef );
1114 }
1115 
1116 static void target_exception_kernel( CPU_Exception_frame *ef )
1117 {
1118   /*
1119    * If there is a stack alignment problem in exception mode, it really
1120    * shouldn't happen and execution won't even make it this far.
1121    */
1122   if ( !debug_session_active ) {
1123     /* does not return */
1124     _AArch64_Exception_default( ef );
1125   }
1126 
1127   /*
1128    * Set CPSR.D to disable single-step operation, this will be cleared before
1129    * the thread is resumed if necessary.
1130    */
1131   ef->register_cpsr |= AARCH64_DSPSR_EL0_D;
1132 
1133   if ( target_exception( ef ) ) {
1134     /* does not return */
1135     _AArch64_Exception_default( ef );
1136   }
1137 
1138   /* does not return */
1139   _CPU_Exception_resume( ef );
1140 }
1141 
1142 static void rtems_debugger_target_set_vectors( void )
1143 {
1144   /* Set vectors for both application and kernel modes */
1145   AArch64_set_exception_handler(
1146     AARCH64_EXCEPTION_SPx_SYNCHRONOUS,
1147     (void *) target_exception_application
1148   );
1149   AArch64_set_exception_handler(
1150     AARCH64_EXCEPTION_SP0_SYNCHRONOUS,
1151     (void *) target_exception_kernel
1152   );
1153 }
1154 
1155 static bool rtems_debugger_is_int_reg( size_t reg )
1156 {
1157   const size_t size = aarch64_reg_offsets[ reg + 1 ] -
1158                       aarch64_reg_offsets[ reg ];
1159 
1160   return size == RTEMS_DEBUGGER_REG_BYTES;
1161 }
1162 
1163 static void rtems_debugger_set_int_reg(
1164   rtems_debugger_thread *thread,
1165   size_t                 reg,
1166   const uint64_t         value
1167 )
1168 {
1169   const size_t offset = aarch64_reg_offsets[ reg ];
1170 
1171   memcpy( &thread->registers[ offset ], &value, sizeof( uint64_t ) );
1172 }
1173 
1174 static const uint64_t rtems_debugger_get_int_reg(
1175   rtems_debugger_thread *thread,
1176   size_t                 reg
1177 )
1178 {
1179   const size_t offset = aarch64_reg_offsets[ reg ];
1180   uint64_t     value;
1181 
1182   memcpy( &value, &thread->registers[ offset ], sizeof( uint64_t ) );
1183   return value;
1184 }
1185 
1186 static void rtems_debugger_set_halfint_reg(
1187   rtems_debugger_thread *thread,
1188   size_t                 reg,
1189   const uint32_t         value
1190 )
1191 {
1192   const size_t offset = aarch64_reg_offsets[ reg ];
1193 
1194   memcpy( &thread->registers[ offset ], &value, sizeof( uint32_t ) );
1195 }
1196 
1197 static const uint32_t rtems_debugger_get_halfint_reg(
1198   rtems_debugger_thread *thread,
1199   size_t                 reg
1200 )
1201 {
1202   const size_t offset = aarch64_reg_offsets[ reg ];
1203   uint32_t     value;
1204 
1205   memcpy( &value, &thread->registers[ offset ], sizeof( uint32_t ) );
1206   return value;
1207 }
1208 
1209 static void rtems_debugger_set_fp_reg(
1210   rtems_debugger_thread *thread,
1211   size_t                 reg,
1212   const uint128_t        value
1213 )
1214 {
1215   const size_t offset = aarch64_reg_offsets[ reg ];
1216 
1217   memcpy( &thread->registers[ offset ], &value, sizeof( uint128_t ) );
1218 }
1219 
1220 static const uint128_t rtems_debugger_get_fp_reg(
1221   rtems_debugger_thread *thread,
1222   size_t                 reg
1223 )
1224 {
1225   const size_t offset = aarch64_reg_offsets[ reg ];
1226   uint128_t    value;
1227 
1228   memcpy( &value, &thread->registers[ offset ], sizeof( uint128_t ) );
1229   return value;
1230 }
1231 
1232 static rtems_status_code rtems_debugger_target_set_text_writable(
1233   bool writable
1234 )
1235 {
1236   uintptr_t         start_begin = (uintptr_t) bsp_section_start_begin;
1237   uintptr_t         start_end = (uintptr_t) bsp_section_start_end;
1238   uintptr_t         text_begin = (uintptr_t) bsp_section_text_begin;
1239   uintptr_t         text_end = (uintptr_t) bsp_section_text_end;
1240   uintptr_t         fast_text_begin = (uintptr_t) bsp_section_fast_text_begin;
1241   uintptr_t         fast_text_end = (uintptr_t) bsp_section_fast_text_end;
1242   uint64_t          mmu_flags = AARCH64_MMU_CODE_RW_CACHED;
1243   rtems_status_code sc;
1244 
1245   if ( !writable ) {
1246     mmu_flags = AARCH64_MMU_CODE_CACHED;
1247   }
1248 
1249   target_printk(
1250     "[} MMU edit: start_begin: 0x%016" PRIxPTR
1251     " start_end: 0x%016" PRIxPTR "\n",
1252     start_begin,
1253     start_end
1254   );
1255   sc = aarch64_mmu_map(
1256     start_begin,
1257     start_end - start_begin,
1258     mmu_flags
1259   );
1260 
1261   if ( sc != RTEMS_SUCCESSFUL ) {
1262     target_printk( "[} MMU edit failed\n" );
1263     return sc;
1264   }
1265 
1266   target_printk(
1267     "[} MMU edit: text_begin: 0x%016" PRIxPTR
1268     " text_end: 0x%016" PRIxPTR "\n",
1269     text_begin,
1270     text_end
1271   );
1272   sc = aarch64_mmu_map(
1273     text_begin,
1274     text_end - text_begin,
1275     mmu_flags
1276   );
1277 
1278   if ( sc != RTEMS_SUCCESSFUL ) {
1279     target_printk( "[} MMU edit failed\n" );
1280     return sc;
1281   }
1282 
1283   target_printk(
1284     "[} MMU edit: fast_text_begin: 0x%016" PRIxPTR
1285     " fast_text_end: 0x%016" PRIxPTR "\n",
1286     fast_text_begin,
1287     fast_text_end
1288   );
1289   sc = aarch64_mmu_map(
1290     fast_text_begin,
1291     fast_text_end - fast_text_begin,
1292     mmu_flags
1293   );
1294 
1295   if ( sc != RTEMS_SUCCESSFUL ) {
1296     target_printk( "[} MMU edit failed\n" );
1297   }
1298 
1299   return sc;
1300 }
1301 
1302 static rtems_task setup_debugger_on_cpu( rtems_task_argument arg )
1303 {
1304   rtems_status_code            sc;
1305   rtems_status_code           *init_error = (rtems_status_code *) arg;
1306   rtems_interrupt_lock_context lock_context;
1307 
1308   rtems_interrupt_lock_acquire( &target_lock, &lock_context );
1309   sc = rtems_debugger_target_set_text_writable( true );
1310 
1311   if ( sc != RTEMS_SUCCESSFUL ) {
1312     *init_error = sc;
1313   }
1314 
1315   rtems_debugger_target_set_vectors();
1316 
1317   /* enable single-step debugging */
1318   uint64_t mdscr = _AArch64_Read_mdscr_el1();
1319 
1320   mdscr |= AARCH64_MDSCR_EL1_SS;
1321   mdscr |= AARCH64_MDSCR_EL1_KDE;
1322   mdscr |= AARCH64_MDSCR_EL1_MDE;
1323   _AArch64_Write_mdscr_el1( mdscr );
1324 
1325   /* clear the OS lock */
1326   _AArch64_Write_oslar_el1( 0 );
1327   rtems_interrupt_lock_release( &target_lock, &lock_context );
1328 }
1329 
1330 int rtems_debugger_target_enable( void )
1331 {
1332   rtems_status_code sc;
1333   rtems_status_code init_error = RTEMS_SUCCESSFUL;
1334 
1335   debug_session_active = true;
1336 #ifdef HARDWARE_BREAKPOINTS_NOT_USED
1337   aarch64_debug_break_unload();
1338   aarch64_debug_break_clear();
1339 #endif
1340   aarch64_debug_disable_debug_exceptions();
1341   sc = run_across_cpus(
1342     setup_debugger_on_cpu,
1343     ( rtems_task_argument ) & init_error
1344   );
1345 
1346   if ( init_error != RTEMS_SUCCESSFUL ) {
1347     return init_error;
1348   }
1349 
1350   return sc;
1351 }
1352 
1353 static rtems_task teardown_debugger_on_cpu( rtems_task_argument arg )
1354 {
1355   rtems_status_code            sc;
1356   rtems_status_code           *deinit_error = (rtems_status_code *) arg;
1357   rtems_interrupt_lock_context lock_context;
1358 
1359   rtems_interrupt_lock_acquire( &target_lock, &lock_context );
1360   sc = rtems_debugger_target_set_text_writable( false );
1361 
1362   if ( sc != RTEMS_SUCCESSFUL ) {
1363     *deinit_error = sc;
1364   }
1365 
1366   /* disable single-step debugging */
1367   uint64_t mdscr = _AArch64_Read_mdscr_el1();
1368 
1369   mdscr &= ~AARCH64_MDSCR_EL1_SS;
1370   mdscr &= ~AARCH64_MDSCR_EL1_KDE;
1371   mdscr &= ~AARCH64_MDSCR_EL1_MDE;
1372   _AArch64_Write_mdscr_el1( mdscr );
1373 
1374   rtems_interrupt_lock_release( &target_lock, &lock_context );
1375 }
1376 
1377 int rtems_debugger_target_disable( void )
1378 {
1379   rtems_status_code sc;
1380   rtems_status_code deinit_error = RTEMS_SUCCESSFUL;
1381 
1382   debug_session_active = false;
1383 #ifdef HARDWARE_BREAKPOINTS_NOT_USED
1384   aarch64_debug_break_unload();
1385   aarch64_debug_break_clear();
1386 #endif
1387   sc = run_across_cpus(
1388     teardown_debugger_on_cpu,
1389     ( rtems_task_argument ) & deinit_error
1390   );
1391 
1392   if ( deinit_error != RTEMS_SUCCESSFUL ) {
1393     return deinit_error;
1394   }
1395 
1396   return sc;
1397 }
1398 
1399 int rtems_debugger_target_read_regs( rtems_debugger_thread *thread )
1400 {
1401   if (
1402     !rtems_debugger_thread_flag(
1403       thread,
1404       RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID
1405     )
1406   ) {
1407     static const uintptr_t good_address = (uintptr_t) &good_address;
1408     int                    i;
1409 
1410     memset( &thread->registers[ 0 ], 0, RTEMS_DEBUGGER_NUMREGBYTES );
1411 
1412     /* set all integer register to a known valid address */
1413     for ( i = 0; i < RTEMS_DEBUGGER_NUMREGS; ++i ) {
1414       if ( rtems_debugger_is_int_reg( i ) ) {
1415         rtems_debugger_set_int_reg( thread, i, (uintptr_t) &good_address );
1416       }
1417     }
1418 
1419     if ( thread->frame ) {
1420       CPU_Exception_frame *frame = thread->frame;
1421 
1422       *( (CPU_Exception_frame *) thread->registers ) = *frame;
1423       rtems_debugger_set_int_reg( thread, REG_X0, frame->register_x0 );
1424       rtems_debugger_set_int_reg( thread, REG_X1, frame->register_x1 );
1425       rtems_debugger_set_int_reg( thread, REG_X2, frame->register_x2 );
1426       rtems_debugger_set_int_reg( thread, REG_X3, frame->register_x3 );
1427       rtems_debugger_set_int_reg( thread, REG_X4, frame->register_x4 );
1428       rtems_debugger_set_int_reg( thread, REG_X5, frame->register_x5 );
1429       rtems_debugger_set_int_reg( thread, REG_X6, frame->register_x6 );
1430       rtems_debugger_set_int_reg( thread, REG_X7, frame->register_x7 );
1431       rtems_debugger_set_int_reg( thread, REG_X8, frame->register_x8 );
1432       rtems_debugger_set_int_reg( thread, REG_X9, frame->register_x9 );
1433       rtems_debugger_set_int_reg( thread, REG_X10, frame->register_x10 );
1434       rtems_debugger_set_int_reg( thread, REG_X11, frame->register_x11 );
1435       rtems_debugger_set_int_reg( thread, REG_X12, frame->register_x12 );
1436       rtems_debugger_set_int_reg( thread, REG_X13, frame->register_x13 );
1437       rtems_debugger_set_int_reg( thread, REG_X14, frame->register_x14 );
1438       rtems_debugger_set_int_reg( thread, REG_X15, frame->register_x15 );
1439       rtems_debugger_set_int_reg( thread, REG_X16, frame->register_x16 );
1440       rtems_debugger_set_int_reg( thread, REG_X17, frame->register_x17 );
1441       rtems_debugger_set_int_reg( thread, REG_X18, frame->register_x18 );
1442       rtems_debugger_set_int_reg( thread, REG_X19, frame->register_x19 );
1443       rtems_debugger_set_int_reg( thread, REG_X20, frame->register_x20 );
1444       rtems_debugger_set_int_reg( thread, REG_X21, frame->register_x21 );
1445       rtems_debugger_set_int_reg( thread, REG_X22, frame->register_x22 );
1446       rtems_debugger_set_int_reg( thread, REG_X23, frame->register_x23 );
1447       rtems_debugger_set_int_reg( thread, REG_X24, frame->register_x24 );
1448       rtems_debugger_set_int_reg( thread, REG_X25, frame->register_x25 );
1449       rtems_debugger_set_int_reg( thread, REG_X26, frame->register_x26 );
1450       rtems_debugger_set_int_reg( thread, REG_X27, frame->register_x27 );
1451       rtems_debugger_set_int_reg( thread, REG_X28, frame->register_x28 );
1452       rtems_debugger_set_int_reg( thread, REG_FP, frame->register_fp );
1453       rtems_debugger_set_int_reg(
1454         thread,
1455         REG_LR,
1456         (intptr_t) frame->register_lr
1457       );
1458       rtems_debugger_set_int_reg(
1459         thread,
1460         REG_SP,
1461         (intptr_t) frame->register_sp
1462       );
1463       rtems_debugger_set_int_reg(
1464         thread,
1465         REG_PC,
1466         (intptr_t) frame->register_pc
1467       );
1468       /* GDB considers CPSR to be 32-bit because bits 63:32 are RES0 */
1469       rtems_debugger_set_halfint_reg(
1470         thread,
1471         REG_CPS,
1472         (uint32_t) frame->register_cpsr
1473       );
1474       rtems_debugger_set_fp_reg( thread, REG_V0, frame->register_q0 );
1475       rtems_debugger_set_fp_reg( thread, REG_V1, frame->register_q1 );
1476       rtems_debugger_set_fp_reg( thread, REG_V2, frame->register_q2 );
1477       rtems_debugger_set_fp_reg( thread, REG_V3, frame->register_q3 );
1478       rtems_debugger_set_fp_reg( thread, REG_V4, frame->register_q4 );
1479       rtems_debugger_set_fp_reg( thread, REG_V5, frame->register_q5 );
1480       rtems_debugger_set_fp_reg( thread, REG_V6, frame->register_q6 );
1481       rtems_debugger_set_fp_reg( thread, REG_V7, frame->register_q7 );
1482       rtems_debugger_set_fp_reg( thread, REG_V8, frame->register_q8 );
1483       rtems_debugger_set_fp_reg( thread, REG_V9, frame->register_q9 );
1484       rtems_debugger_set_fp_reg( thread, REG_V10, frame->register_q10 );
1485       rtems_debugger_set_fp_reg( thread, REG_V11, frame->register_q11 );
1486       rtems_debugger_set_fp_reg( thread, REG_V12, frame->register_q12 );
1487       rtems_debugger_set_fp_reg( thread, REG_V13, frame->register_q13 );
1488       rtems_debugger_set_fp_reg( thread, REG_V14, frame->register_q14 );
1489       rtems_debugger_set_fp_reg( thread, REG_V15, frame->register_q15 );
1490       rtems_debugger_set_fp_reg( thread, REG_V16, frame->register_q16 );
1491       rtems_debugger_set_fp_reg( thread, REG_V17, frame->register_q17 );
1492       rtems_debugger_set_fp_reg( thread, REG_V18, frame->register_q18 );
1493       rtems_debugger_set_fp_reg( thread, REG_V19, frame->register_q19 );
1494       rtems_debugger_set_fp_reg( thread, REG_V20, frame->register_q20 );
1495       rtems_debugger_set_fp_reg( thread, REG_V21, frame->register_q21 );
1496       rtems_debugger_set_fp_reg( thread, REG_V22, frame->register_q22 );
1497       rtems_debugger_set_fp_reg( thread, REG_V23, frame->register_q23 );
1498       rtems_debugger_set_fp_reg( thread, REG_V24, frame->register_q24 );
1499       rtems_debugger_set_fp_reg( thread, REG_V25, frame->register_q25 );
1500       rtems_debugger_set_fp_reg( thread, REG_V26, frame->register_q26 );
1501       rtems_debugger_set_fp_reg( thread, REG_V27, frame->register_q27 );
1502       rtems_debugger_set_fp_reg( thread, REG_V28, frame->register_q28 );
1503       rtems_debugger_set_fp_reg( thread, REG_V29, frame->register_q29 );
1504       rtems_debugger_set_fp_reg( thread, REG_V30, frame->register_q30 );
1505       rtems_debugger_set_fp_reg( thread, REG_V31, frame->register_q31 );
1506       /* GDB considers FPSR and FPCR to be 32-bit because bits 63:32 are RES0 */
1507       rtems_debugger_set_halfint_reg( thread, REG_FPS, frame->register_fpsr );
1508       rtems_debugger_set_halfint_reg( thread, REG_FPC, frame->register_fpcr );
1509       /*
1510        * Get the signal from the frame.
1511        */
1512       thread->signal = rtems_debugger_target_exception_to_signal( frame );
1513     } else {
1514       rtems_debugger_set_int_reg(
1515         thread,
1516         REG_X19,
1517         thread->tcb->Registers.register_x19
1518       );
1519       rtems_debugger_set_int_reg(
1520         thread,
1521         REG_X20,
1522         thread->tcb->Registers.register_x20
1523       );
1524       rtems_debugger_set_int_reg(
1525         thread,
1526         REG_X21,
1527         thread->tcb->Registers.register_x21
1528       );
1529       rtems_debugger_set_int_reg(
1530         thread,
1531         REG_X22,
1532         thread->tcb->Registers.register_x22
1533       );
1534       rtems_debugger_set_int_reg(
1535         thread,
1536         REG_X23,
1537         thread->tcb->Registers.register_x23
1538       );
1539       rtems_debugger_set_int_reg(
1540         thread,
1541         REG_X24,
1542         thread->tcb->Registers.register_x24
1543       );
1544       rtems_debugger_set_int_reg(
1545         thread,
1546         REG_X25,
1547         thread->tcb->Registers.register_x25
1548       );
1549       rtems_debugger_set_int_reg(
1550         thread,
1551         REG_X26,
1552         thread->tcb->Registers.register_x26
1553       );
1554       rtems_debugger_set_int_reg(
1555         thread,
1556         REG_X27,
1557         thread->tcb->Registers.register_x27
1558       );
1559       rtems_debugger_set_int_reg(
1560         thread,
1561         REG_X28,
1562         thread->tcb->Registers.register_x28
1563       );
1564       rtems_debugger_set_int_reg(
1565         thread,
1566         REG_FP,
1567         thread->tcb->Registers.register_fp
1568       );
1569       rtems_debugger_set_int_reg(
1570         thread,
1571         REG_LR,
1572         (intptr_t) thread->tcb->Registers.register_lr
1573       );
1574       rtems_debugger_set_int_reg(
1575         thread,
1576         REG_SP,
1577         (intptr_t) thread->tcb->Registers.register_sp
1578       );
1579       rtems_debugger_set_int_reg(
1580         thread,
1581         REG_PC,
1582         (intptr_t) thread->tcb->Registers.register_lr
1583       );
1584       rtems_debugger_set_int_reg(
1585         thread,
1586         REG_V8,
1587         thread->tcb->Registers.register_d8
1588       );
1589       rtems_debugger_set_int_reg(
1590         thread,
1591         REG_V9,
1592         thread->tcb->Registers.register_d9
1593       );
1594       rtems_debugger_set_int_reg(
1595         thread,
1596         REG_V10,
1597         thread->tcb->Registers.register_d10
1598       );
1599       rtems_debugger_set_int_reg(
1600         thread,
1601         REG_V11,
1602         thread->tcb->Registers.register_d11
1603       );
1604       rtems_debugger_set_int_reg(
1605         thread,
1606         REG_V12,
1607         thread->tcb->Registers.register_d12
1608       );
1609       rtems_debugger_set_int_reg(
1610         thread,
1611         REG_V13,
1612         thread->tcb->Registers.register_d13
1613       );
1614       rtems_debugger_set_int_reg(
1615         thread,
1616         REG_V14,
1617         thread->tcb->Registers.register_d14
1618       );
1619       rtems_debugger_set_int_reg(
1620         thread,
1621         REG_V15,
1622         thread->tcb->Registers.register_d15
1623       );
1624       /*
1625        * Blocked threads have no signal.
1626        */
1627       thread->signal = 0;
1628     }
1629 
1630     thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID;
1631     thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
1632   }
1633 
1634   return 0;
1635 }
1636 
1637 int rtems_debugger_target_write_regs( rtems_debugger_thread *thread )
1638 {
1639   if (
1640     rtems_debugger_thread_flag(
1641       thread,
1642       RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY
1643     )
1644   ) {
1645     /*
1646      * Only write to debugger controlled exception threads. Do not touch the
1647      * registers for threads blocked in the context switcher.
1648      */
1649     if (
1650       rtems_debugger_thread_flag(
1651         thread,
1652         RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION
1653       )
1654     ) {
1655       CPU_Exception_frame *frame = thread->frame;
1656       frame->register_x0 = rtems_debugger_get_int_reg( thread, REG_X0 );
1657       frame->register_x1 = rtems_debugger_get_int_reg( thread, REG_X1 );
1658       frame->register_x2 = rtems_debugger_get_int_reg( thread, REG_X2 );
1659       frame->register_x3 = rtems_debugger_get_int_reg( thread, REG_X3 );
1660       frame->register_x4 = rtems_debugger_get_int_reg( thread, REG_X4 );
1661       frame->register_x5 = rtems_debugger_get_int_reg( thread, REG_X5 );
1662       frame->register_x6 = rtems_debugger_get_int_reg( thread, REG_X6 );
1663       frame->register_x7 = rtems_debugger_get_int_reg( thread, REG_X7 );
1664       frame->register_x8 = rtems_debugger_get_int_reg( thread, REG_X8 );
1665       frame->register_x9 = rtems_debugger_get_int_reg( thread, REG_X9 );
1666       frame->register_x10 = rtems_debugger_get_int_reg( thread, REG_X10 );
1667       frame->register_x11 = rtems_debugger_get_int_reg( thread, REG_X11 );
1668       frame->register_x12 = rtems_debugger_get_int_reg( thread, REG_X12 );
1669       frame->register_x13 = rtems_debugger_get_int_reg( thread, REG_X13 );
1670       frame->register_x14 = rtems_debugger_get_int_reg( thread, REG_X14 );
1671       frame->register_x15 = rtems_debugger_get_int_reg( thread, REG_X15 );
1672       frame->register_x16 = rtems_debugger_get_int_reg( thread, REG_X16 );
1673       frame->register_x17 = rtems_debugger_get_int_reg( thread, REG_X17 );
1674       frame->register_x18 = rtems_debugger_get_int_reg( thread, REG_X18 );
1675       frame->register_x19 = rtems_debugger_get_int_reg( thread, REG_X19 );
1676       frame->register_x20 = rtems_debugger_get_int_reg( thread, REG_X20 );
1677       frame->register_x21 = rtems_debugger_get_int_reg( thread, REG_X21 );
1678       frame->register_x22 = rtems_debugger_get_int_reg( thread, REG_X22 );
1679       frame->register_x23 = rtems_debugger_get_int_reg( thread, REG_X23 );
1680       frame->register_x24 = rtems_debugger_get_int_reg( thread, REG_X24 );
1681       frame->register_x25 = rtems_debugger_get_int_reg( thread, REG_X25 );
1682       frame->register_x26 = rtems_debugger_get_int_reg( thread, REG_X26 );
1683       frame->register_x27 = rtems_debugger_get_int_reg( thread, REG_X27 );
1684       frame->register_x28 = rtems_debugger_get_int_reg( thread, REG_X28 );
1685       frame->register_fp = (uintptr_t) rtems_debugger_get_int_reg(
1686         thread,
1687         REG_FP
1688       );
1689       frame->register_lr = (void *) (uintptr_t) rtems_debugger_get_int_reg(
1690         thread,
1691         REG_LR
1692       );
1693       frame->register_sp = (uintptr_t) rtems_debugger_get_int_reg(
1694         thread,
1695         REG_SP
1696       );
1697       frame->register_pc = (void *) (uintptr_t) rtems_debugger_get_int_reg(
1698         thread,
1699         REG_PC
1700       );
1701       frame->register_cpsr = rtems_debugger_get_halfint_reg( thread, REG_CPS );
1702       frame->register_q0 = rtems_debugger_get_fp_reg( thread, REG_V0 );
1703       frame->register_q1 = rtems_debugger_get_fp_reg( thread, REG_V1 );
1704       frame->register_q2 = rtems_debugger_get_fp_reg( thread, REG_V2 );
1705       frame->register_q3 = rtems_debugger_get_fp_reg( thread, REG_V3 );
1706       frame->register_q4 = rtems_debugger_get_fp_reg( thread, REG_V4 );
1707       frame->register_q5 = rtems_debugger_get_fp_reg( thread, REG_V5 );
1708       frame->register_q6 = rtems_debugger_get_fp_reg( thread, REG_V6 );
1709       frame->register_q7 = rtems_debugger_get_fp_reg( thread, REG_V7 );
1710       frame->register_q8 = rtems_debugger_get_fp_reg( thread, REG_V8 );
1711       frame->register_q9 = rtems_debugger_get_fp_reg( thread, REG_V9 );
1712       frame->register_q10 = rtems_debugger_get_fp_reg( thread, REG_V10 );
1713       frame->register_q11 = rtems_debugger_get_fp_reg( thread, REG_V11 );
1714       frame->register_q12 = rtems_debugger_get_fp_reg( thread, REG_V12 );
1715       frame->register_q13 = rtems_debugger_get_fp_reg( thread, REG_V13 );
1716       frame->register_q14 = rtems_debugger_get_fp_reg( thread, REG_V14 );
1717       frame->register_q15 = rtems_debugger_get_fp_reg( thread, REG_V15 );
1718       frame->register_q16 = rtems_debugger_get_fp_reg( thread, REG_V16 );
1719       frame->register_q17 = rtems_debugger_get_fp_reg( thread, REG_V17 );
1720       frame->register_q18 = rtems_debugger_get_fp_reg( thread, REG_V18 );
1721       frame->register_q19 = rtems_debugger_get_fp_reg( thread, REG_V19 );
1722       frame->register_q20 = rtems_debugger_get_fp_reg( thread, REG_V20 );
1723       frame->register_q21 = rtems_debugger_get_fp_reg( thread, REG_V21 );
1724       frame->register_q22 = rtems_debugger_get_fp_reg( thread, REG_V22 );
1725       frame->register_q23 = rtems_debugger_get_fp_reg( thread, REG_V23 );
1726       frame->register_q24 = rtems_debugger_get_fp_reg( thread, REG_V24 );
1727       frame->register_q25 = rtems_debugger_get_fp_reg( thread, REG_V25 );
1728       frame->register_q26 = rtems_debugger_get_fp_reg( thread, REG_V26 );
1729       frame->register_q27 = rtems_debugger_get_fp_reg( thread, REG_V27 );
1730       frame->register_q28 = rtems_debugger_get_fp_reg( thread, REG_V28 );
1731       frame->register_q29 = rtems_debugger_get_fp_reg( thread, REG_V29 );
1732       frame->register_q30 = rtems_debugger_get_fp_reg( thread, REG_V30 );
1733       frame->register_q31 = rtems_debugger_get_fp_reg( thread, REG_V31 );
1734       frame->register_fpsr = rtems_debugger_get_halfint_reg( thread, REG_FPS );
1735       frame->register_fpcr = rtems_debugger_get_halfint_reg( thread, REG_FPC );
1736     }
1737 
1738     thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
1739   }
1740 
1741   return 0;
1742 }
1743 
1744 uintptr_t rtems_debugger_target_reg_pc( rtems_debugger_thread *thread )
1745 {
1746   int r;
1747 
1748   r = rtems_debugger_target_read_regs( thread );
1749 
1750   if ( r >= 0 ) {
1751     return rtems_debugger_get_int_reg( thread, REG_PC );
1752   }
1753 
1754   return 0;
1755 }
1756 
1757 uintptr_t rtems_debugger_target_frame_pc( CPU_Exception_frame *frame )
1758 {
1759   return (uintptr_t) frame->register_pc;
1760 }
1761 
1762 uintptr_t rtems_debugger_target_reg_sp( rtems_debugger_thread *thread )
1763 {
1764   int r;
1765 
1766   r = rtems_debugger_target_read_regs( thread );
1767 
1768   if ( r >= 0 ) {
1769     return rtems_debugger_get_int_reg( thread, REG_SP );
1770   }
1771 
1772   return 0;
1773 }
1774 
1775 uintptr_t rtems_debugger_target_tcb_sp( rtems_debugger_thread *thread )
1776 {
1777   return (uintptr_t) thread->tcb->Registers.register_sp;
1778 }
1779 
1780 int rtems_debugger_target_thread_stepping( rtems_debugger_thread *thread )
1781 {
1782   CPU_Exception_frame *frame = thread->frame;
1783 
1784   if ( rtems_debugger_thread_flag(
1785     thread,
1786     RTEMS_DEBUGGER_THREAD_FLAG_STEP_INSTR
1787        ) ) {
1788     /* Especially on first startup, frame isn't guaranteed to be non-NULL */
1789     if ( frame == NULL ) {
1790       return -1;
1791     }
1792 
1793     /*
1794      * Single stepping uses AArch64-specific single-step mode and does not
1795      * involve hardware breakpoints.
1796      */
1797 
1798     /* Breakpoint instruction exceptions occur even when D is not set. */
1799     uint64_t stepping_enabled =
1800       !( frame->register_cpsr & AARCH64_DSPSR_EL0_D );
1801 
1802     target_printk( "[} stepping: %s\n", stepping_enabled ? "yes" : "no" );
1803 
1804     /*
1805      * This field is unset by the CPU during the software step process and must
1806      * be set again each time the debugger needs to advance one instruction. If
1807      * this is not set each time, the software step exception will trigger
1808      * before executing an instruction.
1809      */
1810     frame->register_cpsr |= AARCH64_DSPSR_EL0_SS;
1811 
1812     if ( !stepping_enabled ) {
1813       /*
1814        * Clear CPSR.D to enable single-step operation. The debug mask flag is
1815        * set on taking an exception to prevent unwanted stepping. The way
1816        * single-stepping works will need to change if hardware breakpoints and
1817        * watchpoints are ever used.
1818        */
1819       frame->register_cpsr &= ~AARCH64_DSPSR_EL0_D;
1820     }
1821   }
1822 
1823   return 0;
1824 }
1825 
1826 int rtems_debugger_target_exception_to_signal( CPU_Exception_frame *frame )
1827 {
1828   uint64_t EC = AARCH64_ESR_EL1_EC_GET( frame->register_syndrome );
1829 
1830   switch ( EC ) {
1831     case 0x1:   /* WFI */
1832     case 0x7:   /* SVE/SIMD/FP */
1833     case 0xa:   /* LD64B/ST64B* */
1834     case 0x15:
1835     case 0x18:  /* MSR/MRS/system instruction */
1836     case 0x19:  /* SVE */
1837     case 0x31:
1838     case 0x33:
1839     case 0x35:
1840     case 0x3c:
1841       return RTEMS_DEBUGGER_SIGNAL_TRAP;
1842 
1843     case 0x2c:
1844       return RTEMS_DEBUGGER_SIGNAL_FPE;
1845 
1846     case 0x21:
1847     case 0x25:
1848       return RTEMS_DEBUGGER_SIGNAL_SEGV;
1849 
1850     default:
1851       /*
1852        * Covers unknown, SP/PC alignment, illegal execution state, and any new
1853        * exception classes that get added.
1854        */
1855       return RTEMS_DEBUGGER_SIGNAL_ILL;
1856   }
1857 }
1858 
1859 void rtems_debugger_target_exception_print( CPU_Exception_frame *frame )
1860 {
1861   EXC_FRAME_PRINT( rtems_debugger_printf, "", frame );
1862 }
1863 
1864 int rtems_debugger_target_hwbreak_insert( void )
1865 {
1866   /*
1867    * Do nothing, these are loaded elsewhere if needed.
1868    */
1869   return 0;
1870 }
1871 
1872 int rtems_debugger_target_hwbreak_remove( void )
1873 {
1874 #ifdef HARDWARE_BREAKPOINTS_NOT_USED
1875   aarch64_debug_break_unload();
1876 #endif
1877   return 0;
1878 }
1879 
1880 int rtems_debugger_target_hwbreak_control(
1881   rtems_debugger_target_watchpoint wp,
1882   bool                             insert,
1883   uintptr_t                        addr,
1884   DB_UINT                          kind
1885 )
1886 {
1887   /* To do. */
1888   return 0;
1889 }
1890 
1891 int rtems_debugger_target_cache_sync( rtems_debugger_target_swbreak *swbreak )
1892 {
1893   /*
1894    * Flush the data cache and invalidate the instruction cache.
1895    */
1896   rtems_cache_flush_multiple_data_lines(
1897     swbreak->address,
1898     sizeof( breakpoint )
1899   );
1900   rtems_cache_instruction_sync_after_code_change(
1901     swbreak->address,
1902     sizeof( breakpoint )
1903   );
1904   return 0;
1905 }