This is an automated email from Gerrit.

"liangzhen <[email protected]>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/9223

-- gerrit

commit 37a5fae1631b55525649c7bd2823576f06f4ae25
Author: liangzhen <[email protected]>
Date:   Tue May 13 13:49:22 2025 +0800

    target/riscv: add `cetrig` control
    
    Introduce RISC-V-sepecific `configure` parameter `-cetrig`
    
    Change-Id: If490838b81cdd918fae0b29a8e5bf1508afafba2
    Signed-off-by: liangzhen <[email protected]>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 63d07533e6..49e75a44b0 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -11638,6 +11638,15 @@ action pairs.
 @end itemize
 @end itemize
 
+@itemize
+@item @code{-cetrig} @option{disable}|@option{enable} -- determines how 
OpenOCD should
+configure the @code{cetrig} in the dcsr register. Defaults to @option{disable}.
+
+@itemize
+@item @code{cget} returns the currently configured state for @code{cetrig}.
+@end itemize
+@end itemize
+
 @subsection RISC-V Debug Configuration Commands
 
 @deffn {Command} {riscv dump_sample_buf} [base64]
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 6fa5e025be..9cbd6030fd 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -251,9 +251,9 @@ typedef struct {
        /* This target was selected using hasel. */
        bool selected;
 
-       /* When false, we need to set dcsr.ebreak*, halting the target if that's
-        * necessary. */
-       bool dcsr_ebreak_is_set;
+       /* When false, we need to configure certain bits in the dcsr register.
+        * To do that, we may momentarily halt the target, if necessary. */
+       bool dcsr_register_is_set;
 
        /* This hart was placed into a halt group in examine(). */
        bool haltgroup_supported;
@@ -1681,9 +1681,9 @@ static int wait_for_authbusy(struct target *target, 
uint32_t *dmstatus)
        return ERROR_OK;
 }
 
-static int set_dcsr_ebreak(struct target *target, bool step)
+static int set_dcsr_config(struct target *target, bool step)
 {
-       LOG_TARGET_DEBUG(target, "Set dcsr.ebreak*");
+       LOG_TARGET_DEBUG(target, "Set dcsr config");
 
        if (dm013_select_target(target) != ERROR_OK)
                return ERROR_FAIL;
@@ -1701,18 +1701,20 @@ static int set_dcsr_ebreak(struct target *target, bool 
step)
        dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, 
config->dcsr_ebreak_fields[RISCV_MODE_U]);
        dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, 
config->dcsr_ebreak_fields[RISCV_MODE_VS]);
        dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, 
config->dcsr_ebreak_fields[RISCV_MODE_VU]);
+       dcsr = set_field(dcsr, CSR_DCSR_CETRIG, config->dcsr_cetrig);
        if (dcsr != original_dcsr &&
                        riscv_reg_set(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK)
                return ERROR_FAIL;
-       info->dcsr_ebreak_is_set = true;
+       // TODO: Read back the DCSR and check if these WARL bits are set as the 
user intended.
+       info->dcsr_register_is_set = true;
        return ERROR_OK;
 }
 
-static int halt_set_dcsr_ebreak(struct target *target)
+static int halt_set_dcsr_config(struct target *target)
 {
        RISCV_INFO(r);
        RISCV013_INFO(info);
-       LOG_TARGET_DEBUG(target, "Halt to set DCSR.ebreak*");
+       LOG_TARGET_DEBUG(target, "Halt to set dcsr config");
 
        /* Remove this hart from the halt group.  This won't work on all targets
         * because the debug spec allows halt groups to be hard-coded, but I
@@ -1750,7 +1752,7 @@ static int halt_set_dcsr_ebreak(struct target *target)
 
        r->prepped = true;
        if (riscv013_halt_go(target) != ERROR_OK ||
-                       set_dcsr_ebreak(target, false) != ERROR_OK ||
+                       set_dcsr_config(target, false) != ERROR_OK ||
                        riscv013_step_or_resume_current_hart(target, false) != 
ERROR_OK) {
                result = ERROR_FAIL;
        } else {
@@ -2139,7 +2141,7 @@ static int examine(struct target *target)
        if (result != ERROR_OK)
                return result;
 
-       if (set_dcsr_ebreak(target, false) != ERROR_OK)
+       if (set_dcsr_config(target, false) != ERROR_OK)
                return ERROR_FAIL;
 
        if (state_at_examine_start == RISCV_STATE_RUNNING) {
@@ -2786,7 +2788,7 @@ static int riscv013_get_hart_state(struct target *target, 
enum riscv_hart_state
                return ERROR_FAIL;
        if (get_field(dmstatus, DM_DMSTATUS_ANYHAVERESET)) {
                LOG_TARGET_INFO(target, "Hart unexpectedly reset!");
-               info->dcsr_ebreak_is_set = false;
+               info->dcsr_register_is_set = false;
                /* TODO: Can we make this more obvious to eg. a gdb user? */
                uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE |
                        DM_DMCONTROL_ACKHAVERESET;
@@ -2837,17 +2839,17 @@ static int handle_became_unavailable(struct target 
*target,
 
        riscv_reg_cache_invalidate_all(target);
 
-       info->dcsr_ebreak_is_set = false;
+       info->dcsr_register_is_set = false;
        return ERROR_OK;
 }
 
 static int tick(struct target *target)
 {
        RISCV013_INFO(info);
-       if (!info->dcsr_ebreak_is_set &&
+       if (!info->dcsr_register_is_set &&
                        target->state == TARGET_RUNNING &&
                        target_was_examined(target))
-               return halt_set_dcsr_ebreak(target);
+               return halt_set_dcsr_config(target);
        return ERROR_OK;
 }
 
@@ -2946,13 +2948,13 @@ static int assert_reset(struct target *target)
        return riscv013_invalidate_cached_progbuf(target);
 }
 
-static bool dcsr_ebreak_config_equals_reset_value(const struct target *target)
+static bool dcsr_config_equals_reset_value(const struct target *target)
 {
        const struct riscv_private_config * const config = 
riscv_private_config(target);
        for (int i = 0; i < N_RISCV_MODE; ++i)
                if (config->dcsr_ebreak_fields[i])
                        return false;
-       return true;
+       return !config->dcsr_cetrig;
 }
 
 static int deassert_reset(struct target *target)
@@ -3030,7 +3032,7 @@ static int deassert_reset(struct target *target)
                target->state = TARGET_RUNNING;
                target->debug_reason = DBG_REASON_NOTHALTED;
        }
-       info->dcsr_ebreak_is_set = 
dcsr_ebreak_config_equals_reset_value(target);
+       info->dcsr_register_is_set = dcsr_config_equals_reset_value(target);
        return ERROR_OK;
 }
 
@@ -5381,6 +5383,16 @@ static enum riscv_halt_reason 
riscv013_halt_reason(struct target *target)
                return RISCV_HALT_INTERRUPT;
        case CSR_DCSR_CAUSE_GROUP:
                return RISCV_HALT_GROUP;
+       case CSR_DCSR_CAUSE_OTHER:
+               switch (get_field(dcsr, CSR_DCSR_EXTCAUSE)) {
+               case 0:
+                       LOG_TARGET_WARNING(target, "halted because of hart in a 
critical error state.");
+                       return RISCV_HALT_CRITICAL_ERROR;
+               default:
+                       LOG_TARGET_ERROR(target, "Unknown DCSR extcause field: 
0x%"
+                                       PRIx64, get_field(dcsr, 
CSR_DCSR_EXTCAUSE));
+                       return RISCV_HALT_UNKNOWN;
+               }
        }
 
        LOG_TARGET_ERROR(target, "Unknown DCSR cause field: 0x%" PRIx64, 
get_field(dcsr, CSR_DCSR_CAUSE));
@@ -5476,7 +5488,7 @@ static int riscv013_on_step_or_resume(struct target 
*target, bool step)
                if (execute_autofence(target) != ERROR_OK)
                        return ERROR_FAIL;
 
-       if (set_dcsr_ebreak(target, step) != ERROR_OK)
+       if (set_dcsr_config(target, step) != ERROR_OK)
                return ERROR_FAIL;
 
        if (riscv_reg_flush_all(target) != ERROR_OK)
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 8054a1c9b7..bfa8addde0 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -486,6 +486,8 @@ static struct riscv_private_config 
*alloc_default_riscv_private_config(void)
        for (unsigned int i = 0; i < ARRAY_SIZE(config->dcsr_ebreak_fields); 
++i)
                config->dcsr_ebreak_fields[i] = true;
 
+       config->dcsr_cetrig = true;
+
        return config;
 }
 
@@ -525,6 +527,15 @@ static struct jim_nvp nvp_ebreak_mode_opts[] = {
        { .name = NULL, .value = RISCV_EBREAK_MODE_INVALID }
 };
 
+
+#define RISCV_CETRIG_INVALID -1
+
+static struct jim_nvp nvp_cetrig_opts[] = {
+       { .name = "disable", .value = false },
+       { .name = "enable", .value = true },
+       { .name = NULL, .value = RISCV_CETRIG_INVALID }
+};
+
 static int jim_configure_ebreak(struct riscv_private_config *config, struct 
jim_getopt_info *goi)
 {
        if (goi->argc == 0) {
@@ -611,13 +622,42 @@ static int jim_report_ebreak_config(const struct 
riscv_private_config *config,
        return JIM_OK;
 }
 
+static int jim_configure_cetrig(struct riscv_private_config *config,
+               struct jim_getopt_info *goi)
+{
+       if (goi->argc == 0) {
+               Jim_WrongNumArgs(goi->interp, 1, goi->argv - 1,
+                               "?disable|enable?");
+               return JIM_ERR;
+       }
+
+       struct jim_nvp *opt_nvp;
+       if (jim_getopt_nvp(goi, nvp_cetrig_opts, &opt_nvp) != JIM_OK) {
+               jim_getopt_nvp_unknown(goi, nvp_cetrig_opts, /*hadprefix*/ 
true);
+               return JIM_ERR;
+       }
+       config->dcsr_cetrig = opt_nvp->value;
+       return JIM_OK;
+}
+
+static int jim_report_cetrig_config(const struct riscv_private_config *config,
+               Jim_Interp *interp)
+{
+       const char *cetrig_opt = jim_nvp_value2name_simple(nvp_cetrig_opts,
+                       config->dcsr_cetrig)->name;
+       Jim_SetResultString(interp, cetrig_opt, strlen(cetrig_opt));
+       return JIM_OK;
+}
+
 enum riscv_cfg_opts {
        RISCV_CFG_EBREAK,
+       RISCV_CFG_CETRIG,
        RISCV_CFG_INVALID = -1
 };
 
 static struct jim_nvp nvp_config_opts[] = {
        { .name = "-ebreak", .value = RISCV_CFG_EBREAK },
+       { .name = "-cetrig", .value = RISCV_CFG_CETRIG },
        { .name = NULL, .value = RISCV_CFG_INVALID }
 };
 
@@ -654,6 +694,10 @@ static int riscv_jim_configure(struct target *target,
                return goi->is_configure
                        ? jim_configure_ebreak(config, goi)
                        : jim_report_ebreak_config(config, goi->interp);
+       case RISCV_CFG_CETRIG:
+               return goi->is_configure
+                       ? jim_configure_cetrig(config, goi)
+                       : jim_report_cetrig_config(config, goi->interp);
        default:
                assert(false && "'jim_getopt_nvp' should have returned an 
error.");
        }
@@ -2617,6 +2661,7 @@ static int set_debug_reason(struct target *target, enum 
riscv_halt_reason halt_r
                break;
        case RISCV_HALT_INTERRUPT:
        case RISCV_HALT_GROUP:
+       case RISCV_HALT_CRITICAL_ERROR:
                target->debug_reason = DBG_REASON_DBGRQ;
                break;
        case RISCV_HALT_SINGLESTEP:
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 2a0a9b95f0..d1a72c88e5 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -75,6 +75,7 @@ enum riscv_halt_reason {
        RISCV_HALT_TRIGGER,
        RISCV_HALT_UNKNOWN,
        RISCV_HALT_GROUP,
+       RISCV_HALT_CRITICAL_ERROR,
        RISCV_HALT_ERROR
 };
 
@@ -378,6 +379,7 @@ enum riscv_priv_mode {
 
 struct riscv_private_config {
        bool dcsr_ebreak_fields[N_RISCV_MODE];
+       bool dcsr_cetrig;
 };
 
 static inline struct riscv_private_config

-- 

Reply via email to