File indexing completed on 2025-05-11 08:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #define TARGET_DEBUG 0
0037
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041
0042 #include <errno.h>
0043 #include <inttypes.h>
0044 #include <stdlib.h>
0045
0046
0047 extern char bsp_section_text_begin[];
0048 extern char bsp_section_text_end[];
0049 extern char bsp_section_fast_text_begin[];
0050 extern char bsp_section_fast_text_end[];
0051
0052 #include <rtems.h>
0053 #include <rtems/score/cpu.h>
0054 #include <rtems/score/threadimpl.h>
0055 #include <rtems/score/userextimpl.h>
0056
0057 #include <rtems/debugger/rtems-debugger-bsp.h>
0058
0059 #include "rtems-debugger-target.h"
0060 #include "rtems-debugger-threads.h"
0061
0062 #if TARGET_DEBUG
0063 #include <rtems/bspIo.h>
0064 #endif
0065
0066
0067
0068
0069 #define RTEMS_DEBUGGER_NUMREGS 57
0070
0071
0072
0073
0074 #define RTEMS_DEBUGGER_REG_BYTES 4
0075
0076
0077 #define REG_R0 0
0078 #define REG_R1 1
0079 #define REG_R2 2
0080 #define REG_R3 3
0081 #define REG_R4 4
0082 #define REG_R5 5
0083 #define REG_R6 6
0084 #define REG_R7 7
0085 #define REG_R8 8
0086 #define REG_R9 9
0087 #define REG_R10 10
0088 #define REG_R11 11
0089 #define REG_R12 12
0090 #define REG_R13 13
0091 #define REG_R14 14
0092 #define REG_R15 15
0093 #define REG_R16 16
0094 #define REG_R17 17
0095 #define REG_R18 18
0096 #define REG_R19 19
0097 #define REG_R20 20
0098 #define REG_R21 21
0099 #define REG_R22 22
0100 #define REG_R23 23
0101 #define REG_R24 24
0102 #define REG_R25 25
0103 #define REG_R26 26
0104 #define REG_R27 27
0105 #define REG_R28 28
0106 #define REG_R29 29
0107 #define REG_R30 30
0108 #define REG_R31 31
0109 #define REG_PC 32
0110 #define REG_MS 33
0111 #define REG_EA 34
0112 #define REG_ES 35
0113 #define REG_FS 36
0114 #define REG_BT 37
0115 #define REG_PV0 38
0116 #define REG_PV1 39
0117 #define REG_PV2 40
0118 #define REG_PV3 41
0119 #define REG_PV4 42
0120 #define REG_PV5 43
0121 #define REG_PV6 44
0122 #define REG_PV7 45
0123 #define REG_PV8 46
0124 #define REG_PV9 47
0125 #define REG_PV10 48
0126 #define REG_PV11 49
0127 #define REG_ED 50
0128 #define REG_PID 51
0129 #define REG_ZP 52
0130 #define REG_TBLX 53
0131 #define REG_TBLSX 54
0132 #define REG_TBLLO 55
0133 #define REG_TBLHI 56
0134
0135
0136
0137
0138
0139
0140
0141
0142 static const size_t microblaze_reg_offsets[ RTEMS_DEBUGGER_NUMREGS + 1 ] = {
0143 REG_R0 * 4,
0144 REG_R1 * 4,
0145 REG_R2 * 4,
0146 REG_R3 * 4,
0147 REG_R4 * 4,
0148 REG_R5 * 4,
0149 REG_R6 * 4,
0150 REG_R7 * 4,
0151 REG_R8 * 4,
0152 REG_R9 * 4,
0153 REG_R10 * 4,
0154 REG_R11 * 4,
0155 REG_R12 * 4,
0156 REG_R13 * 4,
0157 REG_R14 * 4,
0158 REG_R15 * 4,
0159 REG_R16 * 4,
0160 REG_R17 * 4,
0161 REG_R18 * 4,
0162 REG_R19 * 4,
0163 REG_R20 * 4,
0164 REG_R21 * 4,
0165 REG_R22 * 4,
0166 REG_R23 * 4,
0167 REG_R24 * 4,
0168 REG_R25 * 4,
0169 REG_R26 * 4,
0170 REG_R27 * 4,
0171 REG_R28 * 4,
0172 REG_R29 * 4,
0173 REG_R30 * 4,
0174 REG_R31 * 4,
0175 REG_PC * 4,
0176 REG_MS * 4,
0177 REG_EA * 4,
0178 REG_ES * 4,
0179 REG_FS * 4,
0180 REG_BT * 4,
0181 REG_PV0 * 4,
0182 REG_PV1 * 4,
0183 REG_PV2 * 4,
0184 REG_PV3 * 4,
0185 REG_PV4 * 4,
0186 REG_PV5 * 4,
0187 REG_PV6 * 4,
0188 REG_PV7 * 4,
0189 REG_PV8 * 4,
0190 REG_PV9 * 4,
0191 REG_PV10 * 4,
0192 REG_PV11 * 4,
0193 REG_ED * 4,
0194 REG_PID * 4,
0195 REG_ZP * 4,
0196 REG_TBLX * 4,
0197 REG_TBLSX * 4,
0198 REG_TBLLO * 4,
0199 REG_TBLHI * 4,
0200
0201 REG_TBLHI * 4 + 4,
0202 };
0203
0204
0205
0206
0207 #define RTEMS_DEBUGGER_NUMREGBYTES \
0208 microblaze_reg_offsets[ RTEMS_DEBUGGER_NUMREGS ]
0209
0210
0211
0212
0213 #define EXC_FRAME_PRINT( _out, _prefix, _frame ) \
0214 do { \
0215 _out( \
0216 _prefix " R0 = 0x%08" PRIx32 " R1 = 0x%08" PRIx32 \
0217 " R2 = 0x%08" PRIx32 " R3 = 0x%08" PRIx32 "\n", \
0218 0, \
0219 _frame->r1, \
0220 _frame->r2, \
0221 _frame->r3 \
0222 ); \
0223 _out( \
0224 _prefix " R4 = 0x%08" PRIx32 " R5 = 0x%08" PRIx32 \
0225 " R6 = 0x%08" PRIx32 " R7 = 0x%08" PRIx32 "\n", \
0226 _frame->r4, \
0227 _frame->r5, \
0228 _frame->r6, \
0229 _frame->r7 \
0230 ); \
0231 _out( \
0232 _prefix " R8 = 0x%08" PRIx32 " R9 = 0x%08" PRIx32 \
0233 " R10 = 0x%08" PRIx32 " R11 = 0x%08" PRIx32 "\n", \
0234 _frame->r8, \
0235 _frame->r9, \
0236 _frame->r10, \
0237 _frame->r11 \
0238 ); \
0239 _out( \
0240 _prefix " R12 = 0x%08" PRIx32 " R13 = 0x%08" PRIx32 \
0241 " R14 = 0x%08" PRIxPTR " R15 = 0x%08" PRIxPTR "\n", \
0242 _frame->r12, \
0243 _frame->r13, \
0244 (uintptr_t) _frame->r14, \
0245 (uintptr_t) _frame->r15 \
0246 ); \
0247 _out( \
0248 _prefix " R16 = 0x%08" PRIxPTR " R17 = 0x%08" PRIxPTR \
0249 " R18 = 0x%08" PRIx32 " R19 = 0x%08" PRIx32 "\n", \
0250 (uintptr_t) _frame->r16, \
0251 (uintptr_t) _frame->r17, \
0252 _frame->r18, \
0253 _frame->r19 \
0254 ); \
0255 _out( \
0256 _prefix " R20 = 0x%08" PRIx32 " R21 = 0x%08" PRIx32 \
0257 " R22 = 0x%08" PRIx32 " R23 = 0x%08" PRIx32 "\n", \
0258 _frame->r20, \
0259 _frame->r21, \
0260 _frame->r22, \
0261 _frame->r23 \
0262 ); \
0263 _out( \
0264 _prefix " R24 = 0x%08" PRIx32 " R25 = 0x%08" PRIx32 \
0265 " R26 = 0x%08" PRIx32 " R27 = 0x%08" PRIx32 "\n", \
0266 _frame->r24, \
0267 _frame->r25, \
0268 _frame->r26, \
0269 _frame->r27 \
0270 ); \
0271 _out( \
0272 _prefix " R28 = 0x%08" PRIx32 " R29 = 0x%08" PRIx32 \
0273 " R30 = 0x%08" PRIxPTR " R31 = 0x%08" PRIxPTR "\n", \
0274 _frame->r28, \
0275 _frame->r29, \
0276 _frame->r30, \
0277 _frame->r31 \
0278 ); \
0279 _out( \
0280 _prefix " EAR = %p ESR = 0x%08" PRIx32 "\n", \
0281 _frame->ear, \
0282 _frame->esr \
0283 ); \
0284 _out( \
0285 _prefix " PC = %p\n", \
0286 _frame->r16 \
0287 ); \
0288 _out( \
0289 _prefix " MSR = 0x%08" PRIx32 " En:%c%c%c%c Prog:%c%c%c Mode:%c%c Arith:%c%c\n", \
0290 _frame->msr, \
0291 ( _frame->msr & MICROBLAZE_MSR_IE ) != 0 ? 'I' : '-', \
0292 ( _frame->msr & MICROBLAZE_MSR_ICE ) != 0 ? 'C' : '-', \
0293 ( _frame->msr & MICROBLAZE_MSR_DCE ) != 0 ? 'D' : '-', \
0294 ( _frame->msr & MICROBLAZE_MSR_EE ) != 0 ? 'E' : '-', \
0295 ( _frame->msr & MICROBLAZE_MSR_BIP ) != 0 ? 'B' : '-', \
0296 ( _frame->msr & MICROBLAZE_MSR_FSL ) != 0 ? 'F' : '-', \
0297 ( _frame->msr & MICROBLAZE_MSR_EIP ) != 0 ? 'E' : '-', \
0298 ( _frame->msr & MICROBLAZE_MSR_UM ) != 0 ? 'U' : '-', \
0299 ( _frame->msr & MICROBLAZE_MSR_VM ) != 0 ? 'V' : '-', \
0300 ( _frame->msr & MICROBLAZE_MSR_C ) != 0 ? 'C' : '-', \
0301 ( _frame->msr & MICROBLAZE_MSR_DZO ) != 0 ? 'Z' : '-' \
0302 ); \
0303 } while ( 0 )
0304
0305
0306
0307
0308
0309
0310 static const uint8_t breakpoint[ 4 ] = { 0xef, 0xbe, 0xad, 0xde };
0311
0312
0313
0314
0315 RTEMS_INTERRUPT_LOCK_DEFINE( static, target_lock, "target_lock" )
0316
0317
0318
0319
0320 static bool debug_session_active;
0321
0322
0323
0324
0325 static uint8_t hw_breakpoints;
0326 static uint8_t hw_read_watchpoints;
0327 static uint8_t hw_write_watchpoints;
0328
0329
0330 typedef struct {
0331 uint32_t *address;
0332 } microblaze_soft_step;
0333
0334 microblaze_soft_step next_soft_break = { 0 };
0335 microblaze_soft_step target_soft_break = { 0 };
0336
0337 static void set_soft_break(
0338 microblaze_soft_step *soft_break,
0339 uint32_t *next_ins
0340 )
0341 {
0342 soft_break->address = next_ins;
0343 rtems_debugger_target_swbreak_control(
0344 true,
0345 (uintptr_t) soft_break->address,
0346 4
0347 );
0348 }
0349
0350 static void restore_soft_step( microblaze_soft_step *bp )
0351 {
0352
0353
0354
0355
0356 if ( bp->address != NULL ) {
0357 rtems_debugger_target_swbreak_control( false, (uintptr_t) bp->address, 4 );
0358 }
0359
0360 bp->address = NULL;
0361 }
0362
0363
0364
0365
0366 #if TARGET_DEBUG
0367
0368 void rtems_debugger_printk_lock( rtems_interrupt_lock_context *lock_context );
0369
0370 void rtems_debugger_printk_unlock(
0371 rtems_interrupt_lock_context *lock_context
0372 );
0373
0374 static void target_printk( const char *format, ... ) RTEMS_PRINTFLIKE( 1, 2 );
0375
0376 static void target_printk( const char *format, ... )
0377 {
0378 rtems_interrupt_lock_context lock_context;
0379 va_list ap;
0380
0381 va_start( ap, format );
0382 rtems_debugger_printk_lock( &lock_context );
0383 vprintk( format, ap );
0384 rtems_debugger_printk_unlock( &lock_context );
0385 va_end( ap );
0386 }
0387
0388 #else
0389 #define target_printk( _fmt, ... )
0390 #endif
0391
0392 static int microblaze_debug_probe( rtems_debugger_target *target )
0393 {
0394 uint32_t msr;
0395 uint32_t pvr0;
0396 uint32_t pvr3;
0397 const char *version = NULL;
0398
0399 rtems_debugger_printf(
0400 "rtems-db: MicroBlaze\n"
0401 );
0402
0403 _CPU_MSR_GET( msr );
0404
0405 if ( ( msr & MICROBLAZE_MSR_PVR ) == 0 ) {
0406 rtems_debugger_printf(
0407 "rtems-db: Processor Version Registers not supported\n"
0408 );
0409 return 0;
0410 }
0411
0412 _CPU_PVR0_GET( pvr0 );
0413
0414 switch ( MICROBLAZE_PVR0_VERSION_GET( pvr0 ) ) {
0415 case 0x1:
0416 version = "v5.00.a";
0417 break;
0418 case 0x2:
0419 version = "v5.00.b";
0420 break;
0421 case 0x3:
0422 version = "v5.00.c";
0423 break;
0424 case 0x4:
0425 version = "v6.00.a";
0426 break;
0427 case 0x5:
0428 version = "v7.00.a";
0429 break;
0430 case 0x6:
0431 version = "v6.00.b";
0432 break;
0433 case 0x7:
0434 version = "v7.00.b";
0435 break;
0436 case 0x8:
0437 version = "v7.10.a";
0438 break;
0439 }
0440
0441 rtems_debugger_printf(
0442 "rtems-db: Version: %s (%d)\n",
0443 version,
0444 MICROBLAZE_PVR0_VERSION_GET( pvr0 )
0445 );
0446
0447
0448 if ( ( pvr0 >> 31 ) == 0 ) {
0449 rtems_debugger_printf(
0450 "rtems-db: Further Processor Version Registers not supported\n"
0451 );
0452 return 0;
0453 }
0454
0455 _CPU_PVR3_GET( pvr3 );
0456
0457 hw_breakpoints = MICROBLAZE_PVR3_BP_GET( pvr3 );
0458 hw_read_watchpoints = MICROBLAZE_PVR3_RWP_GET( pvr3 );
0459 hw_write_watchpoints = MICROBLAZE_PVR3_WWP_GET( pvr3 );
0460
0461 rtems_debugger_printf(
0462 "rtems-db: breakpoints:%" PRIu32
0463 " read watchpoints:%" PRIu32 " write watchpoints:%" PRIu32 "\n",
0464 hw_breakpoints,
0465 hw_read_watchpoints,
0466 hw_write_watchpoints
0467 );
0468
0469 return 0;
0470 }
0471
0472 int rtems_debugger_target_configure( rtems_debugger_target *target )
0473 {
0474 target->capabilities = ( RTEMS_DEBUGGER_TARGET_CAP_SWBREAK
0475 | RTEMS_DEBUGGER_TARGET_CAP_PURE_SWBREAK );
0476 target->reg_num = RTEMS_DEBUGGER_NUMREGS;
0477 target->reg_offset = microblaze_reg_offsets;
0478 target->breakpoint = &breakpoint[ 0 ];
0479 target->breakpoint_size = sizeof( breakpoint );
0480 return microblaze_debug_probe( target );
0481 }
0482
0483 static void target_print_frame( CPU_Exception_frame *frame )
0484 {
0485 EXC_FRAME_PRINT( target_printk, "[} ", frame );
0486 }
0487
0488
0489 static bool target_exception( CPU_Exception_frame *frame )
0490 {
0491 target_print_frame( frame );
0492
0493 switch ( rtems_debugger_target_exception( frame ) ) {
0494 case rtems_debugger_target_exc_consumed:
0495 default:
0496 break;
0497 case rtems_debugger_target_exc_step:
0498 break;
0499 case rtems_debugger_target_exc_cascade:
0500 target_printk( "rtems-db: unhandled exception: cascading\n" );
0501
0502 return true;
0503 }
0504
0505 target_printk(
0506 "[} < resuming frame = %016" PRIxPTR "\n",
0507 (uintptr_t) frame
0508 );
0509 target_print_frame( frame );
0510
0511 return false;
0512 }
0513
0514 static void target_exception_handler( CPU_Exception_frame *ef )
0515 {
0516 if ( debug_session_active == false ) {
0517
0518 return;
0519 }
0520
0521
0522
0523
0524
0525
0526
0527 ef->r17 = &ef->r17[ -1 ];
0528
0529
0530
0531
0532
0533 restore_soft_step( &next_soft_break );
0534 restore_soft_step( &target_soft_break );
0535
0536
0537 rtems_debugger_target_swbreak_remove();
0538
0539 if ( target_exception( ef ) == true ) {
0540
0541 ef->r17 = &ef->r17[ 1 ];
0542
0543
0544 return;
0545 }
0546
0547
0548 rtems_debugger_target_swbreak_insert();
0549
0550
0551 _CPU_Exception_resume( ef );
0552 }
0553
0554 static void rtems_debugger_set_int_reg(
0555 rtems_debugger_thread *thread,
0556 size_t reg,
0557 const uint32_t value
0558 )
0559 {
0560 const size_t offset = microblaze_reg_offsets[ reg ];
0561
0562 memcpy( &thread->registers[ offset ], &value, sizeof( uint32_t ) );
0563 }
0564
0565 static const uint32_t rtems_debugger_get_int_reg(
0566 rtems_debugger_thread *thread,
0567 size_t reg
0568 )
0569 {
0570 const size_t offset = microblaze_reg_offsets[ reg ];
0571 uint32_t value;
0572
0573 memcpy( &value, &thread->registers[ offset ], sizeof( uint32_t ) );
0574 return value;
0575 }
0576
0577 static bool tid_is_excluded( const rtems_id tid )
0578 {
0579 rtems_debugger_threads *threads = rtems_debugger->threads;
0580 rtems_id *excludes;
0581 size_t i;
0582
0583 excludes = rtems_debugger_thread_excludes( threads );
0584
0585 for ( i = 0; i < threads->excludes.level; ++i ) {
0586 if ( tid == excludes[ i ] ) {
0587 return true;
0588 }
0589 }
0590
0591
0592 char name[ RTEMS_DEBUGGER_THREAD_NAME_SIZE ];
0593
0594 rtems_object_get_name( tid, sizeof( name ), (char *) &name[ 0 ] );
0595
0596 if ( strcmp( "DBSe", name ) == 0 ) {
0597 return true;
0598 }
0599
0600 return false;
0601 }
0602
0603 static void mb_thread_switch( Thread_Control *executing, Thread_Control *heir )
0604 {
0605 if ( tid_is_excluded( heir->Object.id ) == true ) {
0606 rtems_debugger_target_swbreak_remove();
0607 return;
0608 }
0609
0610
0611 rtems_debugger_target_swbreak_insert();
0612 }
0613
0614 User_extensions_Control mb_ext = {
0615 .Callouts = { .thread_switch = mb_thread_switch }
0616 };
0617
0618 int rtems_debugger_target_enable( void )
0619 {
0620 debug_session_active = true;
0621 rtems_interrupt_lock_context lock_context;
0622
0623 rtems_interrupt_lock_acquire( &target_lock, &lock_context );
0624
0625 _MicroBlaze_Debug_install_handler( target_exception_handler, NULL );
0626 _MicroBlaze_Exception_install_handler( target_exception_handler, NULL );
0627 _User_extensions_Add_set( &mb_ext );
0628
0629 rtems_interrupt_lock_release( &target_lock, &lock_context );
0630 return RTEMS_SUCCESSFUL;
0631 }
0632
0633 int rtems_debugger_target_disable( void )
0634 {
0635 debug_session_active = false;
0636 rtems_interrupt_lock_context lock_context;
0637
0638 rtems_interrupt_lock_acquire( &target_lock, &lock_context );
0639
0640 _User_extensions_Remove_set( &mb_ext );
0641
0642 rtems_interrupt_lock_release( &target_lock, &lock_context );
0643 return RTEMS_SUCCESSFUL;
0644 }
0645
0646 int rtems_debugger_target_read_regs( rtems_debugger_thread *thread )
0647 {
0648 if (
0649 rtems_debugger_thread_flag(
0650 thread,
0651 RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID
0652 ) == 0
0653 ) {
0654 static const uintptr_t good_address = (uintptr_t) &good_address;
0655 int i;
0656
0657 memset( &thread->registers[ 0 ], 0, RTEMS_DEBUGGER_NUMREGBYTES );
0658
0659
0660 for ( i = 0; i < RTEMS_DEBUGGER_NUMREGS; ++i ) {
0661 rtems_debugger_set_int_reg( thread, i, (uintptr_t) &good_address );
0662 }
0663
0664 if ( thread->frame != NULL ) {
0665 CPU_Exception_frame *frame = thread->frame;
0666
0667 *( (CPU_Exception_frame *) thread->registers ) = *frame;
0668 rtems_debugger_set_int_reg( thread, REG_R0, 0 );
0669 rtems_debugger_set_int_reg( thread, REG_R1, frame->r1 );
0670 rtems_debugger_set_int_reg( thread, REG_R2, frame->r2 );
0671 rtems_debugger_set_int_reg( thread, REG_R3, frame->r3 );
0672 rtems_debugger_set_int_reg( thread, REG_R4, frame->r4 );
0673 rtems_debugger_set_int_reg( thread, REG_R5, frame->r5 );
0674 rtems_debugger_set_int_reg( thread, REG_R6, frame->r6 );
0675 rtems_debugger_set_int_reg( thread, REG_R7, frame->r7 );
0676 rtems_debugger_set_int_reg( thread, REG_R8, frame->r8 );
0677 rtems_debugger_set_int_reg( thread, REG_R9, frame->r9 );
0678 rtems_debugger_set_int_reg( thread, REG_R10, frame->r10 );
0679 rtems_debugger_set_int_reg( thread, REG_R11, frame->r11 );
0680 rtems_debugger_set_int_reg( thread, REG_R12, frame->r12 );
0681 rtems_debugger_set_int_reg( thread, REG_R13, frame->r13 );
0682 rtems_debugger_set_int_reg( thread, REG_R14, (uintptr_t) frame->r14 );
0683 rtems_debugger_set_int_reg( thread, REG_R15, (uintptr_t) frame->r15 );
0684 rtems_debugger_set_int_reg( thread, REG_R16, (uintptr_t) frame->r16 );
0685 rtems_debugger_set_int_reg( thread, REG_R17, (uintptr_t) frame->r17 );
0686 rtems_debugger_set_int_reg( thread, REG_R18, frame->r18 );
0687 rtems_debugger_set_int_reg( thread, REG_R19, frame->r19 );
0688 rtems_debugger_set_int_reg( thread, REG_R20, frame->r20 );
0689 rtems_debugger_set_int_reg( thread, REG_R21, frame->r21 );
0690 rtems_debugger_set_int_reg( thread, REG_R22, frame->r22 );
0691 rtems_debugger_set_int_reg( thread, REG_R23, frame->r23 );
0692 rtems_debugger_set_int_reg( thread, REG_R24, frame->r24 );
0693 rtems_debugger_set_int_reg( thread, REG_R25, frame->r25 );
0694 rtems_debugger_set_int_reg( thread, REG_R26, frame->r26 );
0695 rtems_debugger_set_int_reg( thread, REG_R27, frame->r27 );
0696 rtems_debugger_set_int_reg( thread, REG_R28, frame->r28 );
0697 rtems_debugger_set_int_reg( thread, REG_R29, frame->r29 );
0698 rtems_debugger_set_int_reg( thread, REG_R30, frame->r30 );
0699 rtems_debugger_set_int_reg( thread, REG_R31, frame->r31 );
0700 rtems_debugger_set_int_reg(
0701 thread,
0702 REG_PC,
0703 rtems_debugger_target_frame_pc( frame )
0704 );
0705 rtems_debugger_set_int_reg( thread, REG_MS, frame->msr );
0706 rtems_debugger_set_int_reg( thread, REG_EA, (uintptr_t) frame->ear );
0707 rtems_debugger_set_int_reg( thread, REG_ES, frame->esr );
0708 rtems_debugger_set_int_reg( thread, REG_BT, (uintptr_t) frame->btr );
0709
0710
0711
0712 thread->signal = rtems_debugger_target_exception_to_signal( frame );
0713 } else {
0714 rtems_debugger_set_int_reg(
0715 thread,
0716 REG_R1,
0717 thread->tcb->Registers.r1
0718 );
0719 rtems_debugger_set_int_reg(
0720 thread,
0721 REG_R13,
0722 thread->tcb->Registers.r13
0723 );
0724 rtems_debugger_set_int_reg(
0725 thread,
0726 REG_R14,
0727 thread->tcb->Registers.r14
0728 );
0729 rtems_debugger_set_int_reg(
0730 thread,
0731 REG_R15,
0732 thread->tcb->Registers.r15
0733 );
0734 rtems_debugger_set_int_reg(
0735 thread,
0736 REG_R16,
0737 thread->tcb->Registers.r16
0738 );
0739 rtems_debugger_set_int_reg(
0740 thread,
0741 REG_R17,
0742 thread->tcb->Registers.r17
0743 );
0744 rtems_debugger_set_int_reg(
0745 thread,
0746 REG_R18,
0747 thread->tcb->Registers.r18
0748 );
0749 rtems_debugger_set_int_reg(
0750 thread,
0751 REG_R19,
0752 thread->tcb->Registers.r19
0753 );
0754 rtems_debugger_set_int_reg(
0755 thread,
0756 REG_R20,
0757 thread->tcb->Registers.r20
0758 );
0759 rtems_debugger_set_int_reg(
0760 thread,
0761 REG_R21,
0762 thread->tcb->Registers.r21
0763 );
0764 rtems_debugger_set_int_reg(
0765 thread,
0766 REG_R22,
0767 thread->tcb->Registers.r22
0768 );
0769 rtems_debugger_set_int_reg(
0770 thread,
0771 REG_R23,
0772 thread->tcb->Registers.r23
0773 );
0774 rtems_debugger_set_int_reg(
0775 thread,
0776 REG_R24,
0777 thread->tcb->Registers.r24
0778 );
0779 rtems_debugger_set_int_reg(
0780 thread,
0781 REG_R25,
0782 thread->tcb->Registers.r25
0783 );
0784 rtems_debugger_set_int_reg(
0785 thread,
0786 REG_R26,
0787 thread->tcb->Registers.r26
0788 );
0789 rtems_debugger_set_int_reg(
0790 thread,
0791 REG_R27,
0792 thread->tcb->Registers.r27
0793 );
0794 rtems_debugger_set_int_reg(
0795 thread,
0796 REG_R28,
0797 thread->tcb->Registers.r28
0798 );
0799 rtems_debugger_set_int_reg(
0800 thread,
0801 REG_R29,
0802 thread->tcb->Registers.r29
0803 );
0804 rtems_debugger_set_int_reg(
0805 thread,
0806 REG_R30,
0807 thread->tcb->Registers.r30
0808 );
0809 rtems_debugger_set_int_reg(
0810 thread,
0811 REG_R31,
0812 thread->tcb->Registers.r31
0813 );
0814 rtems_debugger_set_int_reg(
0815 thread,
0816 REG_MS,
0817 (intptr_t) thread->tcb->Registers.rmsr
0818 );
0819
0820
0821
0822 thread->signal = 0;
0823 }
0824
0825 thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID;
0826 thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
0827 }
0828
0829 return 0;
0830 }
0831
0832 int rtems_debugger_target_write_regs( rtems_debugger_thread *thread )
0833 {
0834 if (
0835 rtems_debugger_thread_flag(
0836 thread,
0837 RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY
0838 ) != 0
0839 ) {
0840
0841
0842
0843
0844 if (
0845 rtems_debugger_thread_flag(
0846 thread,
0847 RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION
0848 ) != 0
0849 ) {
0850 CPU_Exception_frame *frame = thread->frame;
0851 frame->r1 = rtems_debugger_get_int_reg( thread, REG_R1 );
0852 frame->r2 = rtems_debugger_get_int_reg( thread, REG_R2 );
0853 frame->r3 = rtems_debugger_get_int_reg( thread, REG_R3 );
0854 frame->r4 = rtems_debugger_get_int_reg( thread, REG_R4 );
0855 frame->r5 = rtems_debugger_get_int_reg( thread, REG_R5 );
0856 frame->r6 = rtems_debugger_get_int_reg( thread, REG_R6 );
0857 frame->r7 = rtems_debugger_get_int_reg( thread, REG_R7 );
0858 frame->r8 = rtems_debugger_get_int_reg( thread, REG_R8 );
0859 frame->r9 = rtems_debugger_get_int_reg( thread, REG_R9 );
0860 frame->r10 = rtems_debugger_get_int_reg( thread, REG_R10 );
0861 frame->r11 = rtems_debugger_get_int_reg( thread, REG_R11 );
0862 frame->r12 = rtems_debugger_get_int_reg( thread, REG_R12 );
0863 frame->r13 = rtems_debugger_get_int_reg( thread, REG_R13 );
0864 frame->r14 = (uint32_t *) rtems_debugger_get_int_reg( thread, REG_R14 );
0865 frame->r15 = (uint32_t *) rtems_debugger_get_int_reg( thread, REG_R15 );
0866 frame->r16 = (uint32_t *) rtems_debugger_get_int_reg( thread, REG_R16 );
0867 frame->r17 = (uint32_t *) rtems_debugger_get_int_reg( thread, REG_R17 );
0868 frame->r18 = rtems_debugger_get_int_reg( thread, REG_R18 );
0869 frame->r19 = rtems_debugger_get_int_reg( thread, REG_R19 );
0870 frame->r20 = rtems_debugger_get_int_reg( thread, REG_R20 );
0871 frame->r21 = rtems_debugger_get_int_reg( thread, REG_R21 );
0872 frame->r22 = rtems_debugger_get_int_reg( thread, REG_R22 );
0873 frame->r23 = rtems_debugger_get_int_reg( thread, REG_R23 );
0874 frame->r24 = rtems_debugger_get_int_reg( thread, REG_R24 );
0875 frame->r25 = rtems_debugger_get_int_reg( thread, REG_R25 );
0876 frame->r26 = rtems_debugger_get_int_reg( thread, REG_R26 );
0877 frame->r27 = rtems_debugger_get_int_reg( thread, REG_R27 );
0878 frame->r28 = rtems_debugger_get_int_reg( thread, REG_R28 );
0879 frame->r29 = rtems_debugger_get_int_reg( thread, REG_R29 );
0880 frame->r30 = rtems_debugger_get_int_reg( thread, REG_R30 );
0881 frame->r31 = rtems_debugger_get_int_reg( thread, REG_R31 );
0882 frame->msr = rtems_debugger_get_int_reg( thread, REG_MS );
0883 frame->ear = (uint32_t *) rtems_debugger_get_int_reg( thread, REG_EA );
0884 frame->esr = rtems_debugger_get_int_reg( thread, REG_ES );
0885 frame->btr = (uint32_t *) rtems_debugger_get_int_reg( thread, REG_BT );
0886 }
0887
0888 thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
0889 }
0890
0891 return 0;
0892 }
0893
0894 uintptr_t rtems_debugger_target_reg_pc( rtems_debugger_thread *thread )
0895 {
0896 return thread->tcb->Registers.r15;
0897 }
0898
0899 uintptr_t rtems_debugger_target_frame_pc( CPU_Exception_frame *frame )
0900 {
0901 return (uintptr_t) _MicroBlaze_Get_return_address( frame );
0902 }
0903
0904 uintptr_t rtems_debugger_target_reg_sp( rtems_debugger_thread *thread )
0905 {
0906 int r;
0907
0908 r = rtems_debugger_target_read_regs( thread );
0909
0910 if ( r >= 0 ) {
0911 return rtems_debugger_get_int_reg( thread, REG_R1 );
0912 }
0913
0914 return 0;
0915 }
0916
0917 uintptr_t rtems_debugger_target_tcb_sp( rtems_debugger_thread *thread )
0918 {
0919 return (uintptr_t) thread->tcb->Registers.r1;
0920 }
0921
0922 #define IGROUP_MASK 0x3f
0923
0924 static uint32_t get_igroup( uint32_t ins )
0925 {
0926 return ( ins >> 26 ) & IGROUP_MASK;
0927 }
0928
0929 #define REGISTER_MASK 0x1f
0930
0931 static uint32_t get_Ra( uint32_t ins )
0932 {
0933 return ( ins >> 16 ) & REGISTER_MASK;
0934 }
0935
0936 static uint32_t get_Rb( uint32_t ins )
0937 {
0938 return ( ins >> 11 ) & REGISTER_MASK;
0939 }
0940
0941 static uint32_t get_Rd( uint32_t ins )
0942 {
0943 return ( ins >> 21 ) & REGISTER_MASK;
0944 }
0945
0946 #define IMM16_MASK 0xffff
0947
0948 static int32_t get_Imm16( uint32_t ins )
0949 {
0950 int16_t base = (int16_t) ins & IMM16_MASK;
0951
0952 return base;
0953 }
0954
0955 #define IMM24_MASK 0xffffff
0956
0957 static int32_t get_Imm24( uint32_t ins )
0958 {
0959 int32_t base = ins & IMM24_MASK;
0960
0961
0962 if ( ( base & 0x800000 ) != 0 ) {
0963 base &= 0xFF000000;
0964 }
0965
0966 return base;
0967 }
0968
0969 static int64_t get_Imm( uint32_t ins )
0970 {
0971 if ( ( get_Rd( ins ) & 0x10 ) != 0 ) {
0972 return get_Imm24( ins );
0973 }
0974
0975 return get_Imm16( ins );
0976 }
0977
0978 #define IMM_GROUP 0x2c
0979
0980 static bool is_imm( uint32_t ins )
0981 {
0982 return get_igroup( ins ) == IMM_GROUP;
0983 }
0984
0985 #define RETURN_GROUP 0x2d
0986
0987 static bool is_return( uint32_t ins )
0988 {
0989 return get_igroup( ins ) == RETURN_GROUP;
0990 }
0991
0992
0993 #define UBRANCH_GROUP 0x26
0994
0995 static bool is_ubranch( uint32_t ins )
0996 {
0997 return get_igroup( ins ) == UBRANCH_GROUP;
0998 }
0999
1000
1001 #define CBRANCH_GROUP 0x27
1002
1003 static bool is_cbranch( uint32_t ins )
1004 {
1005 return get_igroup( ins ) == CBRANCH_GROUP;
1006 }
1007
1008
1009 #define UIBRANCH_GROUP 0x2e
1010
1011 static bool is_uibranch( uint32_t ins )
1012 {
1013
1014 return get_igroup( ins ) == UIBRANCH_GROUP && get_Ra( ins ) != 0x2;
1015 }
1016
1017
1018 #define CIBRANCH_GROUP 0x2f
1019
1020 static bool is_cibranch( uint32_t ins )
1021 {
1022 return get_igroup( ins ) == CIBRANCH_GROUP;
1023 }
1024
1025 static bool branch_has_delay_slot( uint32_t ins )
1026 {
1027 if ( is_ubranch( ins ) == true && ( get_Ra( ins ) & 0x10 ) != 0 ) {
1028 return true;
1029 }
1030
1031 if ( is_cbranch( ins ) == true && ( get_Ra( ins ) & 0x10 ) != 0 ) {
1032 return true;
1033 }
1034
1035 if ( is_uibranch( ins ) == true && ( get_Ra( ins ) & 0x10 ) != 0 ) {
1036 return true;
1037 }
1038
1039 if ( is_cibranch( ins ) == true && ( get_Rd( ins ) & 0x10 ) != 0 ) {
1040 return true;
1041 }
1042
1043 return false;
1044 }
1045
1046
1047
1048 static bool branch_is_absolute( uint32_t ins )
1049 {
1050 return ( is_ubranch( ins ) == true || is_uibranch( ins ) == true ) &&
1051 ( get_Ra( ins ) & 0x8 ) != 0;
1052 }
1053
1054
1055
1056 static bool target_is_absolute( uint32_t ins )
1057 {
1058 return branch_is_absolute( ins ) == true || is_return( ins ) == true;
1059 }
1060
1061 static bool is_branch( uint32_t ins )
1062 {
1063 if ( is_ubranch( ins ) == true ) {
1064 return true;
1065 }
1066
1067 if ( is_cbranch( ins ) == true ) {
1068 return true;
1069 }
1070
1071 if ( is_uibranch( ins ) == true ) {
1072 return true;
1073 }
1074
1075 if ( is_cibranch( ins ) == true ) {
1076 return true;
1077 }
1078
1079 return false;
1080 }
1081
1082 #define BRK_RA 0xC
1083
1084 static bool is_brk( uint32_t ins )
1085 {
1086 return ( is_ubranch( ins ) == true || is_uibranch( ins ) == true ) &&
1087 get_Ra( ins ) == BRK_RA;
1088 }
1089
1090 static uint32_t get_register_value(
1091 CPU_Exception_frame *frame,
1092 uint32_t target_register
1093 )
1094 {
1095 if ( target_register == 0 ) {
1096 return 0;
1097 }
1098
1099
1100 return ( &( frame->r1 ) )[ target_register - 1 ];
1101 }
1102
1103 static void set_frame_pc( CPU_Exception_frame *frame, uint32_t *new_pc )
1104 {
1105 Per_CPU_Control *cpu_self = _Per_CPU_Get();
1106
1107
1108 if ( ( frame->msr & MICROBLAZE_MSR_BIP ) != 0 ) {
1109 frame->r16 = (uint32_t *) new_pc;
1110 return;
1111 }
1112
1113
1114 if ( ( frame->msr & MICROBLAZE_MSR_EIP ) != 0 ) {
1115 frame->r17 = (uint32_t *) new_pc;
1116 return;
1117 }
1118
1119
1120 if (
1121 frame->r1 >= (uint32_t) cpu_self->interrupt_stack_low
1122 && frame->r1 < (uint32_t) cpu_self->interrupt_stack_high
1123 ) {
1124 frame->r14 = (uint32_t *) new_pc;
1125 return;
1126 }
1127
1128
1129 frame->r15 = (uint32_t *) new_pc;
1130 }
1131
1132 static uint32_t bypass_swbreaks( uint32_t *addr )
1133 {
1134 rtems_debugger_target *target = rtems_debugger->target;
1135
1136 if ( target != NULL && target->swbreaks.block != NULL ) {
1137 rtems_debugger_target_swbreak *swbreaks = target->swbreaks.block;
1138 size_t i;
1139
1140 for ( i = 0; i < target->swbreaks.level; ++i ) {
1141 if ( swbreaks[ i ].address == addr ) {
1142 return *( (uint32_t *) &( swbreaks[ i ].contents[ 0 ] ) );
1143 }
1144 }
1145 }
1146
1147 return *addr;
1148 }
1149
1150 static int setup_single_step_breakpoints( CPU_Exception_frame *frame )
1151 {
1152
1153
1154
1155
1156
1157 uint32_t *pc = (uint32_t *) rtems_debugger_target_frame_pc( frame );
1158 int64_t imm = 0;
1159 uint32_t *resume_pc;
1160
1161
1162
1163
1164
1165 while ( is_imm( bypass_swbreaks( pc ) ) == true ) {
1166 pc = &pc[ 1 ];
1167 }
1168
1169 resume_pc = pc;
1170
1171
1172
1173
1174
1175
1176
1177
1178 uint32_t bypass_ins = bypass_swbreaks( &pc[ -1 ] );
1179
1180 if ( is_imm( bypass_ins ) == true ) {
1181 imm = get_Imm( bypass_ins );
1182 imm <<= 16;
1183 resume_pc = &pc[ -1 ];
1184 }
1185
1186 uint32_t ins = bypass_swbreaks( pc );
1187 bool needs_target_break = false;
1188 bool needs_next_break = true;
1189
1190 if ( is_brk( ins ) == true ) {
1191
1192
1193
1194
1195
1196
1197 rtems_debugger_printf(
1198 "rtems-db: Unable to set single-step breakpoints for brk/brki instructions\n"
1199 );
1200
1201 return -1;
1202 }
1203
1204 if ( is_branch( ins ) == true ) {
1205 needs_target_break = true;
1206
1207
1208
1209
1210
1211 if (
1212 is_ubranch( ins ) == true
1213 || is_uibranch( ins ) == true
1214 || is_return( ins ) == true
1215 ) {
1216 needs_next_break = false;
1217 }
1218 }
1219
1220 if ( is_return( ins ) == true ) {
1221 needs_target_break = true;
1222 needs_next_break = false;
1223 }
1224
1225 if ( needs_next_break == true ) {
1226 uint32_t *next_ins = &pc[ 1 ];
1227
1228 if ( branch_has_delay_slot( ins ) == true ) {
1229 next_ins = &pc[ 2 ];
1230 }
1231
1232 if ( is_brk( *next_ins ) == false ) {
1233
1234 set_soft_break( &next_soft_break, next_ins );
1235 }
1236 }
1237
1238 if ( imm != 0 ) {
1239 imm |= ( get_Imm16( ins ) & 0xFFFF );
1240 } else {
1241 imm = get_Imm16( ins );
1242 }
1243
1244 if ( needs_target_break == true ) {
1245
1246 uintptr_t target_ins = 0;
1247
1248 if ( target_is_absolute( ins ) == false ) {
1249 target_ins += (uintptr_t) pc;
1250 }
1251
1252 if (
1253 is_uibranch( ins ) == true || is_cibranch( ins ) == true ||
1254 is_return( ins ) == true
1255 ) {
1256 target_ins += imm;
1257 }
1258
1259 if ( is_return( ins ) == true ) {
1260 uint32_t target_register = get_Ra( ins );
1261 target_ins += get_register_value( frame, target_register );
1262 }
1263
1264 if ( is_ubranch( ins ) == true || is_cbranch( ins ) == true ) {
1265 uint32_t target_register = get_Rb( ins );
1266 target_ins += get_register_value( frame, target_register );
1267 }
1268
1269 if ( is_brk( *( (uint32_t *) target_ins ) ) == false ) {
1270
1271 set_soft_break( &target_soft_break, (uint32_t *) target_ins );
1272 }
1273 }
1274
1275
1276 set_frame_pc( frame, resume_pc );
1277
1278 return 0;
1279 }
1280
1281 int rtems_debugger_target_thread_stepping( rtems_debugger_thread *thread )
1282 {
1283 CPU_Exception_frame *frame = thread->frame;
1284 int ret = 0;
1285
1286 if (
1287 rtems_debugger_thread_flag(
1288 thread,
1289 RTEMS_DEBUGGER_THREAD_FLAG_STEP_INSTR
1290 ) != 0
1291 ) {
1292
1293 if ( frame == NULL ) {
1294 return -1;
1295 }
1296
1297
1298 ret = setup_single_step_breakpoints( frame );
1299 }
1300
1301 return ret;
1302 }
1303
1304 int rtems_debugger_target_exception_to_signal( CPU_Exception_frame *frame )
1305 {
1306 uint32_t BiP = frame->msr & MICROBLAZE_MSR_BIP;
1307 uint32_t EiP = frame->msr & MICROBLAZE_MSR_EIP;
1308
1309 if ( BiP != 0 ) {
1310 return RTEMS_DEBUGGER_SIGNAL_TRAP;
1311 }
1312
1313 if ( EiP != 0 ) {
1314 uint32_t EC = frame->esr & 0x1f;
1315
1316 switch ( EC ) {
1317 case 0x0:
1318 case 0x1:
1319 case 0x3:
1320 case 0x4:
1321 case 0x10:
1322 case 0x11:
1323 case 0x12:
1324 case 0x13:
1325 return RTEMS_DEBUGGER_SIGNAL_SEGV;
1326
1327 case 0x7:
1328 return RTEMS_DEBUGGER_SIGNAL_TRAP;
1329
1330 case 0x5:
1331 case 0x6:
1332 return RTEMS_DEBUGGER_SIGNAL_FPE;
1333
1334 case 0x2:
1335
1336
1337 if ( rtems_debugger_target_swbreak_is_configured( (uintptr_t) frame->r17 ) ) {
1338 return RTEMS_DEBUGGER_SIGNAL_TRAP;
1339 }
1340
1341 default:
1342 return RTEMS_DEBUGGER_SIGNAL_ILL;
1343 }
1344 }
1345
1346
1347 return RTEMS_DEBUGGER_SIGNAL_ILL;
1348 }
1349
1350 void rtems_debugger_target_exception_print( CPU_Exception_frame *frame )
1351 {
1352 EXC_FRAME_PRINT( rtems_debugger_printf, "", frame );
1353 }
1354
1355
1356
1357
1358
1359 int rtems_debugger_target_hwbreak_insert( void )
1360 {
1361 return 0;
1362 }
1363
1364 int rtems_debugger_target_hwbreak_remove( void )
1365 {
1366 return 0;
1367 }
1368
1369 int rtems_debugger_target_hwbreak_control(
1370 rtems_debugger_target_watchpoint wp,
1371 bool insert,
1372 uintptr_t addr,
1373 DB_UINT kind
1374 )
1375 {
1376 return 0;
1377 }
1378
1379 int rtems_debugger_target_cache_sync( rtems_debugger_target_swbreak *swbreak )
1380 {
1381
1382
1383
1384 rtems_cache_flush_multiple_data_lines(
1385 swbreak->address,
1386 sizeof( breakpoint )
1387 );
1388 rtems_cache_instruction_sync_after_code_change(
1389 swbreak->address,
1390 sizeof( breakpoint )
1391 );
1392 return 0;
1393 }