Skip to content

Commit

Permalink
Merge pull request #918 from kr-sc/kr-sc/allow-to-query-status-dcsr-e…
Browse files Browse the repository at this point in the history
…break

openocd does not allow to query status of dcsr.ebreak{u,s,m}
  • Loading branch information
timsifive authored Sep 29, 2023
2 parents ef3be96 + ee2bc80 commit 75b5de6
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 38 deletions.
6 changes: 3 additions & 3 deletions doc/openocd.texi
Original file line number Diff line number Diff line change
Expand Up @@ -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.
@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
OpenOCD. When off, they generate a breakpoint exception handled internally.
@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
OpenOCD. When off, they generate a breakpoint exception handled internally.
@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
OpenOCD. When off, they generate a breakpoint exception handled internally.
@end deffn
Expand Down
14 changes: 8 additions & 6 deletions src/target/riscv/riscv-011.c
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,7 @@ static int maybe_write_tselect(struct target *target)

static int execute_resume(struct target *target, bool step)
{
RISCV_INFO(r);
riscv011_info_t *info = get_info(target);

LOG_DEBUG("step=%d", step);
Expand Down Expand Up @@ -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_EBREAKS, riscv_ebreaks);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, riscv_ebreaku);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, r->riscv_ebreakm);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, r->riscv_ebreaks);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, r->riscv_ebreaku);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1);
info->dcsr &= ~DCSR_HALT;

Expand Down Expand Up @@ -1936,6 +1937,7 @@ static int riscv011_resume(struct target *target, int current,

static int assert_reset(struct target *target)
{
RISCV_INFO(r);
riscv011_info_t *info = get_info(target);
/* TODO: Maybe what I implemented here is more like soft_reset_halt()? */

Expand All @@ -1949,9 +1951,9 @@ static int assert_reset(struct target *target)

/* Not sure what we should do when there are multiple cores.
* 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_EBREAKS, riscv_ebreaks);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, riscv_ebreaku);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, r->riscv_ebreakm);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, r->riscv_ebreaks);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, r->riscv_ebreaku);
info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1);
info->dcsr |= DCSR_HALT;
if (target->reset_halt)
Expand Down
11 changes: 6 additions & 5 deletions src/target/riscv/riscv-013.c
Original file line number Diff line number Diff line change
Expand Up @@ -1721,18 +1721,19 @@ static int set_dcsr_ebreak(struct target *target, bool step)
if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL;

RISCV_INFO(r);
RISCV013_INFO(info);
riscv_reg_t original_dcsr, dcsr;
/* We want to twiddle some bits in the debug CSR so debugging works. */
if (riscv_get_register(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK)
return ERROR_FAIL;
original_dcsr = dcsr;
dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, riscv_ebreakm);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, 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_EBREAKVS, 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_EBREAKM, r->riscv_ebreakm);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, r->riscv_ebreaks && riscv_supports_extension(target, 'S'));
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, r->riscv_ebreaku && riscv_supports_extension(target, 'U'));
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, r->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 &&
riscv_set_register(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK)
return ERROR_FAIL;
Expand Down
64 changes: 43 additions & 21 deletions src/target/riscv/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ int riscv_command_timeout_sec = DEFAULT_COMMAND_TIMEOUT_SEC;
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;

static bool riscv_enable_virt2phys = true;
bool riscv_ebreakm = true;
bool riscv_ebreaks = true;
bool riscv_ebreaku = true;

bool riscv_enable_virtual;

Expand Down Expand Up @@ -3748,32 +3745,53 @@ COMMAND_HANDLER(riscv_set_enable_virt2phys)

COMMAND_HANDLER(riscv_set_ebreakm)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR;
struct target *target = get_current_target(CMD_CTX);
RISCV_INFO(r);

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)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR;
struct target *target = get_current_target(CMD_CTX);
RISCV_INFO(r);

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)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR;
struct target *target = get_current_target(CMD_CTX);
RISCV_INFO(r);

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)
Expand Down Expand Up @@ -4452,23 +4470,23 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.name = "set_ebreakm",
.handler = riscv_set_ebreakm,
.mode = COMMAND_ANY,
.usage = "on|off",
.usage = "[on|off]",
.help = "Control dcsr.ebreakm. When off, M-mode ebreak instructions "
"don't trap to OpenOCD. Defaults to on."
},
{
.name = "set_ebreaks",
.handler = riscv_set_ebreaks,
.mode = COMMAND_ANY,
.usage = "on|off",
.usage = "[on|off]",
.help = "Control dcsr.ebreaks. When off, S-mode ebreak instructions "
"don't trap to OpenOCD. Defaults to on."
},
{
.name = "set_ebreaku",
.handler = riscv_set_ebreaku,
.mode = COMMAND_ANY,
.usage = "on|off",
.usage = "[on|off]",
.help = "Control dcsr.ebreaku. When off, U-mode ebreak instructions "
"don't trap to OpenOCD. Defaults to on."
},
Expand Down Expand Up @@ -4632,6 +4650,10 @@ static void riscv_info_init(struct target *target, struct riscv_info *r)
INIT_LIST_HEAD(&r->hide_csr);

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)
Expand Down
7 changes: 4 additions & 3 deletions src/target/riscv/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ struct riscv_info {
yes_no_maybe_t vsew64_supported;

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,
Expand Down Expand Up @@ -328,9 +332,6 @@ extern int riscv_command_timeout_sec;
extern int riscv_reset_timeout_sec;

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
* that provides that. */
Expand Down

0 comments on commit 75b5de6

Please sign in to comment.