Merge pull request #918 from kr-sc/kr-sc/allow-to-query-status-dcsr-ebreak

openocd does not allow to query status of dcsr.ebreak{u,s,m}
This commit is contained in:
Tim Newsome 2023-09-29 09:30:46 -07:00 committed by GitHub
commit 75b5de67df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 38 deletions

View File

@ -10856,17 +10856,17 @@ Keep in mind, disabling the option does not guarantee that single stepping will
To make that happen, dcsr.stepie would have to be written to 1 as well. To make that happen, dcsr.stepie would have to be written to 1 as well.
@end deffn @end deffn
@deffn {Command} {riscv set_ebreakm} on|off @deffn {Command} {riscv set_ebreakm} [on|off]
Control dcsr.ebreakm. When on (default), M-mode ebreak instructions trap to Control dcsr.ebreakm. When on (default), M-mode ebreak instructions trap to
OpenOCD. When off, they generate a breakpoint exception handled internally. OpenOCD. When off, they generate a breakpoint exception handled internally.
@end deffn @end deffn
@deffn {Command} {riscv set_ebreaks} on|off @deffn {Command} {riscv set_ebreaks} [on|off]
Control dcsr.ebreaks. When on (default), S-mode ebreak instructions trap to Control dcsr.ebreaks. When on (default), S-mode ebreak instructions trap to
OpenOCD. When off, they generate a breakpoint exception handled internally. OpenOCD. When off, they generate a breakpoint exception handled internally.
@end deffn @end deffn
@deffn {Command} {riscv set_ebreaku} on|off @deffn {Command} {riscv set_ebreaku} [on|off]
Control dcsr.ebreaku. When on (default), U-mode ebreak instructions trap to Control dcsr.ebreaku. When on (default), U-mode ebreak instructions trap to
OpenOCD. When off, they generate a breakpoint exception handled internally. OpenOCD. When off, they generate a breakpoint exception handled internally.
@end deffn @end deffn

View File

@ -1104,6 +1104,7 @@ static int maybe_write_tselect(struct target *target)
static int execute_resume(struct target *target, bool step) static int execute_resume(struct target *target, bool step)
{ {
RISCV_INFO(r);
riscv011_info_t *info = get_info(target); riscv011_info_t *info = get_info(target);
LOG_DEBUG("step=%d", step); LOG_DEBUG("step=%d", step);
@ -1135,9 +1136,9 @@ static int execute_resume(struct target *target, bool step)
} }
} }
info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, riscv_ebreakm); info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, r->riscv_ebreakm);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, riscv_ebreaks); info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, r->riscv_ebreaks);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, riscv_ebreaku); info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, r->riscv_ebreaku);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1); info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1);
info->dcsr &= ~DCSR_HALT; info->dcsr &= ~DCSR_HALT;
@ -1936,6 +1937,7 @@ static int riscv011_resume(struct target *target, int current,
static int assert_reset(struct target *target) static int assert_reset(struct target *target)
{ {
RISCV_INFO(r);
riscv011_info_t *info = get_info(target); riscv011_info_t *info = get_info(target);
/* TODO: Maybe what I implemented here is more like soft_reset_halt()? */ /* TODO: Maybe what I implemented here is more like soft_reset_halt()? */
@ -1949,9 +1951,9 @@ static int assert_reset(struct target *target)
/* Not sure what we should do when there are multiple cores. /* Not sure what we should do when there are multiple cores.
* Here just reset the single hart we're talking to. */ * Here just reset the single hart we're talking to. */
info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, riscv_ebreakm); info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, r->riscv_ebreakm);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, riscv_ebreaks); info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, r->riscv_ebreaks);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, riscv_ebreaku); info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, r->riscv_ebreaku);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1); info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1);
info->dcsr |= DCSR_HALT; info->dcsr |= DCSR_HALT;
if (target->reset_halt) if (target->reset_halt)

View File

@ -1721,6 +1721,7 @@ static int set_dcsr_ebreak(struct target *target, bool step)
if (dm013_select_target(target) != ERROR_OK) if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
RISCV_INFO(r);
RISCV013_INFO(info); RISCV013_INFO(info);
riscv_reg_t original_dcsr, dcsr; riscv_reg_t original_dcsr, dcsr;
/* We want to twiddle some bits in the debug CSR so debugging works. */ /* We want to twiddle some bits in the debug CSR so debugging works. */
@ -1728,11 +1729,11 @@ static int set_dcsr_ebreak(struct target *target, bool step)
return ERROR_FAIL; return ERROR_FAIL;
original_dcsr = dcsr; original_dcsr = dcsr;
dcsr = set_field(dcsr, CSR_DCSR_STEP, step); dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, riscv_ebreakm); dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, r->riscv_ebreakm);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, riscv_ebreaks && riscv_supports_extension(target, 'S')); dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, r->riscv_ebreaks && riscv_supports_extension(target, 'S'));
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, riscv_ebreaku && riscv_supports_extension(target, 'U')); dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, r->riscv_ebreaku && riscv_supports_extension(target, 'U'));
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, riscv_ebreaku && riscv_supports_extension(target, 'H')); dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, r->riscv_ebreaku && riscv_supports_extension(target, 'H'));
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, riscv_ebreaku && riscv_supports_extension(target, 'H')); dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, r->riscv_ebreaku && riscv_supports_extension(target, 'H'));
if (dcsr != original_dcsr && if (dcsr != original_dcsr &&
riscv_set_register(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK) riscv_set_register(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;

View File

@ -135,9 +135,6 @@ int riscv_command_timeout_sec = DEFAULT_COMMAND_TIMEOUT_SEC;
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC; int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
static bool riscv_enable_virt2phys = true; static bool riscv_enable_virt2phys = true;
bool riscv_ebreakm = true;
bool riscv_ebreaks = true;
bool riscv_ebreaku = true;
bool riscv_enable_virtual; bool riscv_enable_virtual;
@ -3748,32 +3745,53 @@ COMMAND_HANDLER(riscv_set_enable_virt2phys)
COMMAND_HANDLER(riscv_set_ebreakm) COMMAND_HANDLER(riscv_set_ebreakm)
{ {
if (CMD_ARGC != 1) { struct target *target = get_current_target(CMD_CTX);
LOG_ERROR("Command takes exactly 1 parameter"); RISCV_INFO(r);
return ERROR_COMMAND_SYNTAX_ERROR;
if (CMD_ARGC == 0) {
command_print(CMD, "riscv_ebreakm enabled: %s", r->riscv_ebreakm ? "on" : "off");
return ERROR_OK;
} else if (CMD_ARGC == 1) {
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], r->riscv_ebreakm);
return ERROR_OK;
} }
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_ebreakm);
return ERROR_OK; LOG_ERROR("Command takes 0 or 1 parameters");
return ERROR_COMMAND_SYNTAX_ERROR;
} }
COMMAND_HANDLER(riscv_set_ebreaks) COMMAND_HANDLER(riscv_set_ebreaks)
{ {
if (CMD_ARGC != 1) { struct target *target = get_current_target(CMD_CTX);
LOG_ERROR("Command takes exactly 1 parameter"); RISCV_INFO(r);
return ERROR_COMMAND_SYNTAX_ERROR;
if (CMD_ARGC == 0) {
command_print(CMD, "riscv_ebreaks enabled: %s", r->riscv_ebreaks ? "on" : "off");
return ERROR_OK;
} else if (CMD_ARGC == 1) {
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], r->riscv_ebreaks);
return ERROR_OK;
} }
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_ebreaks);
return ERROR_OK; LOG_ERROR("Command takes 0 or 1 parameters");
return ERROR_COMMAND_SYNTAX_ERROR;
} }
COMMAND_HANDLER(riscv_set_ebreaku) COMMAND_HANDLER(riscv_set_ebreaku)
{ {
if (CMD_ARGC != 1) { struct target *target = get_current_target(CMD_CTX);
LOG_ERROR("Command takes exactly 1 parameter"); RISCV_INFO(r);
return ERROR_COMMAND_SYNTAX_ERROR;
if (CMD_ARGC == 0) {
command_print(CMD, "riscv_ebreaku enabled: %s", r->riscv_ebreaku ? "on" : "off");
return ERROR_OK;
} else if (CMD_ARGC == 1) {
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], r->riscv_ebreaku);
return ERROR_OK;
} }
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_ebreaku);
return ERROR_OK; LOG_ERROR("Command takes 0 or 1 parameters");
return ERROR_COMMAND_SYNTAX_ERROR;
} }
COMMAND_HELPER(riscv_clear_trigger, int trigger_id, const char *name) COMMAND_HELPER(riscv_clear_trigger, int trigger_id, const char *name)
@ -4452,7 +4470,7 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.name = "set_ebreakm", .name = "set_ebreakm",
.handler = riscv_set_ebreakm, .handler = riscv_set_ebreakm,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "on|off", .usage = "[on|off]",
.help = "Control dcsr.ebreakm. When off, M-mode ebreak instructions " .help = "Control dcsr.ebreakm. When off, M-mode ebreak instructions "
"don't trap to OpenOCD. Defaults to on." "don't trap to OpenOCD. Defaults to on."
}, },
@ -4460,7 +4478,7 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.name = "set_ebreaks", .name = "set_ebreaks",
.handler = riscv_set_ebreaks, .handler = riscv_set_ebreaks,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "on|off", .usage = "[on|off]",
.help = "Control dcsr.ebreaks. When off, S-mode ebreak instructions " .help = "Control dcsr.ebreaks. When off, S-mode ebreak instructions "
"don't trap to OpenOCD. Defaults to on." "don't trap to OpenOCD. Defaults to on."
}, },
@ -4468,7 +4486,7 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.name = "set_ebreaku", .name = "set_ebreaku",
.handler = riscv_set_ebreaku, .handler = riscv_set_ebreaku,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "on|off", .usage = "[on|off]",
.help = "Control dcsr.ebreaku. When off, U-mode ebreak instructions " .help = "Control dcsr.ebreaku. When off, U-mode ebreak instructions "
"don't trap to OpenOCD. Defaults to on." "don't trap to OpenOCD. Defaults to on."
}, },
@ -4632,6 +4650,10 @@ static void riscv_info_init(struct target *target, struct riscv_info *r)
INIT_LIST_HEAD(&r->hide_csr); INIT_LIST_HEAD(&r->hide_csr);
r->vsew64_supported = YNM_MAYBE; r->vsew64_supported = YNM_MAYBE;
r->riscv_ebreakm = true;
r->riscv_ebreaks = true;
r->riscv_ebreaku = true;
} }
static int riscv_resume_go_all_harts(struct target *target) static int riscv_resume_go_all_harts(struct target *target)

View File

@ -297,6 +297,10 @@ struct riscv_info {
yes_no_maybe_t vsew64_supported; yes_no_maybe_t vsew64_supported;
bool range_trigger_fallback_encountered; bool range_trigger_fallback_encountered;
bool riscv_ebreakm;
bool riscv_ebreaks;
bool riscv_ebreaku;
}; };
COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key, COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key,
@ -328,9 +332,6 @@ extern int riscv_command_timeout_sec;
extern int riscv_reset_timeout_sec; extern int riscv_reset_timeout_sec;
extern bool riscv_enable_virtual; extern bool riscv_enable_virtual;
extern bool riscv_ebreakm;
extern bool riscv_ebreaks;
extern bool riscv_ebreaku;
/* Everything needs the RISC-V specific info structure, so here's a nice macro /* Everything needs the RISC-V specific info structure, so here's a nice macro
* that provides that. */ * that provides that. */