Skip to content

Commit 2210897

Browse files
authored
Merge pull request #1168 from en-sc/en-sc/ebreak
target/riscv: new `ebreak` controls
2 parents eb9ba21 + b9d9d1a commit 2210897

File tree

6 files changed

+295
-80
lines changed

6 files changed

+295
-80
lines changed

doc/openocd.texi

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11225,6 +11225,25 @@ follows:
1122511225
</feature>
1122611226
@end example
1122711227

11228+
@subsection RISC-V @code{$target_name configure} options
11229+
@itemize
11230+
@item @code{-ebreak} [@option{m}|@option{s}|@option{u}|@option{vs}|@option{vu}]
11231+
@option{exception}|@option{halt} -- sets the desired behavior of @code{ebreak}
11232+
instruction on the target. Defaults to @option{halt} in all execution modes.
11233+
11234+
@itemize
11235+
@item The last argument specifies which action should be taken when a hart
11236+
executes a @code{ebreak}.
11237+
11238+
@item The first argument specifies in which execution mode the @code{ebreak}
11239+
behavior should change. If this option is omitted the configuration affects
11240+
all execution modes.
11241+
11242+
@item @code{cget} returns a TCL @code{dict} of execution mode - @code{ebreak}
11243+
action pairs.
11244+
@end itemize
11245+
@end itemize
11246+
1122811247
@subsection RISC-V Debug Configuration Commands
1122911248

1123011249
@deffn {Command} {riscv dump_sample_buf} [base64]
@@ -11434,21 +11453,6 @@ Keep in mind, disabling the option does not guarantee that single stepping will
1143411453
To make that happen, dcsr.stepie would have to be written to 1 as well.
1143511454
@end deffn
1143611455

11437-
@deffn {Command} {riscv set_ebreakm} [on|off]
11438-
Control dcsr.ebreakm. When on (default), M-mode ebreak instructions trap to
11439-
OpenOCD. When off, they generate a breakpoint exception handled internally.
11440-
@end deffn
11441-
11442-
@deffn {Command} {riscv set_ebreaks} [on|off]
11443-
Control dcsr.ebreaks. When on (default), S-mode ebreak instructions trap to
11444-
OpenOCD. When off, they generate a breakpoint exception handled internally.
11445-
@end deffn
11446-
11447-
@deffn {Command} {riscv set_ebreaku} [on|off]
11448-
Control dcsr.ebreaku. When on (default), U-mode ebreak instructions trap to
11449-
OpenOCD. When off, they generate a breakpoint exception handled internally.
11450-
@end deffn
11451-
1145211456
The commands below can be used to prevent OpenOCD from using certain RISC-V trigger features.
1145311457
For example in cases when there are known issues in the target hardware.
1145411458

src/target/riscv/riscv-011.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,9 +1074,18 @@ static int maybe_write_tselect(struct target *target)
10741074
return ERROR_OK;
10751075
}
10761076

1077+
static uint64_t set_ebreakx_fields(uint64_t dcsr, const struct target *target)
1078+
{
1079+
const struct riscv_private_config * const config = riscv_private_config(target);
1080+
dcsr = set_field(dcsr, DCSR_EBREAKM, config->dcsr_ebreak_fields[RISCV_MODE_M]);
1081+
dcsr = set_field(dcsr, DCSR_EBREAKS, config->dcsr_ebreak_fields[RISCV_MODE_S]);
1082+
dcsr = set_field(dcsr, DCSR_EBREAKU, config->dcsr_ebreak_fields[RISCV_MODE_U]);
1083+
dcsr = set_field(dcsr, DCSR_EBREAKH, 1);
1084+
return dcsr;
1085+
}
1086+
10771087
static int execute_resume(struct target *target, bool step)
10781088
{
1079-
RISCV_INFO(r);
10801089
riscv011_info_t *info = get_info(target);
10811090

10821091
LOG_DEBUG("step=%d", step);
@@ -1108,10 +1117,7 @@ static int execute_resume(struct target *target, bool step)
11081117
}
11091118
}
11101119

1111-
info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, r->riscv_ebreakm);
1112-
info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, r->riscv_ebreaks);
1113-
info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, r->riscv_ebreaku);
1114-
info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1);
1120+
info->dcsr = set_ebreakx_fields(info->dcsr, target);
11151121
info->dcsr &= ~DCSR_HALT;
11161122

11171123
if (step)
@@ -1928,7 +1934,6 @@ static int riscv011_resume(struct target *target, int current,
19281934

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

@@ -1942,10 +1947,7 @@ static int assert_reset(struct target *target)
19421947

19431948
/* Not sure what we should do when there are multiple cores.
19441949
* Here just reset the single hart we're talking to. */
1945-
info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, r->riscv_ebreakm);
1946-
info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, r->riscv_ebreaks);
1947-
info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, r->riscv_ebreaku);
1948-
info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1);
1950+
info->dcsr = set_ebreakx_fields(info->dcsr, target);
19491951
info->dcsr |= DCSR_HALT;
19501952
if (target->reset_halt)
19511953
info->dcsr |= DCSR_NDRESET;

src/target/riscv/riscv-013.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,19 +1611,19 @@ static int set_dcsr_ebreak(struct target *target, bool step)
16111611
if (dm013_select_target(target) != ERROR_OK)
16121612
return ERROR_FAIL;
16131613

1614-
RISCV_INFO(r);
16151614
RISCV013_INFO(info);
16161615
riscv_reg_t original_dcsr, dcsr;
16171616
/* We want to twiddle some bits in the debug CSR so debugging works. */
16181617
if (riscv_reg_get(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK)
16191618
return ERROR_FAIL;
16201619
original_dcsr = dcsr;
16211620
dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
1622-
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, r->riscv_ebreakm);
1623-
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, r->riscv_ebreaks && riscv_supports_extension(target, 'S'));
1624-
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, r->riscv_ebreaku && riscv_supports_extension(target, 'U'));
1625-
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, r->riscv_ebreaku && riscv_supports_extension(target, 'H'));
1626-
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, r->riscv_ebreaku && riscv_supports_extension(target, 'H'));
1621+
const struct riscv_private_config * const config = riscv_private_config(target);
1622+
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, config->dcsr_ebreak_fields[RISCV_MODE_M]);
1623+
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, config->dcsr_ebreak_fields[RISCV_MODE_S]);
1624+
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, config->dcsr_ebreak_fields[RISCV_MODE_U]);
1625+
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, config->dcsr_ebreak_fields[RISCV_MODE_VS]);
1626+
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, config->dcsr_ebreak_fields[RISCV_MODE_VU]);
16271627
if (dcsr != original_dcsr &&
16281628
riscv_reg_set(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK)
16291629
return ERROR_FAIL;
@@ -2858,8 +2858,11 @@ static int assert_reset(struct target *target)
28582858

28592859
static bool dcsr_ebreak_config_equals_reset_value(const struct target *target)
28602860
{
2861-
RISCV_INFO(r);
2862-
return !(r->riscv_ebreakm || r->riscv_ebreaks || r->riscv_ebreaku);
2861+
const struct riscv_private_config * const config = riscv_private_config(target);
2862+
for (int i = 0; i < N_RISCV_MODE; ++i)
2863+
if (config->dcsr_ebreak_fields[i])
2864+
return false;
2865+
return true;
28632866
}
28642867

28652868
static int deassert_reset(struct target *target)

0 commit comments

Comments
 (0)