Give control over dcsr.ebreak[msu] bits. (#451)

This allows a user to debug code that uses software breakpoints itself.

Change-Id: If40cb626354e11703017cdf8c5919a31e83ebc3f
This commit is contained in:
Tim Newsome 2020-02-20 13:58:15 -08:00 committed by GitHub
parent 95462a8a35
commit 1449af5bdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 6 deletions

View File

@ -9511,6 +9511,21 @@ Enable or disable use of a BSCAN tunnel to reach DM. Supply the width of
the DM transport TAP's instruction register to enable. Supply a value of 0 to disable. the DM transport TAP's instruction register to enable. Supply a value of 0 to disable.
@end deffn @end deffn
@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
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
Control dcsr.ebreaku. When on (default), U-mode ebreak instructions trap to
OpenOCD. When off, they generate a breakpoint exception handled internally.
@end deffn
@subsection RISC-V Authentication Commands @subsection RISC-V Authentication Commands
The following commands can be used to authenticate to a RISC-V system. Eg. a The following commands can be used to authenticate to a RISC-V system. Eg. a

View File

@ -1114,7 +1114,10 @@ static int execute_resume(struct target *target, bool step)
} }
} }
info->dcsr |= DCSR_EBREAKM | DCSR_EBREAKH | DCSR_EBREAKS | DCSR_EBREAKU; 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_EBREAKH, 1);
info->dcsr &= ~DCSR_HALT; info->dcsr &= ~DCSR_HALT;
if (step) if (step)
@ -1946,8 +1949,11 @@ 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 |= DCSR_EBREAKM | DCSR_EBREAKH | DCSR_EBREAKS | info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, riscv_ebreakm);
DCSR_EBREAKU | DCSR_HALT; 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_EBREAKH, 1);
info->dcsr |= DCSR_HALT;
if (target->reset_halt) if (target->reset_halt)
info->dcsr |= DCSR_NDRESET; info->dcsr |= DCSR_NDRESET;
else else

View File

@ -4310,9 +4310,9 @@ static int riscv013_on_step_or_resume(struct target *target, bool step)
if (result != ERROR_OK) if (result != ERROR_OK)
return result; return result;
dcsr = set_field(dcsr, CSR_DCSR_STEP, step); dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, 1); dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, riscv_ebreakm);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, 1); dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, riscv_ebreaks);
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, 1); dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, riscv_ebreaku);
return riscv_set_register(target, GDB_REGNO_DCSR, dcsr); return riscv_set_register(target, GDB_REGNO_DCSR, dcsr);
} }

View File

@ -252,6 +252,9 @@ int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
bool riscv_prefer_sba; bool riscv_prefer_sba;
bool riscv_enable_virt2phys = true; 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;
@ -2465,6 +2468,36 @@ COMMAND_HANDLER(riscv_set_enable_virt2phys)
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(riscv_set_ebreakm)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_ebreakm);
return ERROR_OK;
}
COMMAND_HANDLER(riscv_set_ebreaks)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_ebreaks);
return ERROR_OK;
}
COMMAND_HANDLER(riscv_set_ebreaku)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_ebreaku);
return ERROR_OK;
}
static const struct command_registration riscv_exec_command_handlers[] = { static const struct command_registration riscv_exec_command_handlers[] = {
{ {
.name = "test_compliance", .name = "test_compliance",
@ -2607,6 +2640,30 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.usage = "riscv set_enable_virt2phys on|off", .usage = "riscv set_enable_virt2phys on|off",
.help = "Enable translation from virtual address to physical address." .help = "Enable translation from virtual address to physical address."
}, },
{
.name = "set_ebreakm",
.handler = riscv_set_ebreakm,
.mode = COMMAND_ANY,
.usage = "riscv set_ebreakm 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 = "riscv set_ebreaks 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 = "riscv set_ebreaku on|off",
.help = "Control dcsr.ebreaku. When off, U-mode ebreak instructions "
"don't trap to OpenOCD. Defaults to on."
},
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@ -195,6 +195,9 @@ extern int riscv_reset_timeout_sec;
extern bool riscv_prefer_sba; extern bool riscv_prefer_sba;
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. */