Skip to content

Commit fb914e0

Browse files
committed
target/riscv: add cetrig control
Introduce RISC-V-sepecific `configure` parameter `-cetrig`
1 parent 6a30484 commit fb914e0

File tree

4 files changed

+87
-18
lines changed

4 files changed

+87
-18
lines changed

doc/openocd.texi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11437,6 +11437,15 @@ action pairs.
1143711437
@end itemize
1143811438
@end itemize
1143911439

11440+
@itemize
11441+
@item @code{-cetrig} @option{disable}|@option{enable} -- determines how OpenOCD should
11442+
configure the @code{cetrig} in the dcsr register. Defaults to @option{disable}.
11443+
11444+
@itemize
11445+
@item @code{cget} returns the currently configured state for @code{cetrig}.
11446+
@end itemize
11447+
@end itemize
11448+
1144011449
@subsection RISC-V Debug Configuration Commands
1144111450

1144211451
@deffn {Command} {riscv dump_sample_buf} [base64]

src/target/riscv/riscv-013.c

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ typedef struct {
251251
/* This target was selected using hasel. */
252252
bool selected;
253253

254-
/* When false, we need to set dcsr.ebreak*, halting the target if that's
255-
* necessary. */
256-
bool dcsr_ebreak_is_set;
254+
/* When false, we need to configure certain bits in the dcsr register.
255+
* To do that, we may momentarily halt the target, if necessary. */
256+
bool dcsr_register_is_set;
257257

258258
/* This hart was placed into a halt group in examine(). */
259259
bool haltgroup_supported;
@@ -1674,9 +1674,9 @@ static int wait_for_authbusy(struct target *target, uint32_t *dmstatus)
16741674
return ERROR_OK;
16751675
}
16761676

1677-
static int set_dcsr_ebreak(struct target *target, bool step)
1677+
static int set_dcsr_config(struct target *target, bool step)
16781678
{
1679-
LOG_TARGET_DEBUG(target, "Set dcsr.ebreak*");
1679+
LOG_TARGET_DEBUG(target, "Set dcsr config");
16801680

16811681
if (dm013_select_target(target) != ERROR_OK)
16821682
return ERROR_FAIL;
@@ -1694,18 +1694,20 @@ static int set_dcsr_ebreak(struct target *target, bool step)
16941694
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, config->dcsr_ebreak_fields[RISCV_MODE_U]);
16951695
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, config->dcsr_ebreak_fields[RISCV_MODE_VS]);
16961696
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, config->dcsr_ebreak_fields[RISCV_MODE_VU]);
1697+
dcsr = set_field(dcsr, CSR_DCSR_CETRIG, config->dcsr_cetrig);
16971698
if (dcsr != original_dcsr &&
16981699
riscv_reg_set(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK)
16991700
return ERROR_FAIL;
1700-
info->dcsr_ebreak_is_set = true;
1701+
// TODO: Read back the DCSR and check if these WARL bits are set as the user intended.
1702+
info->dcsr_register_is_set = true;
17011703
return ERROR_OK;
17021704
}
17031705

1704-
static int halt_set_dcsr_ebreak(struct target *target)
1706+
static int halt_set_dcsr_config(struct target *target)
17051707
{
17061708
RISCV_INFO(r);
17071709
RISCV013_INFO(info);
1708-
LOG_TARGET_DEBUG(target, "Halt to set DCSR.ebreak*");
1710+
LOG_TARGET_DEBUG(target, "Halt to set dcsr config");
17091711

17101712
/* Remove this hart from the halt group. This won't work on all targets
17111713
* because the debug spec allows halt groups to be hard-coded, but I
@@ -1743,7 +1745,7 @@ static int halt_set_dcsr_ebreak(struct target *target)
17431745

17441746
r->prepped = true;
17451747
if (riscv013_halt_go(target) != ERROR_OK ||
1746-
set_dcsr_ebreak(target, false) != ERROR_OK ||
1748+
set_dcsr_config(target, false) != ERROR_OK ||
17471749
riscv013_step_or_resume_current_hart(target, false) != ERROR_OK) {
17481750
result = ERROR_FAIL;
17491751
} else {
@@ -2132,7 +2134,7 @@ static int examine(struct target *target)
21322134
if (result != ERROR_OK)
21332135
return result;
21342136

2135-
if (set_dcsr_ebreak(target, false) != ERROR_OK)
2137+
if (set_dcsr_config(target, false) != ERROR_OK)
21362138
return ERROR_FAIL;
21372139

21382140
if (state_at_examine_start == RISCV_STATE_RUNNING) {
@@ -2779,7 +2781,7 @@ static int riscv013_get_hart_state(struct target *target, enum riscv_hart_state
27792781
return ERROR_FAIL;
27802782
if (get_field(dmstatus, DM_DMSTATUS_ANYHAVERESET)) {
27812783
LOG_TARGET_INFO(target, "Hart unexpectedly reset!");
2782-
info->dcsr_ebreak_is_set = false;
2784+
info->dcsr_register_is_set = false;
27832785
/* TODO: Can we make this more obvious to eg. a gdb user? */
27842786
uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE |
27852787
DM_DMCONTROL_ACKHAVERESET;
@@ -2830,17 +2832,17 @@ static int handle_became_unavailable(struct target *target,
28302832

28312833
riscv_reg_cache_invalidate_all(target);
28322834

2833-
info->dcsr_ebreak_is_set = false;
2835+
info->dcsr_register_is_set = false;
28342836
return ERROR_OK;
28352837
}
28362838

28372839
static int tick(struct target *target)
28382840
{
28392841
RISCV013_INFO(info);
2840-
if (!info->dcsr_ebreak_is_set &&
2842+
if (!info->dcsr_register_is_set &&
28412843
target->state == TARGET_RUNNING &&
28422844
target_was_examined(target))
2843-
return halt_set_dcsr_ebreak(target);
2845+
return halt_set_dcsr_config(target);
28442846
return ERROR_OK;
28452847
}
28462848

@@ -2939,13 +2941,13 @@ static int assert_reset(struct target *target)
29392941
return riscv013_invalidate_cached_progbuf(target);
29402942
}
29412943

2942-
static bool dcsr_ebreak_config_equals_reset_value(const struct target *target)
2944+
static bool dcsr_config_equals_reset_value(const struct target *target)
29432945
{
29442946
const struct riscv_private_config * const config = riscv_private_config(target);
29452947
for (int i = 0; i < N_RISCV_MODE; ++i)
29462948
if (config->dcsr_ebreak_fields[i])
29472949
return false;
2948-
return true;
2950+
return !config->dcsr_cetrig;
29492951
}
29502952

29512953
static int deassert_reset(struct target *target)
@@ -3023,7 +3025,7 @@ static int deassert_reset(struct target *target)
30233025
target->state = TARGET_RUNNING;
30243026
target->debug_reason = DBG_REASON_NOTHALTED;
30253027
}
3026-
info->dcsr_ebreak_is_set = dcsr_ebreak_config_equals_reset_value(target);
3028+
info->dcsr_register_is_set = dcsr_config_equals_reset_value(target);
30273029
return ERROR_OK;
30283030
}
30293031

@@ -5367,6 +5369,17 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
53675369
return RISCV_HALT_INTERRUPT;
53685370
case CSR_DCSR_CAUSE_GROUP:
53695371
return RISCV_HALT_GROUP;
5372+
case CSR_DCSR_CAUSE_OTHER:
5373+
switch (get_field(dcsr, CSR_DCSR_EXTCAUSE))
5374+
{
5375+
case 0:
5376+
LOG_TARGET_WARNING(target, "halted because of hart in a critical error state.");
5377+
return RISCV_HALT_CRITICAL_ERROR;
5378+
default:
5379+
LOG_TARGET_ERROR(target, "Unknown DCSR extcause field: 0x%"
5380+
PRIx64, get_field(dcsr, CSR_DCSR_EXTCAUSE));
5381+
return RISCV_HALT_UNKNOWN;
5382+
}
53705383
}
53715384

53725385
LOG_TARGET_ERROR(target, "Unknown DCSR cause field: 0x%" PRIx64, get_field(dcsr, CSR_DCSR_CAUSE));
@@ -5462,7 +5475,7 @@ static int riscv013_on_step_or_resume(struct target *target, bool step)
54625475
if (execute_autofence(target) != ERROR_OK)
54635476
return ERROR_FAIL;
54645477

5465-
if (set_dcsr_ebreak(target, step) != ERROR_OK)
5478+
if (set_dcsr_config(target, step) != ERROR_OK)
54665479
return ERROR_FAIL;
54675480

54685481
if (riscv_reg_flush_all(target) != ERROR_OK)

src/target/riscv/riscv.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ static struct riscv_private_config *alloc_default_riscv_private_config(void)
486486
for (unsigned int i = 0; i < ARRAY_SIZE(config->dcsr_ebreak_fields); ++i)
487487
config->dcsr_ebreak_fields[i] = true;
488488

489+
config->dcsr_cetrig = true;
490+
489491
return config;
490492
}
491493

@@ -525,6 +527,15 @@ static struct jim_nvp nvp_ebreak_mode_opts[] = {
525527
{ .name = NULL, .value = RISCV_EBREAK_MODE_INVALID }
526528
};
527529

530+
531+
#define RISCV_CETRIG_INVALID -1
532+
533+
static struct jim_nvp nvp_cetrig_opts[] = {
534+
{ .name = "disable", .value = false },
535+
{ .name = "enable", .value = true },
536+
{ .name = NULL, .value = RISCV_CETRIG_INVALID }
537+
};
538+
528539
static int jim_configure_ebreak(struct riscv_private_config *config, struct jim_getopt_info *goi)
529540
{
530541
if (goi->argc == 0) {
@@ -611,13 +622,42 @@ static int jim_report_ebreak_config(const struct riscv_private_config *config,
611622
return JIM_OK;
612623
}
613624

625+
static int jim_configure_cetrig(struct riscv_private_config *config,
626+
struct jim_getopt_info *goi)
627+
{
628+
if (goi->argc == 0) {
629+
Jim_WrongNumArgs(goi->interp, 1, goi->argv - 1,
630+
"?disable|enable?");
631+
return JIM_ERR;
632+
}
633+
634+
struct jim_nvp *opt_nvp;
635+
if (jim_getopt_nvp(goi, nvp_cetrig_opts, &opt_nvp) != JIM_OK) {
636+
jim_getopt_nvp_unknown(goi, nvp_cetrig_opts, /*hadprefix*/ true);
637+
return JIM_ERR;
638+
}
639+
config->dcsr_cetrig = opt_nvp->value;
640+
return JIM_OK;
641+
}
642+
643+
static int jim_report_cetrig_config(const struct riscv_private_config *config,
644+
Jim_Interp *interp)
645+
{
646+
const char *cetrig_opt = jim_nvp_value2name_simple(nvp_cetrig_opts,
647+
config->dcsr_cetrig)->name;
648+
Jim_SetResultString(interp, cetrig_opt, strlen(cetrig_opt));
649+
return JIM_OK;
650+
}
651+
614652
enum riscv_cfg_opts {
615653
RISCV_CFG_EBREAK,
654+
RISCV_CFG_CETRIG,
616655
RISCV_CFG_INVALID = -1
617656
};
618657

619658
static struct jim_nvp nvp_config_opts[] = {
620659
{ .name = "-ebreak", .value = RISCV_CFG_EBREAK },
660+
{ .name = "-cetrig", .value = RISCV_CFG_CETRIG },
621661
{ .name = NULL, .value = RISCV_CFG_INVALID }
622662
};
623663

@@ -654,6 +694,10 @@ static int riscv_jim_configure(struct target *target,
654694
return goi->is_configure
655695
? jim_configure_ebreak(config, goi)
656696
: jim_report_ebreak_config(config, goi->interp);
697+
case RISCV_CFG_CETRIG:
698+
return goi->is_configure
699+
? jim_configure_cetrig(config, goi)
700+
: jim_report_cetrig_config(config, goi->interp);
657701
default:
658702
assert(false && "'jim_getopt_nvp' should have returned an error.");
659703
}
@@ -2617,6 +2661,7 @@ static int set_debug_reason(struct target *target, enum riscv_halt_reason halt_r
26172661
break;
26182662
case RISCV_HALT_INTERRUPT:
26192663
case RISCV_HALT_GROUP:
2664+
case RISCV_HALT_CRITICAL_ERROR:
26202665
target->debug_reason = DBG_REASON_DBGRQ;
26212666
break;
26222667
case RISCV_HALT_SINGLESTEP:

src/target/riscv/riscv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ enum riscv_halt_reason {
7575
RISCV_HALT_TRIGGER,
7676
RISCV_HALT_UNKNOWN,
7777
RISCV_HALT_GROUP,
78+
RISCV_HALT_CRITICAL_ERROR,
7879
RISCV_HALT_ERROR
7980
};
8081

@@ -378,6 +379,7 @@ enum riscv_priv_mode {
378379

379380
struct riscv_private_config {
380381
bool dcsr_ebreak_fields[N_RISCV_MODE];
382+
bool dcsr_cetrig;
381383
};
382384

383385
static inline struct riscv_private_config

0 commit comments

Comments
 (0)