armv8: allow halt on exception 79/4479/10
authorMatthias Welwarsky <matthias.welwarsky@sysgo.com>
Thu, 5 Apr 2018 11:42:21 +0000 (13:42 +0200)
committerMatthias Welwarsky <matthias@welwarsky.de>
Mon, 4 Mar 2019 11:53:00 +0000 (11:53 +0000)
add command 'catch_exc' to halt a core on entering any of Secure EL1 or
EL3 or Non-Secure EL1 or EL2.

Change-Id: I0c68e247af68dd96616855a9bc1063c277d222e5
Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
Reviewed-on: http://openocd.zylin.com/4479
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
doc/openocd.texi
src/server/gdb_server.c
src/target/armv8.c
src/target/armv8.h
src/target/armv8_dpm.c
src/target/target.c
src/target/target.h

index 8b03b80..2e04182 100644 (file)
@@ -9345,6 +9345,14 @@ be copied to an in-memory buffer identified by the @option{address} and
 @option{size} options using DMA.
 @end deffn
 
+@deffn Command {$target_name catch_exc} [@option{off}|@option{sec_el1}|@option{sec_el3}|@option{nsec_el1}|@option{nsec_el2}]+
+Cause @command{$target_name} to halt when an exception is taken. Any combination of
+Secure (sec) EL1/EL3 or Non-Secure (nsec) EL1/EL2 is valid. The target
+@command{$target_name} will halt before taking the exception. In order to resume
+the target, the exception catch must be disabled again with @command{$target_name catch_exc off}.
+Issuing the command without options prints the current configuration.
+@end deffn
+
 @section Intel Architecture
 
 Intel Quark X10xx is the first product in the Quark family of SoCs. It is an IA-32
index 13e5aca..ef2ead4 100644 (file)
@@ -153,6 +153,8 @@ static int gdb_last_signal(struct target *target)
                        return 0x05;    /* SIGTRAP */
                case DBG_REASON_SINGLESTEP:
                        return 0x05;    /* SIGTRAP */
+               case DBG_REASON_EXC_CATCH:
+                       return 0x05;
                case DBG_REASON_NOTHALTED:
                        return 0x0;             /* no signal... shouldn't happen */
                default:
index cee837f..76a2d98 100644 (file)
@@ -1013,6 +1013,72 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
        return retval;
 }
 
+COMMAND_HANDLER(armv8_handle_exception_catch_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct armv8_common *armv8 = target_to_armv8(target);
+       uint32_t edeccr = 0;
+       unsigned int argp = 0;
+       int retval;
+
+       static const Jim_Nvp nvp_ecatch_modes[] = {
+               { .name = "off",       .value = 0 },
+               { .name = "nsec_el1",  .value = (1 << 5) },
+               { .name = "nsec_el2",  .value = (2 << 5) },
+               { .name = "nsec_el12", .value = (3 << 5) },
+               { .name = "sec_el1",   .value = (1 << 1) },
+               { .name = "sec_el3",   .value = (4 << 1) },
+               { .name = "sec_el13",  .value = (5 << 1) },
+               { .name = NULL, .value = -1 },
+       };
+       const Jim_Nvp *n;
+
+       if (CMD_ARGC == 0) {
+               const char *sec = NULL, *nsec = NULL;
+
+               retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+                                       armv8->debug_base + CPUV8_DBG_ECCR, &edeccr);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               n = Jim_Nvp_value2name_simple(nvp_ecatch_modes, edeccr & 0x0f);
+               if (n->name != NULL)
+                       sec = n->name;
+
+               n = Jim_Nvp_value2name_simple(nvp_ecatch_modes, edeccr & 0xf0);
+               if (n->name != NULL)
+                       nsec = n->name;
+
+               if (sec == NULL || nsec == NULL) {
+                       LOG_WARNING("Exception Catch: unknown exception catch configuration: EDECCR = %02x", edeccr & 0xff);
+                       return ERROR_FAIL;
+               }
+
+               command_print(CMD_CTX, "Exception Catch: Secure: %s, Non-Secure: %s", sec, nsec);
+               return ERROR_OK;
+       }
+
+       while (CMD_ARGC > argp) {
+               n = Jim_Nvp_name2value_simple(nvp_ecatch_modes, CMD_ARGV[argp]);
+               if (n->name == NULL) {
+                       LOG_ERROR("Unknown option: %s", CMD_ARGV[argp]);
+                       return ERROR_FAIL;
+               }
+
+               LOG_DEBUG("found: %s", n->name);
+
+               edeccr |= n->value;
+               argp++;
+       }
+
+       retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+                               armv8->debug_base + CPUV8_DBG_ECCR, edeccr);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return ERROR_OK;
+}
+
 int armv8_handle_cache_info_command(struct command_context *cmd_ctx,
        struct armv8_cache_common *armv8_cache)
 {
@@ -1675,6 +1741,13 @@ void armv8_free_reg_cache(struct target *target)
 }
 
 const struct command_registration armv8_command_handlers[] = {
+       {
+               .name = "catch_exc",
+               .handler = armv8_handle_exception_catch_command,
+               .mode = COMMAND_EXEC,
+               .help = "configure exception catch",
+               .usage = "[(nsec_el1,nsec_el2,sec_el1,sec_el3)+,off]",
+       },
        COMMAND_REGISTRATION_DONE
 };
 
index dfd54ed..af00e52 100644 (file)
@@ -261,6 +261,7 @@ static inline bool is_armv8(struct armv8_common *armv8)
 #define CPUV8_DBG_WFAR1                0x34
 #define CPUV8_DBG_DSCR         0x088
 #define CPUV8_DBG_DRCR         0x090
+#define CPUV8_DBG_ECCR         0x098
 #define CPUV8_DBG_PRCR         0x310
 #define CPUV8_DBG_PRSR         0x314
 
index a5d7d11..081eed2 100644 (file)
@@ -1381,13 +1381,15 @@ void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
                case DSCRV8_ENTRY_BKPT: /* SW BKPT (?) */
                case DSCRV8_ENTRY_RESET_CATCH:  /* Reset catch */
                case DSCRV8_ENTRY_OS_UNLOCK:  /*OS unlock catch*/
-               case DSCRV8_ENTRY_EXCEPTION_CATCH:  /*exception catch*/
                case DSCRV8_ENTRY_SW_ACCESS_DBG: /*SW access dbg register*/
                        target->debug_reason = DBG_REASON_BREAKPOINT;
                        break;
                case DSCRV8_ENTRY_WATCHPOINT:   /* asynch watchpoint */
                        target->debug_reason = DBG_REASON_WATCHPOINT;
                        break;
+               case DSCRV8_ENTRY_EXCEPTION_CATCH:  /*exception catch*/
+                       target->debug_reason = DBG_REASON_EXC_CATCH;
+                       break;
                default:
                        target->debug_reason = DBG_REASON_UNDEFINED;
                        break;
index 9955a56..1f8e0bf 100644 (file)
@@ -251,6 +251,7 @@ static const Jim_Nvp nvp_target_debug_reason[] = {
        { .name = "single-step"              , .value = DBG_REASON_SINGLESTEP },
        { .name = "target-not-halted"        , .value = DBG_REASON_NOTHALTED  },
        { .name = "program-exit"             , .value = DBG_REASON_EXIT },
+       { .name = "exception-catch"          , .value = DBG_REASON_EXC_CATCH },
        { .name = "undefined"                , .value = DBG_REASON_UNDEFINED },
        { .name = NULL, .value = -1 },
 };
index 36b131a..794ee83 100644 (file)
@@ -84,7 +84,8 @@ enum target_debug_reason {
        DBG_REASON_SINGLESTEP = 4,
        DBG_REASON_NOTHALTED = 5,
        DBG_REASON_EXIT = 6,
-       DBG_REASON_UNDEFINED = 7,
+       DBG_REASON_EXC_CATCH = 7,
+       DBG_REASON_UNDEFINED = 8,
 };
 
 enum target_endianness {