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/+/9694
-- gerrit commit 6192e3e2e050aaf5ac7f8e84c92abe9044b51947 Author: Zane Leung <[email protected]> Date: Tue Jun 16 11:24:49 2026 +0800 target/riscv: add `-check-dbgbase` control Introduce RISC-V-sepecific `configure` parameter `-check-dbgbase` to control whether OpenOCD verifies DM address (dbgbase) existence by reading nextdm registers. In systems where certain DMs may be powered down, reading their nextdm registers fails. The -check-dbgbase option allows users to disable verification and use the provided dbgbase address directly, enabling debugging of accessible DMs even when other DMs in the chain are powered down. Change-Id: Ie41cbf3ac4072f392d7a289c8bbf9a6057d09a91 Signed-off-by: Zane Leung <[email protected]> diff --git a/doc/openocd.texi b/doc/openocd.texi index 89900b06a7..dfe81aab0e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11750,6 +11750,22 @@ action pairs. @end itemize @end itemize +@itemize +@item @code{-check-dbgbase} @option{off}|@option{on} -- determines whether OpenOCD +should check that DM address (dbgbase) really exists by read @code{nextdm}. +Defaults to @option{on}. + +In some cases, certain DMs may be in a power-down state, preventing OpenOCD from +reading their @code{nextdm} registers. However, debugging of hardware on powered-on DMs +still needs to be supported. When @option{-check-dbgbase} is set to @option{off}, OpenOCD +will skip the verification check and use the provided @code{dbgbase} address directly, +allowing debugging of accessible DMs even when other DMs in the chain are powered down. + +@itemize +@item @code{cget} returns the currently configured state for @code{-check-dbgbase}. +@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 318a66ffe0..a5be868bec 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -537,6 +537,10 @@ static bool check_dbgbase_exists(struct target *target) unsigned int count = 1; riscv013_info_t *info = get_info(target); + struct riscv_private_config *config = target->private_config; + if (!config->check_dbgbase) + return ERROR_OK; + LOG_TARGET_DEBUG(target, "Searching for DM with DMI base address (dbgbase) = 0x%x", target->dbgbase); while (1) { uint32_t current_dm = next_dm; diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 30094b34b5..b2a6ab8a05 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->check_dbgbase = true; + return config; } @@ -525,6 +527,12 @@ static struct jim_nvp nvp_ebreak_mode_opts[] = { { .name = NULL, .value = RISCV_EBREAK_MODE_INVALID } }; +static struct jim_nvp nvp_on_off_opts[] = { + { .name = "off", .value = false }, + { .name = "on", .value = true }, + { .name = NULL, .value = -1 } +}; + static int jim_configure_ebreak(struct riscv_private_config *config, struct jim_getopt_info *goi) { if (goi->argc == 0) { @@ -613,11 +621,13 @@ static int jim_report_ebreak_config(const struct riscv_private_config *config, enum riscv_cfg_opts { RISCV_CFG_EBREAK, + RISCV_CFG_CHECK_DBGBASE, RISCV_CFG_INVALID = -1 }; static struct jim_nvp nvp_config_opts[] = { { .name = "-ebreak", .value = RISCV_CFG_EBREAK }, + { .name = "-check-dbgbase", .value = RISCV_CFG_CHECK_DBGBASE }, { .name = NULL, .value = RISCV_CFG_INVALID } }; @@ -654,10 +664,24 @@ 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_CHECK_DBGBASE: + if (goi->is_configure) { + struct jim_nvp *opt_nvp; + e = jim_getopt_nvp(goi, nvp_on_off_opts, &opt_nvp); + if (e != JIM_OK) { + jim_getopt_nvp_unknown(goi, nvp_on_off_opts, /*hadprefix*/ true); + return e; + } + config->check_dbgbase = opt_nvp->value; + } else { + Jim_SetResultString(goi->interp, + jim_nvp_value2name_simple(nvp_on_off_opts, config->check_dbgbase)->name, -1); + } + break; default: assert(false && "'jim_getopt_nvp' should have returned an error."); } - return JIM_ERR; + return JIM_OK; } static int riscv_init_target(struct command_context *cmd_ctx, diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 2a0a9b95f0..d73c64fd05 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -378,6 +378,7 @@ enum riscv_priv_mode { struct riscv_private_config { bool dcsr_ebreak_fields[N_RISCV_MODE]; + bool check_dbgbase; }; static inline struct riscv_private_config --
