Ignore:
Timestamp:
Jul 16, 2017, 11:53:11 PM (2 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
8ad4d93
Parents:
2465c01
git-author:
Chris Johns <chrisj@…> (07/16/17 23:53:11)
git-committer:
Chris Johns <chrisj@…> (08/15/17 01:39:22)
Message:

libdebugger: Fixes to debugging, ARM support, locking, and gcc-7.1 warnings.

  • Add printk support to aid multi-core debugging.
  • Add lock trace to aid lock debugging.
  • Fixes to gcc-7.1 warnings.
  • Fixes from ticket #2879.
  • Add verbose command controls.
  • Change using the RTEMS sys/lock.h API to manage exception threads.
  • ARM hardware breakpoint fixes. Support for SMP stepping is not implemented, this requires use of the context id register.

Closes #2879.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libdebugger/rtems-debugger-arm.c

    r2465c01 rb2353ed9  
    11/*
    2  * Copyright (c) 2016 Chris Johns <chrisj@rtems.org>.  All rights reserved.
     2 * Copyright (c) 2016-2017 Chris Johns <chrisj@rtems.org>.
     3 * All rights reserved.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    222223
    223224#if TARGET_DEBUG
     225void rtems_debugger_printk_lock(rtems_interrupt_lock_context* lock_context);
     226void rtems_debugger_printk_unlock(rtems_interrupt_lock_context* lock_context);
     227
    224228static void target_printk(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
    225229static void
    226230target_printk(const char* format, ...)
    227231{
     232  rtems_interrupt_lock_context lock_context;
    228233  va_list ap;
    229234  va_start(ap, format);
     235  rtems_debugger_printk_lock(&lock_context);
    230236  vprintk(format, ap);
     237  rtems_debugger_printk_unlock(&lock_context);
    231238  va_end(ap);
    232239}
     
    262269
    263270/*
     271 * CP register access.
     272 */
     273#define ARM_CP_INSTR(_opc, _cp, _op1, _val, _CRn, _CRm, _op2)           \
     274  #_opc " p" #_cp ", " #_op1 ", %[" #_val "], c" #_CRn ", c" #_CRm ", " #_op2 "\n"
     275
     276#define ARM_CP_WRITE(_cp, _op1, _val, _CRn, _CRm, _op2)    \
     277  do {                                                     \
     278    ARM_SWITCH_REG;                                        \
     279    asm volatile(                                          \
     280      ASM_ARM_MODE                                         \
     281      ARM_CP_INSTR(mcr, _cp, _op1, val, _CRn, _CRm, _op2)  \
     282      ASM_THUMB_MODE                                       \
     283      : ARM_SWITCH_REG_ASM                                 \
     284      : [val] "r" (_val));                                 \
     285  } while (0)
     286
     287#define ARM_CP_READ(_cp, _op1, _val, _CRn, _CRm, _op2)     \
     288  do {                                                     \
     289    ARM_SWITCH_REG;                                        \
     290    asm volatile(                                          \
     291      ASM_ARM_MODE                                         \
     292      ARM_CP_INSTR(mrc, _cp, _op1, val, _CRn, _CRm, _op2)  \
     293      ASM_THUMB_MODE                                       \
     294      : ARM_SWITCH_REG_ASM,                                \
     295        [val] "=&r" (_val));                               \
     296  } while (0)
     297
     298/*
    264299 * Read and write a CP14 register.
    265300 *
     
    269304 * this.
    270305 */
    271 #define ARM_CP14_INSTR(_opc, _val, _CRn, _CRm, _opc2)                   \
    272   #_opc " p14, 0, %[" #_val "], c" #_CRn ", c" #_CRm ", " #_opc2 "\n"
    273 
    274 #define ARM_CP14_WRITE(_val, _CRn, _CRm, _opc2)            \
    275   do {                                                     \
    276     ARM_SWITCH_REG;                                        \
    277     asm volatile(                                          \
    278       ASM_ARM_MODE                                         \
    279       ARM_CP14_INSTR(mcr, val, _CRn, _CRm, _opc2)          \
    280       ASM_THUMB_MODE                                       \
    281       : ARM_SWITCH_REG_ASM                                 \
    282       : [val] "r" (_val));                                 \
    283   } while (0)
    284 
    285 #define ARM_CP14_READ(_val, _CRn, _CRm, _opc2)             \
    286   do {                                                     \
    287     ARM_SWITCH_REG;                                        \
    288     asm volatile(                                          \
    289       ASM_ARM_MODE                                         \
    290       ARM_CP14_INSTR(mrc, val, _CRn, _CRm, _opc2)          \
    291       ASM_THUMB_MODE                                       \
    292       : ARM_SWITCH_REG_ASM,                                \
    293         [val] "=&r" (_val));                               \
    294   } while (0)
     306#define ARM_CP14_WRITE(_val, _CRn, _CRm, _op2) \
     307  ARM_CP_WRITE(14, 0, _val, _CRn, _CRm, _op2)
     308
     309#define ARM_CP14_READ(_val, _CRn, _CRm, _op2)  \
     310  ARM_CP_READ(14, 0, _val, _CRn, _CRm, _op2)
     311
     312/*
     313 * Read and write a CP15 register.
     314 *
     315 * The Context ID register is a process level context and used to scope
     316 * hardware break points.
     317 */
     318#define ARM_CP15_WRITE(_val, _op1, _CRn, _CRm, _op2) \
     319  ARM_CP_WRITE(15, _op1, _val, _CRn, _CRm, _op2)
     320
     321#define ARM_CP15_READ(_val, _op1, _CRn, _CRm, _op2)  \
     322  ARM_CP_READ(15, _op1, _val, _CRn, _CRm, _op2)
    295323
    296324static int
     
    299327  #define ID_VALUE(_i, _h, _l) ((_i >> _l) & ((1 << ((_h - _l) + 1)) -1))
    300328  uint32_t          val;
    301   const char const* vl = "[Invalid version]";
    302   const char const* labels[] = {
     329  const char*      vl = "[Invalid version]";
     330  const char* const labels[] = {
    303331    "ARMv6 [v6]",
    304332    "ARMv6 [v6.1]",
     
    472500arm_debug_break_clear(void)
    473501{
    474   arm_debug_hwbreak* bp = &hw_breaks[0];
    475   int                i;
     502  rtems_interrupt_lock_context lock_context;
     503  arm_debug_hwbreak*           bp = &hw_breaks[0];
     504  int                          i;
     505  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
    476506  for (i = 0; i < hw_breakpoints; ++i, ++bp) {
    477507    bp->enabled = false;
    478508    bp->loaded = false;
    479509  }
    480 }
    481 
     510  rtems_interrupt_lock_release(&target_lock, &lock_context);
     511}
     512
     513static inline void
     514arm_debug_set_context_id(const uint32_t id)
     515{
     516  ARM_CP15_WRITE(id, 0, 13, 0, 1);
     517}
     518
     519/*
     520 * You can only load the hardware breaks points when in the SVC mode or the
     521 * single step inverted break point will trigger.
     522 */
    482523static void
    483524arm_debug_break_load(void)
    484525{
    485   arm_debug_hwbreak* bp = &hw_breaks[0];
    486   int                i;
    487   for (i = 0; i < hw_breakpoints; ++i, ++bp) {
     526  rtems_interrupt_lock_context lock_context;
     527  arm_debug_hwbreak*            bp = &hw_breaks[0];
     528  int                           i;
     529  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
     530  if (bp->enabled && !bp->loaded) {
     531    arm_debug_set_context_id(0xdead1111);
     532    arm_debug_break_write_value(0, bp->value);
     533    arm_debug_break_write_control(0, bp->control);
     534  }
     535  ++bp;
     536  for (i = 1; i < hw_breakpoints; ++i, ++bp) {
    488537    if (bp->enabled && !bp->loaded) {
    489538      bp->loaded = true;
    490       target_printk("]]} hwbp: %i: v:%08lx c:%08lx l:%08x\n",
    491                     i, bp->value, bp->control, bp->length);
    492539      arm_debug_break_write_value(i, bp->value);
    493540      arm_debug_break_write_control(i, bp->control);
    494541    }
    495542  }
     543  rtems_interrupt_lock_release(&target_lock, &lock_context);
    496544}
    497545
     
    499547arm_debug_break_unload(void)
    500548{
    501   arm_debug_hwbreak* bp = &hw_breaks[0];
     549  rtems_interrupt_lock_context lock_context;
     550  arm_debug_hwbreak*           bp = &hw_breaks[0];
    502551  int                i;
     552  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
     553  arm_debug_set_context_id(0);
    503554  for (i = 0; i < hw_breakpoints; ++i, ++bp) {
    504555    bp->loaded = false;
    505556    arm_debug_break_write_control(i, 0);
    506557  }
     558  rtems_interrupt_lock_release(&target_lock, &lock_context);
    507559}
    508560
     
    938990  rtems_interrupt_lock_context lock_context;
    939991  debug_session_active = true;
    940   rtems_interrupt_lock_acquire(&target_lock, &lock_context);
    941992  arm_debug_break_unload();
    942993  arm_debug_break_clear();
     994  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
    943995  rtems_debugger_target_set_vectors();
    944996  rtems_interrupt_lock_release(&target_lock, &lock_context);
     
    9541006  void*                        text_end;
    9551007#endif
     1008  arm_debug_break_unload();
     1009  arm_debug_break_clear();
    9561010  rtems_interrupt_lock_acquire(&target_lock, &lock_context);
    9571011  debug_session_active = false;
     
    10641118
    10651119    /*
    1066      * Only write to debugger controlled threads. Do not touch the registers
    1067      * for threads blocked in the context switcher.
     1120     * Only write to debugger controlled exception threads. Do not touch the
     1121     * registers for threads blocked in the context switcher.
    10681122     */
    10691123    if (rtems_debugger_thread_flag(thread,
    1070                                    RTEMS_DEBUGGER_THREAD_FLAG_DEBUGGING)) {
     1124                                   RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
    10711125      CPU_Exception_frame* frame = thread->frame;
    10721126      frame->register_r0  = regs[REG_R0];
     
    11321186rtems_debugger_target_thread_stepping(rtems_debugger_thread* thread)
    11331187{
    1134   if (rtems_debugger_thread_flag(thread,
    1135                                  (RTEMS_DEBUGGER_THREAD_FLAG_STEP |
    1136                                   RTEMS_DEBUGGER_THREAD_FLAG_STEPPING))) {
     1188  if (rtems_debugger_thread_flag(thread, RTEMS_DEBUGGER_THREAD_FLAG_STEP_INSTR)) {
    11371189    /*
    11381190     * Single stepping and range stepping uses hardware debug breakpoint
     
    11411193    CPU_Exception_frame* frame = thread->frame;
    11421194    arm_debug_hwbreak*   bp = &hw_breaks[0];
    1143     int                  i;
    1144     for (i = 0; i < hw_breakpoints; ++i, ++bp) {
    1145       if (!bp->enabled) {
    1146         const uint32_t addr = (intptr_t) frame->register_pc;
    1147         const bool     thumb = (FRAME_SR & (1 << 5)) != 0 ? true : false;
    1148         uint32_t       bas;
    1149 
    1150         bp->enabled = true;
    1151         bp->loaded = false;
    1152         bp->address = frame->register_pc;
    1153         bp->frame = frame;
    1154         bp->length = sizeof(uint32_t);
    1155 
    1156         if (thumb) {
    1157           uint16_t instr = *((uint16_t*) frame->register_pc);
    1158           switch (instr & 0xf800) {
    1159           case 0xe800:
    1160           case 0xf000:
    1161           case 0xf800:
    1162             break;
    1163           default:
    1164             bp->length = sizeof(uint16_t);
    1165             break;
    1166           }
     1195    target_printk("[} stepping: %s\n", bp->enabled ? "yes" : "no");
     1196    if (!bp->enabled) {
     1197      const uint32_t addr = (intptr_t) frame->register_pc;
     1198      const bool     thumb = (FRAME_SR & (1 << 5)) != 0 ? true : false;
     1199      uint32_t       bas;
     1200
     1201      bp->enabled = true;
     1202      bp->loaded = false;
     1203      bp->address = frame->register_pc;
     1204      bp->frame = frame;
     1205      bp->length = sizeof(uint32_t);
     1206
     1207      if (thumb) {
     1208        uint16_t instr = *((uint16_t*) frame->register_pc);
     1209        switch (instr & 0xf800) {
     1210        case 0xe800:
     1211        case 0xf000:
     1212        case 0xf800:
     1213          break;
     1214        default:
     1215          bp->length = sizeof(uint16_t);
     1216          break;
    11671217        }
    1168 
    1169         /*
    1170          * See table C3-2 Effect of byte address selection on Breakpoint
    1171          * generation and "Instruction address comparisoin programming
    1172          * examples.
    1173          */
    1174         if (thumb) {
    1175           if ((addr & (1 << 1)) == 0) {
    1176             bas = 0x3; /* b0011 */
    1177           }
    1178           else {
    1179             bas = 0xc; /* b1100 */
    1180           }
     1218      }
     1219
     1220      /*
     1221       * See table C3-2 Effect of byte address selection on Breakpoint
     1222       * generation and "Instruction address comparision programming
     1223       * examples.
     1224       */
     1225      if (thumb) {
     1226        if ((addr & (1 << 1)) == 0) {
     1227          bas = 0x3; /* b0011 */
    11811228        }
    11821229        else {
    1183           bas = 0xf; /* b1111 */
     1230          bas = 0xc; /* b1100 */
    11841231        }
    1185 
    1186         arm_debug_break_setup(bp,
    1187                               addr & ~0x3,
    1188                               ARM_HW_BP_UNLINKED_INSTR_MISMATCH,
    1189                               bas,
    1190                               ARM_HW_BP_PRIV_PL0_SUP_SYS);
    1191 
    1192         /*
    1193          * Save the interrupt state before stepping if set.
    1194          */
     1232      }
     1233      else {
     1234        bas = 0xf; /* b1111 */
     1235      }
     1236
     1237      arm_debug_break_setup(bp,
     1238                            addr & ~0x3,
     1239                            ARM_HW_BP_UNLINKED_INSTR_MISMATCH,
     1240                            bas,
     1241                            ARM_HW_BP_PRIV_PL0_SUP_SYS);
     1242
     1243      /*
     1244       * Save the interrupt state before stepping if set.
     1245       */
    11951246#if ARM_PSR_HAS_INT_MASK
    1196         if ((FRAME_SR & CPSR_INTS_MASK) != 0) {
    1197           uint32_t int_state;
    1198           int_state =
    1199             (frame->register_cpsr & CPSR_INTS_MASK) << RTEMS_DEBUGGER_THREAD_FLAG_TARGET_BASE;
    1200           thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_INTS_DISABLED | int_state;
    1201         }
    1202         /*
    1203          * Mask the interrupt when stepping.
    1204          */
    1205         FRAME_SR |= CPSR_INTS_MASK;
    1206 #endif
    1207         break;
     1247      if ((FRAME_SR & CPSR_INTS_MASK) != 0) {
     1248        uint32_t int_state;
     1249        int_state =
     1250          (frame->register_cpsr & CPSR_INTS_MASK) << RTEMS_DEBUGGER_THREAD_FLAG_TARGET_BASE;
     1251        thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_INTS_DISABLED | int_state;
    12081252      }
     1253      /*
     1254       * Mask the interrupt when stepping.
     1255       */
     1256      FRAME_SR |= CPSR_INTS_MASK;
     1257#endif
    12091258    }
    12101259  }
     
    12161265{
    12171266  int sig = RTEMS_DEBUGGER_SIGNAL_HUP;
    1218 #if defined(ARM_EXCEPTION_RESET)
     1267#if defined(ARM_MULTILIB_ARCH_V4)
    12191268  switch (frame->vector) {
    12201269  case ARM_EXCEPTION_RESET:
     
    12411290#endif
    12421291  return sig;
     1292}
     1293
     1294int
     1295rtems_debugger_target_hwbreak_insert(void)
     1296{
     1297  /*
     1298   * Do nothing, load on exit of the exception handler.
     1299   */
     1300  return 0;
     1301}
     1302
     1303int
     1304rtems_debugger_target_hwbreak_remove(void)
     1305{
     1306  arm_debug_break_unload();
     1307  return 0;
    12431308}
    12441309
     
    12631328  rtems_cache_flush_multiple_data_lines(swbreak->address,
    12641329                                        sizeof(breakpoint));
    1265   rtems_cache_invalidate_multiple_instruction_lines(swbreak->address,
    1266                                                     sizeof(breakpoint));
     1330  rtems_cache_instruction_sync_after_code_change(swbreak->address,
     1331                                                 sizeof(breakpoint));
    12671332  return 0;
    12681333}
Note: See TracChangeset for help on using the changeset viewer.